<commit_before>'use strict';

const Node = require('./node');
const RegExpNode = require('./regexp');
const TokenNode = require('./token');
const SubNode = require('./sub');
const CollectorNode = require('./collector');
const CustomNode = require('./custom');

const Encounter = require('./encounter');

class Parser extends Node {
	constructor(language, options) {
		super();

		this.language = language;
		this.needsAll = (options && options.needsAll) || false;

		this.supportsPartial = false;
		this._skipPunctuation = false;
	}

	allowPartial() {
		this.supportsPartial = true;
		return this;
	}

	name(name) {
		this._name = this.language.id + ':' + name;
		return this;
	}

	skipPunctuation() {
		this._skipPunctuation = true;
		return this;
	}

	add(nodes, value) {
		if(! Array.isArray(nodes)) {
			nodes = [ nodes ];
		}

		let last = this;
		const push = node => {
			if(! (node instanceof Node)) {
				throw new Error('Not a node: ' + node);
			}

			/**
			 * Check if we can attach to an existing node or if we need to
			 * create a new branch.
			 */
			for(let i=0; i<last.outgoing.length; i++) {
				if(last.outgoing[i].equals(node)) {
					last = last.outgoing[i];
					mergeOutgoing(node);
					return;
				}
			}

			last.outgoing.push(node);
			last = node;

			// TODO: This needs to handle multiple nodes and multiple outgoing
			mergeOutgoing(last);
		};

		const mergeOutgoing = node => {
			// TODO: This needs to handle multiple nodes and multiple outgoing
			if(node.outgoing.length === 1) {
				push(node.outgoing[0]);
			} else if(node.outgoing.length > 1) {
				throw new Error('Too many outgoing nodes, branching is not supported yet');
			}
		};

		const createNode = n => {
			if(typeof n === 'function') {
				const result = n(this);
				push(result);
			} else if(n instanceof RegExp) {
				push(new RegExpNode(n));
			} else if(n instanceof Parser) {
				push(new SubNode(n));
			} else if(n instanceof Node) {
				push(n);
			} else if(typeof n === 'string') {
				push(this.parse(n));
			} else {
				throw new Error('Invalid node');
			}
		};

		nodes.forEach(createNode);

		push(new CollectorNode(nodes.length, value, this.needsAll));

		return this;
	}

	parse(text) {
		let first;
		let last;
		this.language.tokenize(text).forEach(t => {
			if(this._skipPunctuation && t.punctuation) {
				return;
			}

			const node = new TokenNode(this.language, t);
			if(last) {
				last.outgoing.push(node);
			} else {
				first = node;
			}
			last = node;
		});
		return first;
	}

	map(values, func) {
		Object.keys(values).forEach(k => this.add(k, func(values[k])));

		return this;
	}

	mapResults(mapper) {
		this._mapper = mapper;

		return this;
	}

	finalizer(func) {
		if(this._finalizer) {
			const previous = this._finalizer;
			this._finalizer = function(results, encounter) {
				return func(previous(results, encounter));
			}
		} else {
			this._finalizer = func;
		}
		return this;
	}

	onlyBest() {
		return this.finalizer((results, encounter) => {
			let best;
			for(let i=0; i<results.length; i++) {
				const result = results[i];
				if(! best || result.score > best.score) {
					best = result;
				}
			}

			let data = best ? best.data : null;
			if(data && this._mapper) {
				data = this._mapper(data, encounter);
			}
			return data;
		});
	}

	onlyLongest() {
		return this.finalizer((results, encounter) => {
			let best;
			for(let i=0; i<results.length; i++) {
				const result = results[i];
				if(! best || result.index > best.index) {
					best = result;
				}
			}

			let data = best ? best.data : null;
			if(data && this._mapper) {
				data = this._mapper(data, encounter);
			}
			return data;
		});
	}

	match(encounter, options) {
		if(typeof encounter === 'string') {
			encounter = new Encounter(this.language, encounter, options || {});
			encounter.outgoing = this.outgoing;

			if(this._skipPunctuation) {
				encounter.skipPunctuation = true;
			}
		}

		if(! encounter) {
			throw new Error('Nothing to match on');
		}

		let promise = encounter.next(0, 0);
		if(this._finalizer) {
			promise = promise.then(results => {
				return this._finalizer(results, encounter);
			});
		}

		return promise;
	}

	toString() {
		return 'Parser[]';
	}

	static result(validator) {
		return function(parser) {
			return new SubNode(parser.outgoing, validator);
		};
	}

	static custom(validator) {
		return function() {
			return new CustomNode(validator);
		};
	}
}

module.exports = Parser;
<commit_msg>Setting correct depth for values in Collector<commit_after>'use strict';

const Node = require('./node');
const RegExpNode = require('./regexp');
const TokenNode = require('./token');
const SubNode = require('./sub');
const CollectorNode = require('./collector');
const CustomNode = require('./custom');

const Encounter = require('./encounter');

class Parser extends Node {
	constructor(language, options) {
		super();

		this.language = language;
		this.needsAll = (options && options.needsAll) || false;

		this.supportsPartial = false;
		this._skipPunctuation = false;
	}

	allowPartial() {
		this.supportsPartial = true;
		return this;
	}

	name(name) {
		this._name = this.language.id + ':' + name;
		return this;
	}

	skipPunctuation() {
		this._skipPunctuation = true;
		return this;
	}

	add(nodes, value) {
		if(! Array.isArray(nodes)) {
			nodes = [ nodes ];
		}

		let values = 0;
		let last = this;
		const push = node => {
			if(! (node instanceof Node)) {
				throw new Error('Not a node: ' + node);
			}

			/**
			 * Check if we can attach to an existing node or if we need to
			 * create a new branch.
			 */
			for(let i=0; i<last.outgoing.length; i++) {
				if(last.outgoing[i].equals(node)) {
					last = last.outgoing[i];
					mergeOutgoing(node);
					return node;
				}
			}

			last.outgoing.push(node);
			last = node;

			// TODO: This needs to handle multiple nodes and multiple outgoing
			mergeOutgoing(last);

			return node;
		};

		const mergeOutgoing = node => {
			// TODO: This needs to handle multiple nodes and multiple outgoing
			if(node.outgoing.length === 1) {
				push(node.outgoing[0]);
			} else if(node.outgoing.length > 1) {
				throw new Error('Too many outgoing nodes, branching is not supported yet');
			}
		};

		const createNode = n => {
			if(typeof n === 'function') {
				const result = n(this);
				return push(result);
			} else if(n instanceof RegExp) {
				return push(new RegExpNode(n));
			} else if(n instanceof Parser) {
				return push(new SubNode(n));
			} else if(n instanceof Node) {
				return push(n);
			} else if(typeof n === 'string') {
				return push(this.parse(n));
			} else {
				throw new Error('Invalid node');
			}
		};

		nodes.forEach(n => {
			let r = createNode(n);
			if(r && ! (r instanceof TokenNode)) {
				values++;
			}
		});

		push(new CollectorNode(values, value, this.needsAll));

		return this;
	}

	parse(text) {
		let first;
		let last;
		this.language.tokenize(text).forEach(t => {
			if(this._skipPunctuation && t.punctuation) {
				return;
			}

			const node = new TokenNode(this.language, t);
			if(last) {
				last.outgoing.push(node);
			} else {
				first = node;
			}
			last = node;
		});
		return first;
	}

	map(values, func) {
		Object.keys(values).forEach(k => this.add(k, func(values[k])));

		return this;
	}

	mapResults(mapper) {
		this._mapper = mapper;

		return this;
	}

	finalizer(func) {
		if(this._finalizer) {
			const previous = this._finalizer;
			this._finalizer = function(results, encounter) {
				return func(previous(results, encounter));
			}
		} else {
			this._finalizer = func;
		}
		return this;
	}

	onlyBest() {
		return this.finalizer((results, encounter) => {
			let best;
			for(let i=0; i<results.length; i++) {
				const result = results[i];
				if(! best || result.score > best.score) {
					best = result;
				}
			}

			let data = best ? best.data : null;
			if(data && this._mapper) {
				data = this._mapper(data, encounter);
			}
			return data;
		});
	}

	onlyLongest() {
		return this.finalizer((results, encounter) => {
			let best;
			for(let i=0; i<results.length; i++) {
				const result = results[i];
				if(! best || result.index > best.index) {
					best = result;
				}
			}

			let data = best ? best.data : null;
			if(data && this._mapper) {
				data = this._mapper(data, encounter);
			}
			return data;
		});
	}

	match(encounter, options) {
		if(typeof encounter === 'string') {
			encounter = new Encounter(this.language, encounter, options || {});
			encounter.outgoing = this.outgoing;

			if(this._skipPunctuation) {
				encounter.skipPunctuation = true;
			}
		}

		if(! encounter) {
			throw new Error('Nothing to match on');
		}

		let promise = encounter.next(0, 0);
		if(this._finalizer) {
			promise = promise.then(results => {
				return this._finalizer(results, encounter);
			});
		}

		return promise;
	}

	toString() {
		return 'Parser[]';
	}

	static result(node, validator) {
		if(typeof validator === 'undefined') {
			validator = node;
			node = null;
		}

		return function(parser) {
			const sub = new SubNode(node ? node : parser.outgoing, validator);
			if(validator) {
				sub.name = (node ? node.name + ':' : '') + validator.name;
			}
			return sub;
		};
	}

	static custom(validator) {
		return function() {
			return new CustomNode(validator);
		};
	}
}

module.exports = Parser;
<|endoftext|>


<commit_before>/**
 * @file ListItem component
 * @author liangxiaojun(liangxiaojun@derbysoft.com)
 */

import React, {Component} from 'react';
import PropTypes from 'prop-types';

import Checkbox from '../Checkbox';
import Radio from '../Radio';
import CircularLoading from '../CircularLoading';
import TipProvider from '../TipProvider';
import TouchRipple from '../TouchRipple';
import Theme from '../Theme';

import Util from '../_vendors/Util';
import Position from '../_statics/Position';
import SelectMode from '../_statics/SelectMode';

export default class ListItem extends Component {

    constructor(props, ...restArgs) {

        super(props, ...restArgs);

        this.state = {
            checked: props.checked
        };

        this.checkboxChangeHandler = ::this.checkboxChangeHandler;
        this.radioChangeHandler = ::this.radioChangeHandler;
        this.touchTapHandler = ::this.touchTapHandler;

    }

    checkboxChangeHandler(checked) {
        this.setState({
            checked
        }, () => {

            const {onSelect, onDeselect} = this.props;

            if (checked) {
                onSelect && onSelect();
            } else {
                onDeselect && onDeselect();
            }

        });
    }

    radioChangeHandler() {

        const {checked} = this.state;

        if (!checked) {
            this.setState({
                checked: true
            }, () => {
                const {onSelect} = this.props;
                onSelect && onSelect();
            });
        }

    }

    touchTapHandler(e) {

        e.preventDefault();

        const {disabled, isLoading, readOnly} = this.props;

        if (disabled || isLoading || readOnly) {
            return;
        }

        const {onTouchTap} = this.props;
        onTouchTap && onTouchTap(e);

        switch (this.props.selectMode) {
            case SelectMode.MULTI_SELECT:
                this.checkboxChangeHandler(!this.state.checked);
                return;
            case SelectMode.SINGLE_SELECT:
                this.radioChangeHandler();
                return;
        }

    }

    componentWillReceiveProps(nextProps) {
        if (nextProps.checked !== this.state.checked) {
            this.setState({
                checked: nextProps.checked
            });
        }
    }

    render() {

        const {

                index, className, style, theme, data, text, desc, iconCls, rightIconCls, tip, tipPosition,
                disabled, isLoading, disableTouchRipple, rippleDisplayCenter, renderer, itemRenderer, readOnly,

                selectTheme, selectMode, radioUncheckedIconCls, radioCheckedIconCls,
                checkboxUncheckedIconCls, checkboxCheckedIconCls, checkboxIndeterminateIconCls,

                onMouseEnter, onMouseLeave

            } = this.props,
            {checked} = this.state,

            listItemClassName = (theme ? ` theme-${theme}` : '') + (checked ? ' activated' : '')
                + (className ? ' ' + className : ''),
            loadingIconPosition = (rightIconCls && !iconCls) ? 'right' : 'left';

        return (
            <TipProvider className='block'
                         text={tip}
                         tipPosition={tipPosition}>

                    {
                        selectMode === SelectMode.SINGLE_SELECT && (radioUncheckedIconCls || radioCheckedIconCls) ?
                            <Radio className="list-item-select"
                                   theme={selectTheme}
                                   checked={checked}
                                   disabled={disabled || isLoading}
                                   uncheckedIconCls={radioUncheckedIconCls}
                                   checkedIconCls={radioCheckedIconCls}
                                   disableTouchRipple={true}/>
                            :
                            null
                    }

                    {
                        selectMode === SelectMode.MULTI_SELECT ?
                            <Checkbox className="list-item-select"
                                      theme={selectTheme}
                                      checked={checked}
                                      disabled={disabled || isLoading}
                                      uncheckedIconCls={checkboxUncheckedIconCls}
                                      checkedIconCls={checkboxCheckedIconCls}
                                      indeterminateIconCls={checkboxIndeterminateIconCls}
                                      disableTouchRipple={true}/>
                            :
                            null
                    }

                    {
                        isLoading && loadingIconPosition === 'left' ?

                                <CircularLoading className="button-loading-icon"
                                                 size="small"/>

                            :
                            (
                                iconCls ?
                                    <i className={`button-icon button-icon-left ${iconCls}`}
                                       aria-hidden="true">
                                    :
                                    null
                            )
                    }

                    {
                        itemRenderer && typeof itemRenderer === 'function' ?
                            itemRenderer(data, index)
                            :
                            (
                                renderer && typeof renderer === 'function' ?
                                    renderer(data, index)
                                    :
                                    (
                                        desc ?

                                                    {text}

                                                    {desc}

                                            :
                                            text
                                    )
                            )
                    }

                    {
                        isLoading && loadingIconPosition === 'right' ?
                            <CircularLoading className="button-icon button-icon-right button-loading-icon"
                                             size="small"/>
                            :
                            (
                                rightIconCls ?
                                    <i className={`button-icon button-icon-right ${rightIconCls}`}
                                       aria-hidden="true">
                                    :
                                    null
                            )
                    }

                    {
                        disableTouchRipple || readOnly ?
                            null
                            :
                            <TouchRipple ref="touchRipple"
                                         className={disabled || isLoading ? 'hidden' : ''}
                                         displayCenter={rippleDisplayCenter}/>
                    }

            </TipProvider>
        );

    }
};

ListItem.propTypes = {

    index: PropTypes.number,

    className: PropTypes.string,
    style: PropTypes.object,
    theme: PropTypes.oneOf(Util.enumerateValue(Theme)),

    selectTheme: PropTypes.oneOf(Util.enumerateValue(Theme)),
    selectMode: PropTypes.oneOf(Util.enumerateValue(SelectMode)),

    data: PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.object]),
    value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
    text: PropTypes.any,
    desc: PropTypes.string,

    disabled: PropTypes.bool,
    isLoading: PropTypes.bool,
    disableTouchRipple: PropTypes.bool,
    rippleDisplayCenter: PropTypes.bool,
    checked: PropTypes.bool,
    readOnly: PropTypes.bool,

    iconCls: PropTypes.string,
    rightIconCls: PropTypes.string,

    tip: PropTypes.string,
    tipPosition: PropTypes.oneOf(Util.enumerateValue(Position)),

    radioUncheckedIconCls: PropTypes.string,
    radioCheckedIconCls: PropTypes.string,
    checkboxUncheckedIconCls: PropTypes.string,
    checkboxCheckedIconCls: PropTypes.string,
    checkboxIndeterminateIconCls: PropTypes.string,

    itemRenderer: PropTypes.func,
    renderer: PropTypes.func,

    onTouchTap: PropTypes.func,
    onSelect: PropTypes.func,
    onDeselect: PropTypes.func,
    onMouseEnter: PropTypes.func,
    onMouseLeave: PropTypes.func

};

ListItem.defaultProps = {

    index: 0,

    className: null,
    style: null,
    theme: Theme.DEFAULT,

    selectTheme: Theme.DEFAULT,
    selectMode: SelectMode.SINGLE_SELECT,

    data: null,
    value: null,
    text: null,
    desc: null,

    disabled: false,
    isLoading: false,
    disableTouchRipple: false,
    rippleDisplayCenter: false,
    checked: false,
    readOnly: false,

    iconCls: null,
    rightIconCls: null,

    tip: null,
    tipPosition: Position.BOTTOM,

    radioUncheckedIconCls: null,
    radioCheckedIconCls: null,
    checkboxUncheckedIconCls: 'fa fa-square-o',
    checkboxCheckedIconCls: 'fa fa-check-square',
    checkboxIndeterminateIconCls: 'fa fa-minus-square'

};<commit_msg>optimize ListItem<commit_after>/**
 * @file ListItem component
 * @author liangxiaojun(liangxiaojun@derbysoft.com)
 */

import React, {Component} from 'react';
import PropTypes from 'prop-types';

import Checkbox from '../Checkbox';
import Radio from '../Radio';
import CircularLoading from '../CircularLoading';
import TipProvider from '../TipProvider';
import TouchRipple from '../TouchRipple';
import Theme from '../Theme';

import Util from '../_vendors/Util';
import Position from '../_statics/Position';
import SelectMode from '../_statics/SelectMode';

export default class ListItem extends Component {

    static Theme = Theme;

    constructor(props, ...restArgs) {

        super(props, ...restArgs);

        this.state = {
            checked: props.checked
        };

        this.checkboxChangeHandler = ::this.checkboxChangeHandler;
        this.radioChangeHandler = ::this.radioChangeHandler;
        this.touchTapHandler = ::this.touchTapHandler;

    }

    checkboxChangeHandler(checked) {
        this.setState({
            checked
        }, () => {

            const {onSelect, onDeselect} = this.props;

            if (checked) {
                onSelect && onSelect();
            } else {
                onDeselect && onDeselect();
            }

        });
    }

    radioChangeHandler() {

        const {checked} = this.state;

        if (!checked) {
            this.setState({
                checked: true
            }, () => {
                const {onSelect} = this.props;
                onSelect && onSelect();
            });
        }

    }

    touchTapHandler(e) {

        e.preventDefault();

        const {disabled, isLoading, readOnly} = this.props;

        if (disabled || isLoading || readOnly) {
            return;
        }

        const {onTouchTap} = this.props;
        onTouchTap && onTouchTap(e);

        switch (this.props.selectMode) {
            case SelectMode.MULTI_SELECT:
                this.checkboxChangeHandler(!this.state.checked);
                return;
            case SelectMode.SINGLE_SELECT:
                this.radioChangeHandler();
                return;
        }

    }

    componentWillReceiveProps(nextProps) {
        if (nextProps.checked !== this.state.checked) {
            this.setState({
                checked: nextProps.checked
            });
        }
    }

    render() {

        const {

                index, className, style, theme, data, text, desc, iconCls, rightIconCls, tip, tipPosition,
                disabled, isLoading, disableTouchRipple, rippleDisplayCenter, renderer, itemRenderer, readOnly,

                selectTheme, selectMode, radioUncheckedIconCls, radioCheckedIconCls,
                checkboxUncheckedIconCls, checkboxCheckedIconCls, checkboxIndeterminateIconCls,

                onMouseEnter, onMouseLeave

            } = this.props,
            {checked} = this.state,

            listItemClassName = (theme ? ` theme-${theme}` : '') + (checked ? ' activated' : '')
                + (className ? ' ' + className : ''),
            loadingIconPosition = (rightIconCls && !iconCls) ? 'right' : 'left';

        return (
            <TipProvider className='block'
                         text={tip}
                         tipPosition={tipPosition}>

                    {
                        selectMode === SelectMode.SINGLE_SELECT && (radioUncheckedIconCls || radioCheckedIconCls) ?
                            <Radio className="list-item-select"
                                   theme={selectTheme}
                                   checked={checked}
                                   disabled={disabled || isLoading}
                                   uncheckedIconCls={radioUncheckedIconCls}
                                   checkedIconCls={radioCheckedIconCls}
                                   disableTouchRipple={true}/>
                            :
                            null
                    }

                    {
                        selectMode === SelectMode.MULTI_SELECT ?
                            <Checkbox className="list-item-select"
                                      theme={selectTheme}
                                      checked={checked}
                                      disabled={disabled || isLoading}
                                      uncheckedIconCls={checkboxUncheckedIconCls}
                                      checkedIconCls={checkboxCheckedIconCls}
                                      indeterminateIconCls={checkboxIndeterminateIconCls}
                                      disableTouchRipple={true}/>
                            :
                            null
                    }

                    {
                        isLoading && loadingIconPosition === 'left' ?

                                <CircularLoading className="button-loading-icon"
                                                 size="small"/>

                            :
                            (
                                iconCls ?
                                    <i className={`button-icon button-icon-left ${iconCls}`}
                                       aria-hidden="true">
                                    :
                                    null
                            )
                    }

                    {
                        itemRenderer && typeof itemRenderer === 'function' ?
                            itemRenderer(data, index)
                            :
                            (
                                renderer && typeof renderer === 'function' ?
                                    renderer(data, index)
                                    :
                                    (
                                        desc ?

                                                    {text}

                                                    {desc}

                                            :
                                            text
                                    )
                            )
                    }

                    {
                        isLoading && loadingIconPosition === 'right' ?
                            <CircularLoading className="button-icon button-icon-right button-loading-icon"
                                             size="small"/>
                            :
                            (
                                rightIconCls ?
                                    <i className={`button-icon button-icon-right ${rightIconCls}`}
                                       aria-hidden="true">
                                    :
                                    null
                            )
                    }

                    {
                        disableTouchRipple || readOnly ?
                            null
                            :
                            <TouchRipple ref="touchRipple"
                                         className={disabled || isLoading ? 'hidden' : ''}
                                         displayCenter={rippleDisplayCenter}/>
                    }

            </TipProvider>
        );

    }
};

ListItem.propTypes = {

    index: PropTypes.number,

    className: PropTypes.string,
    style: PropTypes.object,
    theme: PropTypes.oneOf(Util.enumerateValue(Theme)),

    selectTheme: PropTypes.oneOf(Util.enumerateValue(Theme)),
    selectMode: PropTypes.oneOf(Util.enumerateValue(SelectMode)),

    data: PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.object]),
    value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
    text: PropTypes.any,
    desc: PropTypes.string,

    disabled: PropTypes.bool,
    isLoading: PropTypes.bool,
    disableTouchRipple: PropTypes.bool,
    rippleDisplayCenter: PropTypes.bool,
    checked: PropTypes.bool,
    readOnly: PropTypes.bool,

    iconCls: PropTypes.string,
    rightIconCls: PropTypes.string,

    tip: PropTypes.string,
    tipPosition: PropTypes.oneOf(Util.enumerateValue(Position)),

    radioUncheckedIconCls: PropTypes.string,
    radioCheckedIconCls: PropTypes.string,
    checkboxUncheckedIconCls: PropTypes.string,
    checkboxCheckedIconCls: PropTypes.string,
    checkboxIndeterminateIconCls: PropTypes.string,

    itemRenderer: PropTypes.func,
    renderer: PropTypes.func,

    onTouchTap: PropTypes.func,
    onSelect: PropTypes.func,
    onDeselect: PropTypes.func,
    onMouseEnter: PropTypes.func,
    onMouseLeave: PropTypes.func

};

ListItem.defaultProps = {

    index: 0,

    className: null,
    style: null,
    theme: Theme.DEFAULT,

    selectTheme: Theme.DEFAULT,
    selectMode: SelectMode.SINGLE_SELECT,

    data: null,
    value: null,
    text: null,
    desc: null,

    disabled: false,
    isLoading: false,
    disableTouchRipple: false,
    rippleDisplayCenter: false,
    checked: false,
    readOnly: false,

    iconCls: null,
    rightIconCls: null,

    tip: null,
    tipPosition: Position.BOTTOM,

    radioUncheckedIconCls: null,
    radioCheckedIconCls: null,
    checkboxUncheckedIconCls: 'fa fa-square-o',
    checkboxCheckedIconCls: 'fa fa-check-square',
    checkboxIndeterminateIconCls: 'fa fa-minus-square'

};<|endoftext|>


<commit_before>/*! jQuery adapter for popo.js | http://github.com/niklasramo/popo.js | Copyright (c) 2012, 2013 Niklas Rämö | Released under the MIT license */
(function(a){a.fn.popo=function(c,b){if(c==="get"){return popo(this[0],c,b)}else{return this.each(function(){popo(this,c,b)})}}})(self.jQuery||self.Zepto);
<commit_msg>Updated copyright year<commit_after>/*! jQuery adapter for popo.js | http://github.com/niklasramo/popo.js | Copyright (c) 2012 Niklas Rämö | Released under the MIT license */
(function(a){a.fn.popo=function(c,b){if(c==="get"){return popo(this[0],c,b)}else{return this.each(function(){popo(this,c,b)})}}})(self.jQuery||self.Zepto);
<|endoftext|>


<commit_before>/*
    Agora Forum Software
    Copyright (C) 2016 Gregory Sartucci
    License: GPL, Check file LICENSE
*/

Router.onBeforeAction(function() {
    if (Meteor.user() && Meteor.user().isBanned) {
        return this.render('forbidden');
    } else {
        return this.next();
    }
});

Router.route('/admin', {
    name: 'Admin Screen',
    template: 'adminScreen'
});

Router.route('/user/:_id', function() {
    var id = this.params._id;

    if (this.ready()) {
        if (id) this.render('userProfile', {data: {id: id}});
        else this.render('errorPage', {data: {_id: id}});
    }
    //else this.render('expandedPostLoading');
});

Router.route('/users', {
    name: 'userList',
    template: 'userList'
});

Router.route('/forum', {

    onRun: function() {
        var id = this.params.query.post;

        if (this.ready()) {
            if (id) {
                this.state.set("postID", id);
            }
        }
        this.next();
    },
    action: function() {
        if (this.ready()) {
            this.render('mainView');
        } else this.render('errorPage', {data: {_id: id}});
    }
});

/*Router.route('/search/:_id', function() {
    var id = this.params._id;

    if (this.ready()) {
        var tag = Tags.findOne({_id: id});
        if (tag) this.render('search', {data: tag});
        else this.render('errorPage', {data: {_id: id}});
    }
});*/
<commit_msg>Added route for users to view their own profile.<commit_after>/*
    Agora Forum Software
    Copyright (C) 2016 Gregory Sartucci
    License: GPL, Check file LICENSE
*/

Router.onBeforeAction(function() {
    if (Meteor.user() && Meteor.user().isBanned) {
        return this.render('forbidden');
    } else {
        return this.next();
    }
});

Router.route('/admin', {
    name: 'Admin Screen',
    template: 'adminScreen'
});

Router.route('/user/:_id', function() {
    var id = this.params._id;

    if (!id) id = Meteor.userId();

    if (this.ready()) {
        if (id) this.render('userProfile', {data: {id: id}});
        else this.render('errorPage', {data: {_id: id}});
    }
});

Router.route('/user', function() {
    var id = Meteor.userId();

    if (this.ready()) {
        if (id) this.render('userProfile', {data: {id: id}});
        else this.render('errorPage', {data: {_id: id}});
    }
});

Router.route('/users', {
    name: 'userList',
    template: 'userList'
});

Router.route('/forum', {

    onRun: function() {
        var id = this.params.query.post;

        if (this.ready()) {
            if (id) {
                this.state.set("postID", id);
            }
        }
        this.next();
    },
    action: function() {
        if (this.ready()) {
            this.render('mainView');
        } else this.render('errorPage', {data: {_id: id}});
    }
});

/*Router.route('/search/:_id', function() {
    var id = this.params._id;

    if (this.ready()) {
        var tag = Tags.findOne({_id: id});
        if (tag) this.render('search', {data: tag});
        else this.render('errorPage', {data: {_id: id}});
    }
});*/
<|endoftext|>


<commit_before>// ======================
// = jquery tips plugin =
// ======================
(function($) {
    $.tooltip = {defaults : {}};
    $.fn.tooltip = function(options) {
        var config = $.extend({
            tipTemplate: '_CONTENT_',
            spinner: '
Loading...
',
            delay: 150,
            position: 'right',
            width: 250,
            followMouse: true,
            popup: false,
            ajax: false,
            cache: true,
            ajaxOptions: {}
            }, $.tooltip.defaults, options);

        return this.each(function() {
            var $this = $(this);
            var $tip;
            var timer_in, timer_out;
            var tip_content, tip_title;
            var title = $this.attr('title');

            var showTooltip = function(){
                if (config.ajax && !$tip.hasClass('tooltip-loaded')) {
                    $.ajax($.extend({
                        url: $this.attr('href'),
                        type: 'GET',
                        data: {},
                        success: function(response) {
                            $tip.find('.tooltip-content').html(response);
                            $tip.find('.tooltip-closer').bind('click', hideTooltip);
                            if ( config.cache ) $tip.addClass('tooltip-loaded');
                        } }, config.ajaxOptions));
                }
                if (config.delay == 0) {
                    $tip.show();
                } else {
                    clearTimeout(timer_out);
                    timer_in = setTimeout(function() { $tip.show(); }, config.delay);
                }
            }

            var hideTooltip = function(){
                if (config.delay == 0) {
                    $tip.hide();
                } else {
                    clearTimeout(timer_in);
                    timer_out = setTimeout(function() { $tip.hide(); }, 100);
                }
            }

            if ($this.next('.tooltip-box').length == 0) $this.after('

');

            if (config.ajax) {
                tip_content = config.spinner;
            } else if (title && title != '') {
                title = title.split('|');
                if (title.length > 1) {
                    tip_title = title[0];
                    tip_content = title[1];
                } else {
                    tip_content = title[0];
                }
            } else {
                tip_content = $this.next('.tooltip-box').html();
            }

            $tip = $this.next('.tooltip-box');

            if (($this.attr('rel') && $this.attr('rel').search('jquery-tipped') == -1) || !$this.attr('rel')) {
                $tip
                    .html(config.tipTemplate.replace(/_CONTENT_/, (tip_title ? '
' + tip_title + '
': '') + tip_content))
                    .css({ position: 'absolute' })
                    .css({width: config.width});
                $this
                    .removeAttr('title')
                    .attr('rel', 'jquery-tipped')

                if ( config.popup ) {
                    $this.bind('click', function(){
                      showTooltip();
                      return false;
                    });
                    $tip.find('.tooltip-closer').bind('click', hideTooltip);
                } else {
                  $this
                    .bind('mouseenter', showTooltip)
                    .bind('mouseleave', hideTooltip);
                }

                if ( config.followMouse && !config.popup ){
                    $this.bind('mousemove', function(e) {
                        $tip.css({
                            left: (config.position == 'left' ? e.pageX - 15 - config.width: e.pageX + 15),
                            top: e.pageY - 15
                        });
                    })
                }
            }
        });
    }
})(jQuery);

$j.tooltip.defaults = {
  tipTemplate: '
\

\

_CONTENT_

\

\

'
};
<commit_msg>typo fix<commit_after>// ======================
// = jquery tips plugin =
// ======================
(function($) {
    $.tooltip = {defaults : {}};
    $.fn.tooltip = function(options) {
        var config = $.extend({
            tipTemplate: '_CONTENT_',
            spinner: '
Loading...
',
            delay: 150,
            position: 'right',
            width: 250,
            followMouse: true,
            popup: false,
            ajax: false,
            cache: true,
            ajaxOptions: {}
            }, $.tooltip.defaults, options);

        return this.each(function() {
            var $this = $(this);
            var $tip;
            var timer_in, timer_out;
            var tip_content, tip_title;
            var title = $this.attr('title');

            var showTooltip = function(){
                if (config.ajax && !$tip.hasClass('tooltip-loaded')) {
                    $.ajax($.extend({
                        url: $this.attr('href'),
                        type: 'GET',
                        data: {},
                        success: function(response) {
                            $tip.find('.tooltip-content').html(response);
                            $tip.find('.tooltip-closer').bind('click', hideTooltip);
                            if ( config.cache ) $tip.addClass('tooltip-loaded');
                        } }, config.ajaxOptions));
                }
                if (config.delay == 0) {
                    $tip.show();
                } else {
                    clearTimeout(timer_out);
                    timer_in = setTimeout(function() { $tip.show(); }, config.delay);
                }
            }

            var hideTooltip = function(){
                if (config.delay == 0) {
                    $tip.hide();
                } else {
                    clearTimeout(timer_in);
                    timer_out = setTimeout(function() { $tip.hide(); }, 100);
                }
            }

            if ($this.next('.tooltip-box').length == 0) $this.after('

');

            if (config.ajax) {
                tip_content = config.spinner;
            } else if (title && title != '') {
                title = title.split('|');
                if (title.length > 1) {
                    tip_title = title[0];
                    tip_content = title[1];
                } else {
                    tip_content = title[0];
                }
            } else {
                tip_content = $this.next('.tooltip-box').html();
            }

            $tip = $this.next('.tooltip-box');

            if (($this.attr('rel') && $this.attr('rel').search('jquery-tipped') == -1) || !$this.attr('rel')) {
                $tip
                    .html(config.tipTemplate.replace(/_CONTENT_/, (tip_title ? '
' + tip_title + '
': '') + tip_content))
                    .css({ position: 'absolute' })
                    .css({width: config.width});
                $this
                    .removeAttr('title')
                    .attr('rel', 'jquery-tipped')

                if ( config.popup ) {
                    $this.bind('click', function(){
                      showTooltip();
                      return false;
                    });
                    $tip.find('.tooltip-closer').bind('click', hideTooltip);
                } else {
                  $this
                    .bind('mouseenter', showTooltip)
                    .bind('mouseleave', hideTooltip);
                }

                if ( config.followMouse && !config.popup ){
                    $this.bind('mousemove', function(e) {
                        $tip.css({
                            left: (config.position == 'left' ? e.pageX - 15 - config.width: e.pageX + 15),
                            top: e.pageY - 15
                        });
                    })
                }
            }
        });
    }
})(jQuery);

$.tooltip.defaults = {
  tipTemplate: '
\

\

_CONTENT_

\

\

'
};
<|endoftext|>


<commit_before>import React from 'react';

import { Strings } from '../../constants';

export default React.createClass({

  propTypes: {
    field       : React.PropTypes.string,
    onClick     : React.PropTypes.func,
    valueOn     : React.PropTypes.string,
    valueOff    : React.PropTypes.string,
    checked     : React.PropTypes.bool,
  },

  getDefaultProps () {
    return {
      valueOn   : "Ativo",
      valueOff  : "Desativado",
      checked   : false,
      onChange: function (event) { void event; },
    }
  },

  getInitialState () {
    return {
      valueOn: this.props.valueOn,
      valueOff: this.props.valueOff,
      value: this.props.checked,
    }
  },

  getText () {
    return this.refs[this.props.field].state.placeholder;
  },

  getValue () {
    const value = this.refs[this.props.field].state.checked;

    return value;
  },

  onChange (event) {
    this.setState({ value: event.target.checked });
    this.props.onChange(event);
  },

  render () {

    return (

          {this.props.valueOff}
          <input ref={this.props.field} checked={this.state.value} name={this.props.field} type="checkbox" onChange={this.onChange}/>

          {this.props.valueOn}

    );
  }

});
<commit_msg>Fix onChange propType in Switch component<commit_after>import React from 'react';

import { Strings } from '../../constants';

export default React.createClass({

  propTypes: {
    field       : React.PropTypes.string,
    onClick     : React.PropTypes.func,
    valueOn     : React.PropTypes.string,
    valueOff    : React.PropTypes.string,
    checked     : React.PropTypes.bool,
    onChange: React.PropTypes.func,
  },

  getDefaultProps () {
    return {
      valueOn   : "Ativo",
      valueOff  : "Desativado",
      checked   : false,
    }
  },

  getInitialState () {
    return {
      valueOn: this.props.valueOn,
      valueOff: this.props.valueOff,
      value: this.props.checked,
    }
  },

  getText () {
    return this.refs[this.props.field].state.placeholder;
  },

  getValue () {
    const value = this.refs[this.props.field].state.checked;

    return value;
  },

  onChange (event) {
    this.setState({ value: event.target.checked });

    if (this.props.onChange) {
      this.props.onChange(event.target.checked);
    }
  },

  render () {

    return (

          {this.props.valueOff}
          <input ref={this.props.field} checked={this.state.value} name={this.props.field} type="checkbox" onChange={this.onChange}/>

          {this.props.valueOn}

    );
  }

});
<|endoftext|>


<commit_before>import { notEmpty } from '@ember/object/computed';
import { assign } from '@ember/polyfills';
import Component from '@ember/component';

export default Component.extend({
  classNames: ['div'],

  hasInput: notEmpty('query'),
  hasFilters: true,
  helpText: null,
  filters: null,
  query: null,
  sort: null,
  queryParams: {},
  modelName: null,

  didReceiveAttrs() {
    this._super(...arguments);

    this.set('query', this.model.get('query.query'));
    this.set('sort', this.model.get('query.sort'));
    this.set('filters', this.model.get('query'));
  },

  search() {
    let params = assign(this.model.get('query'), { query: this.query, sort: this.sort });

    this.router.transitionTo({ queryParams: params });
  },

  actions: {
    doSearch(query) {
      if (query) {
        this.set('sort', 'relevance');
      } else if (this.sort === 'relevance') {
        this.set('sort', null);
      }

      this.set('query', query);
      this.search();
    },
    clear() {
      this.set('query', null);
      this.set('sort', null);
      this.search();
    },
    selectMetadata(metadata) {
      this.showMetadata(metadata);
    },
    sort(sort) {
      this.set('sort', sort);
      this.search();
    }
  },

  didInsertElement() {
    let placeholders = { 'doi': 'DOI',
                         'provider': 'Provider',
                         'client': 'Client',
                         'prefix': 'Prefix',
                         'client-prefix': 'Prefix',
                         'provider-prefix': 'Prefix' }

    this.set('modelName', placeholders[this.model.get("modelName")]);

    if (this.get("modelName") === "DOI") {
      this.set('formats', { '-created': 'Sort by Date Created', 'name': 'Sort by DOI', 'relevance': 'Sort by Relevance' });
    } else if (this.get("modelName") === "Prefix") {
      this.set('formats', { 'name': 'Sort by Prefix', '-created': 'Sort by Date Created' });
    } else {
      this.set('formats', { 'name': 'Sort by Name', '-created': 'Sort by Date Joined', 'relevance': 'Sort by Relevance' });
    }
  }
});
<commit_msg>enable doi sort by updated. datacite/datacite#674<commit_after>import { notEmpty } from '@ember/object/computed';
import { assign } from '@ember/polyfills';
import Component from '@ember/component';

export default Component.extend({
  classNames: ['div'],

  hasInput: notEmpty('query'),
  hasFilters: true,
  helpText: null,
  filters: null,
  query: null,
  sort: null,
  queryParams: {},
  modelName: null,

  didReceiveAttrs() {
    this._super(...arguments);

    this.set('query', this.model.get('query.query'));
    this.set('sort', this.model.get('query.sort'));
    this.set('filters', this.model.get('query'));
  },

  search() {
    let params = assign(this.model.get('query'), { query: this.query, sort: this.sort });

    this.router.transitionTo({ queryParams: params });
  },

  actions: {
    doSearch(query) {
      if (query) {
        this.set('sort', 'relevance');
      } else if (this.sort === 'relevance') {
        this.set('sort', null);
      }

      this.set('query', query);
      this.search();
    },
    clear() {
      this.set('query', null);
      this.set('sort', null);
      this.search();
    },
    selectMetadata(metadata) {
      this.showMetadata(metadata);
    },
    sort(sort) {
      this.set('sort', sort);
      this.search();
    }
  },

  didInsertElement() {
    let placeholders = { 'doi': 'DOI',
                         'provider': 'Provider',
                         'client': 'Client',
                         'prefix': 'Prefix',
                         'client-prefix': 'Prefix',
                         'provider-prefix': 'Prefix' }

    this.set('modelName', placeholders[this.model.get("modelName")]);

    if (this.get("modelName") === "DOI") {
      this.set('formats', { '-updated': 'Sort by Date Updated', '-created': 'Sort by Date Created', 'name': 'Sort by DOI', 'relevance': 'Sort by Relevance' });
    } else if (this.get("modelName") === "Prefix") {
      this.set('formats', { 'name': 'Sort by Prefix', '-created': 'Sort by Date Created' });
    } else {
      this.set('formats', { 'name': 'Sort by Name', '-created': 'Sort by Date Joined', 'relevance': 'Sort by Relevance' });
    }
  }
});
<|endoftext|>


<commit_before>var config = require('./config/config'),
    express = require('express'),
    models = require('./models'),
    passport = require('passport'),
    fixtures = require('./fixtures'),
    _ = require('underscore'),
    async = require('async'),
    stream = require('getstream');

var client = stream.connect(config.get('STREAM_API_KEY'),
                            config.get('STREAM_API_SECRET'),
                            config.get('STREAM_ID'));

var router = express.Router(),
    User = models.User,
    Item = models.Item,
    Pin = models.Pin,
    Follow = models.Follow;

var ensureAuthenticated = function(req, res, next){
    if (req.isAuthenticated())
        return next();
    res.redirect('/login');
};

var did_i_pin_it = function(all_items, pinned_items){
    var pinned_items_ids = _.pluck(pinned_items, 'item');

    _.each(all_items, function(item){
        if (pinned_items_ids.indexOf(item._id) >= 0){
            item.pinned = true;
        }
    });
};

var did_i_follow = function(all_users, followed_users){
    var followed_users_ids = _.pluck(followed_users, 'target');

    _.each(all_users, function(user){
        if (followed_users_ids.indexOf(user._id) >= 0){
            user.followed = true
        }
    });
};

router.use(function (error, req, res, next) {
  if (!error) {
    next();
  } else {
    console.error(error.stack);
    res.send(500);
  }
});

router.use(function(req, res, next){
    if (!req.isAuthenticated())
        return next();
    else if(!req.user.id)
        User.findOne({username: req.user.username}).lean().exec(function(err, user){
            if (err)
                return next(err);

            req.user.id = user._id;
            req.user.token = client.feed('notification', req.user.id).token;
            req.user.APP_ID = config.get('STREAM_ID');
            req.user.APP_KEY = config.get('STREAM_API_KEY');

            client.feed('notification', req.user.id).get({limit: 0}, function(err, response, body){
                req.user.unseen = body.unseen;

                next();
            });
        });
    else
        next();
});

router.get('/', function(req, res){
    Item.find({}).populate('user').lean().exec(function(err, popular){
        if (err)
            return next(err);

        if (req.isAuthenticated()){
            Pin.find({user: req.user.id}).select('item -_id').lean().exec(function(err, pinned_items){
                did_i_pin_it(popular, pinned_items);
                return res.render('trending', {location: 'trending', user: req.user, stuff: popular});
            });
        } else
            return res.render('trending', {location: 'trending', user: req.user, stuff: popular});
    });
});

var enrich = function(activities, callback){
    activities = activities.reverse();

    var separated = _.groupBy(activities, function(activity){
        return (activity.verb.localeCompare('pin') == 0);
    });

    var pin_activities = separated['true'];
    var follow_activities = separated['false'];

    async.parallel({
        enrichedPins: function(cb){
            Pin.enrich_activities(pin_activities, cb);
        },
        enrichedFollows: function(cb){
            Follow.enrich_activities(follow_activities, cb);
        }
    }, function(err, results){
        if (err)
            return next(err);

        var enrichedPins = results.enrichedPins,
            enrichedFollows = results.enrichedFollows;

        var results = [];

        var pin_index = 0;
        var follow_index = 0;
        for (var i = 0; i < activities.length; ++i){
            if (typeof enrichedPins[pin_index] !== 'undefined' && (activities[i].foreign_id.split(':')[0].localeCompare('pin')) == 0 &&
            (parseInt(activities[i].foreign_id.split(':')[1]) == enrichedPins[pin_index].foreign_id())){
                var pin = enrichedPins[pin_index].toJSON();
                pin.pin = true;
                results.push(pin);
                ++pin_index;
            } else if (enrichedFollows[follow_index] !== 'undefined' && ((activities[i].foreign_id.split(':')[0].localeCompare('follow')) == 0) &&
                (parseInt(activities[i].foreign_id.split(':')[1]) == enrichedFollows[follow_index].foreign_id())){
                var follow = enrichedFollows[follow_index].toJSON();
                follow.pin = false;
                results.push(follow);
                ++follow_index;
            }
        }

        callback(null, results);
    });
}

var enrich_aggregated_activities = function(activities, callback){
    var asyncStruct = {};

    _.each(activities, function(activity, index){
        asyncStruct[index] = function(cb){
            enrich(activity.activities, cb);
        }
    });

    var results = [];
    async.parallel(asyncStruct, function(err, enrichedActivities){
        _.each(enrichedActivities, function(activitiesArray, key){
            var pin = false;
            if (activitiesArray[0].pin)
                pin = true;

            results.push({objs: activitiesArray, 'pin': pin});
        });

        callback(results);
    });
}

router.get('/flat', ensureAuthenticated, function(req, res, next){
    var flatFeed = client.feed('flat', req.user.id);

    flatFeed.get({}, function(err, response, body){
        if (err)
            return next(err);

        var activities = response.body.results;
        enrich(activities, function(err, results){
            return res.render('feed', {location: 'feed', user: req.user, activities: results, path: req.url});
        });
    });
});

router.get('/aggregated_feed', ensureAuthenticated, function(req, res, next){
    var aggregatedFeed = client.feed('aggregated', req.user.id);

    aggregatedFeed.get({}, function(err, response, body){
        if (err)
            return next(err);

        var activities = response.body.results;
        enrich_aggregated_activities(activities, function(results){
            return res.render('aggregated_feed', {location: 'aggregated_feed', user: req.user, activities: results, path: req.url});
        });
    });
});

router.get('/notification_feed/', ensureAuthenticated, function(req, res){
    var notificationFeed = client.feed('notification', req.user.id);

    notificationFeed.get({mark_read:true, mark_seen: true}, function(err, response, body){
        if (err)
            return next(err);

        if (body.results.length == 0)
            return res.send('');
        else{
            req.user.unseen = 0;
            enrich(body.results[0].activities, function(err, results){
                return res.render('notification_follow', {lastFollower: results[0], count: results.length, layout: false});
            });
        }
    });
});

router.get('/people', ensureAuthenticated, function(req, res){
    User.find({}).nor([{'_id': 0}, {'_id': req.user.id}]).lean().exec(function(err, people){
        Follow.find({user: req.user.id}).exec(function(err, followedUsers){
            if (err)
                return next(err);

            did_i_follow(people, followedUsers);

            return res.render('people', {location: 'people', user: req.user, people: people, path: req.url, show_feed: false});
        });
    })
});

router.get('/profile', ensureAuthenticated, function(req, res, next){
    var userFeed = client.feed('user', req.user.id);

    userFeed.get({}, function(err, response, body){
        if (err)
            return next(err);

        var activities = response.body.results;
        enrich(activities, function(err, results){
            return res.render('profile', {location: 'profile', user: req.user, profile_user: req.user, activities: results, path: req.url, show_feed: true});
        })
    });
});

router.get('/profile/:user', ensureAuthenticated, function(req, res){
    User.findOne({username: req.params.user}, function(err, foundUser){
        if (err)
            return next(err);

        if (!foundUser)
            return res.send('User ' + req.params.user + ' not found.')

        var flatFeed = client.feed('user', foundUser._id);

        flatFeed.get({}, function(err, response, body){
            if (err)
                return next(err);

            var activities = response.body.results;
            enrich(activities, function(err, results){
                return res.render('profile', {location: 'profile', user: req.user, profile_user: foundUser, activities: results, path: req.url, show_feed: true});
            })
        });
    });
});

router.get('/account', ensureAuthenticated, function(req, res){
    res.render('account', {user: req.user});
});

router.get('/login', function(req, res){
    if (req.isAuthenticated())
        return res.redirect('/');

    res.render('login', {location: 'people', user: req.user});
});

router.get('/logout', function(req, res){
    req.logout();
    res.redirect('/');
});

router.get('/auth/github', passport.authenticate('github'));

router.get('/auth/github/callback',
    passport.authenticate('github', {failureRedirect: '/login'}),
    function(req, res) {
        User.findOne({username: req.user.username}, function(err, foundUser){
            if (!foundUser){
                User.create({username: req.user.username, avatar_url: req.user._json.avatar_url}, function(err, newUser){
                    if (err)
                        return next(err);

                    return res.redirect('/');
                });
            } else
                return res.redirect('/');
        });
    }
);

router.get('/fixtures', function(req, res){
    fixtures();

    res.send('fixtures ok');
});

router.post('/follow', ensureAuthenticated, function(req, res){
    var followData = {user: req.user.id, target: req.body.target};

    Follow.findOne(followData, function(err, foundFollow){
        if (!foundFollow)
            Follow.as_activity(followData);
        else
            foundFollow.remove_activity(req.user.id, req.body.target);

        res.set('Content-Type', 'application/json');
        return res.send({'pin': {'id': req.body.item}});
    });
});

router.post('/pin', ensureAuthenticated, function(req, res){
    var user = req.user.mongo_entry;
    var pinData = {user: req.user.id, item: req.body.item};

    Pin.findOne(pinData, function(err, foundPin){
        if (!foundPin)
            Pin.as_activity(pinData);
        else
            foundPin.remove_activity(user._id);

        res.set('Content-Type', 'application/json');
        return res.send({'pin': {'id': req.body.item}});
    });
});

module.exports = router;
<commit_msg>Fix indentation<commit_after>var config = require('./config/config'),
    express = require('express'),
    models = require('./models'),
    passport = require('passport'),
    fixtures = require('./fixtures'),
    _ = require('underscore'),
    async = require('async'),
    stream = require('getstream');

var client = stream.connect(config.get('STREAM_API_KEY'),
                            config.get('STREAM_API_SECRET'),
                            config.get('STREAM_ID'));

var router = express.Router(),
    User = models.User,
    Item = models.Item,
    Pin = models.Pin,
    Follow = models.Follow;

var ensureAuthenticated = function(req, res, next){
    if (req.isAuthenticated())
        return next();
    res.redirect('/login');
};

var did_i_pin_it = function(all_items, pinned_items){
    var pinned_items_ids = _.pluck(pinned_items, 'item');

    _.each(all_items, function(item){
        if (pinned_items_ids.indexOf(item._id) >= 0){
            item.pinned = true;
        }
    });
};

var did_i_follow = function(all_users, followed_users){
    var followed_users_ids = _.pluck(followed_users, 'target');

    _.each(all_users, function(user){
        if (followed_users_ids.indexOf(user._id) >= 0){
            user.followed = true
        }
    });
};

router.use(function (error, req, res, next) {
    if (!error) {
        next();
    } else {
        console.error(error.stack);
        res.send(500);
    }
});

router.use(function(req, res, next){
    if (!req.isAuthenticated())
        return next();
    else if(!req.user.id)
        User.findOne({username: req.user.username}).lean().exec(function(err, user){
            if (err)
                return next(err);

            req.user.id = user._id;
            req.user.token = client.feed('notification', req.user.id).token;
            req.user.APP_ID = config.get('STREAM_ID');
            req.user.APP_KEY = config.get('STREAM_API_KEY');

            client.feed('notification', req.user.id).get({limit: 0}, function(err, response, body){
                req.user.unseen = body.unseen;

                next();
            });
        });
    else
        next();
});

router.get('/', function(req, res){
    Item.find({}).populate('user').lean().exec(function(err, popular){
        if (err)
            return next(err);

        if (req.isAuthenticated()){
            Pin.find({user: req.user.id}).select('item -_id').lean().exec(function(err, pinned_items){
                did_i_pin_it(popular, pinned_items);
                return res.render('trending', {location: 'trending', user: req.user, stuff: popular});
            });
        } else
            return res.render('trending', {location: 'trending', user: req.user, stuff: popular});
    });
});

var enrich = function(activities, callback){
    activities = activities.reverse();

    var separated = _.groupBy(activities, function(activity){
        return (activity.verb.localeCompare('pin') == 0);
    });

    var pin_activities = separated['true'];
    var follow_activities = separated['false'];

    async.parallel({
        enrichedPins: function(cb){
            Pin.enrich_activities(pin_activities, cb);
        },
        enrichedFollows: function(cb){
            Follow.enrich_activities(follow_activities, cb);
        }
    }, function(err, results){
        if (err)
            return next(err);

        var enrichedPins = results.enrichedPins,
            enrichedFollows = results.enrichedFollows;

        var results = [];

        var pin_index = 0;
        var follow_index = 0;
        for (var i = 0; i < activities.length; ++i){
            if (typeof enrichedPins[pin_index] !== 'undefined' && (activities[i].foreign_id.split(':')[0].localeCompare('pin')) == 0 &&
            (parseInt(activities[i].foreign_id.split(':')[1]) == enrichedPins[pin_index].foreign_id())){
                var pin = enrichedPins[pin_index].toJSON();
                pin.pin = true;
                results.push(pin);
                ++pin_index;
            } else if (enrichedFollows[follow_index] !== 'undefined' && ((activities[i].foreign_id.split(':')[0].localeCompare('follow')) == 0) &&
                (parseInt(activities[i].foreign_id.split(':')[1]) == enrichedFollows[follow_index].foreign_id())){
                var follow = enrichedFollows[follow_index].toJSON();
                follow.pin = false;
                results.push(follow);
                ++follow_index;
            }
        }

        callback(null, results);
    });
}

var enrich_aggregated_activities = function(activities, callback){
    var asyncStruct = {};

    _.each(activities, function(activity, index){
        asyncStruct[index] = function(cb){
            enrich(activity.activities, cb);
        }
    });

    var results = [];
    async.parallel(asyncStruct, function(err, enrichedActivities){
        _.each(enrichedActivities, function(activitiesArray, key){
            var pin = false;
            if (activitiesArray[0].pin)
                pin = true;

            results.push({objs: activitiesArray, 'pin': pin});
        });

        callback(results);
    });
}

router.get('/flat', ensureAuthenticated, function(req, res, next){
    var flatFeed = client.feed('flat', req.user.id);

    flatFeed.get({}, function(err, response, body){
        if (err)
            return next(err);

        var activities = response.body.results;
        enrich(activities, function(err, results){
            return res.render('feed', {location: 'feed', user: req.user, activities: results, path: req.url});
        });
    });
});

router.get('/aggregated_feed', ensureAuthenticated, function(req, res, next){
    var aggregatedFeed = client.feed('aggregated', req.user.id);

    aggregatedFeed.get({}, function(err, response, body){
        if (err)
            return next(err);

        var activities = response.body.results;
        enrich_aggregated_activities(activities, function(results){
            return res.render('aggregated_feed', {location: 'aggregated_feed', user: req.user, activities: results, path: req.url});
        });
    });
});

router.get('/notification_feed/', ensureAuthenticated, function(req, res){
    var notificationFeed = client.feed('notification', req.user.id);

    notificationFeed.get({mark_read:true, mark_seen: true}, function(err, response, body){
        if (err)
            return next(err);

        if (body.results.length == 0)
            return res.send('');
        else{
            req.user.unseen = 0;
            enrich(body.results[0].activities, function(err, results){
                return res.render('notification_follow', {lastFollower: results[0], count: results.length, layout: false});
            });
        }
    });
});

router.get('/people', ensureAuthenticated, function(req, res){
    User.find({}).nor([{'_id': 0}, {'_id': req.user.id}]).lean().exec(function(err, people){
        Follow.find({user: req.user.id}).exec(function(err, followedUsers){
            if (err)
                return next(err);

            did_i_follow(people, followedUsers);

            return res.render('people', {location: 'people', user: req.user, people: people, path: req.url, show_feed: false});
        });
    })
});

router.get('/profile', ensureAuthenticated, function(req, res, next){
    var userFeed = client.feed('user', req.user.id);

    userFeed.get({}, function(err, response, body){
        if (err)
            return next(err);

        var activities = response.body.results;
        enrich(activities, function(err, results){
            return res.render('profile', {location: 'profile', user: req.user, profile_user: req.user, activities: results, path: req.url, show_feed: true});
        })
    });
});

router.get('/profile/:user', ensureAuthenticated, function(req, res){
    User.findOne({username: req.params.user}, function(err, foundUser){
        if (err)
            return next(err);

        if (!foundUser)
            return res.send('User ' + req.params.user + ' not found.')

        var flatFeed = client.feed('user', foundUser._id);

        flatFeed.get({}, function(err, response, body){
            if (err)
                return next(err);

            var activities = response.body.results;
            enrich(activities, function(err, results){
                return res.render('profile', {location: 'profile', user: req.user, profile_user: foundUser, activities: results, path: req.url, show_feed: true});
            })
        });
    });
});

router.get('/account', ensureAuthenticated, function(req, res){
    res.render('account', {user: req.user});
});

router.get('/login', function(req, res){
    if (req.isAuthenticated())
        return res.redirect('/');

    res.render('login', {location: 'people', user: req.user});
});

router.get('/logout', function(req, res){
    req.logout();
    res.redirect('/');
});

router.get('/auth/github', passport.authenticate('github'));

router.get('/auth/github/callback',
    passport.authenticate('github', {failureRedirect: '/login'}),
    function(req, res) {
        User.findOne({username: req.user.username}, function(err, foundUser){
            if (!foundUser){
                User.create({username: req.user.username, avatar_url: req.user._json.avatar_url}, function(err, newUser){
                    if (err)
                        return next(err);

                    return res.redirect('/');
                });
            } else
                return res.redirect('/');
        });
    }
);

router.get('/fixtures', function(req, res){
    fixtures();

    res.send('fixtures ok');
});

router.post('/follow', ensureAuthenticated, function(req, res){
    var followData = {user: req.user.id, target: req.body.target};

    Follow.findOne(followData, function(err, foundFollow){
        if (!foundFollow)
            Follow.as_activity(followData);
        else
            foundFollow.remove_activity(req.user.id, req.body.target);

        res.set('Content-Type', 'application/json');
        return res.send({'pin': {'id': req.body.item}});
    });
});

router.post('/pin', ensureAuthenticated, function(req, res){
    var user = req.user.mongo_entry;
    var pinData = {user: req.user.id, item: req.body.item};

    Pin.findOne(pinData, function(err, foundPin){
        if (!foundPin)
            Pin.as_activity(pinData);
        else
            foundPin.remove_activity(user._id);

        res.set('Content-Type', 'application/json');
        return res.send({'pin': {'id': req.body.item}});
    });
});

module.exports = router;
<|endoftext|>


<commit_before>import React, { Component, PropTypes } from 'react';
import { Modal } from 'react-bootstrap';
import RosterRacer from './Racer';
import RosterRace from './Race';
import style from './roster.css';

export default class Roster extends Component {
  static propTypes = {
    races: PropTypes.array.isRequired,
    addRace: PropTypes.func.isRequired,
    racers: PropTypes.array.isRequired,
    addRacer: PropTypes.func.isRequired,
    editRacer: PropTypes.func
  }

  constructor(props, context) {
    super(props, context);
    this.state = {
      search: '',
      previousSearch: '',
      newRacerName: '',
      selectedRacers: [],
      showModal: false
    };
  }

  handleSearch(e) {
    this.setState({ search: e.target.value });
  }

  handleRacerSelect(racer) {
    const { selectedRacers } = this.state;
    if (~selectedRacers.indexOf(racer.id)) {
      this.setState({
        selectedRacers: selectedRacers.filter((id) => id !== racer.id)
      });
    } else {
      this.setState({
        selectedRacers: [...selectedRacers, racer.id]
      });
    }
  }

  open() {
    const { search } = this.state;
    this.setState({
      newRacerName: search,
      previousSearch: search,
      search: '',
      showModal: true
    });
  }

  cancel() {
    this.setState({
      search: this.state.previousSearch,
      previousSearch: '',
      newRacerName: '',
      showModal: false
    });
  }

  render() {
    let input;
    const { search, selectedRacers } = this.state;
    const { races, addRace, racers, addRacer } = this.props;

    return (

          Roster

                Racers

                  <input
                    type="text"
                    className="form-control"
                    style={{
                      width: '80%'
                    }}
                    placeholder="Search for or create a new racer..."
                    autoFocus="true"
                    value={this.state.search}
                    onChange={this.handleSearch.bind(this)}
                  />
                  <i
                    className={`material-icons md-36 unselectable ${style.addRacerBtn}`}
                    tabIndex="0"
                    onClick={() => { this.open(); }}
                    onKeyDown={(e) => {
                      if (e.keyCode === 13) {
                        this.open();
                      }
                    }}
                  >
                    add_box

              {racers.filter((racer) => {
                if (search && search && search.trim()) {
                  return ~racer.name.toLowerCase().indexOf(search.trim().toLowerCase());
                }
                return true;
              }).map((racer) => (
                <RosterRacer
                  key={`racer-${racer.id}`}
                  racer={racer}
                  selected={(selectedRacers.indexOf(racer.id) > -1)}
                  onClick={() => this.handleRacerSelect(racer)}
                />
              ))}

              Name
              <input
                ref={node => {
                  input = node;
                }}
                type="text"
              />

            <button
              className="btn btn-default"
              onClick={() => {
                if (input.value.trim().length > 0) {
                  addRacer({ name: input.value.trim() });
                  input.value = '';
                }
              }}
            >
              Add Racer
            </button>

            Race Setup

              <button
                className={`btn btn-default${(selectedRacers.length > 0 ? '' : ' disabled')}`}
                onClick={() => {
                  if (selectedRacers.length > 0) {
                    addRace(selectedRacers);
                    this.setState({
                      selectedRacers: []
                    });
                  }
                }}
              >
                Add Race with selected Racers
              </button>

                {races.map((race) => (
                  <RosterRace
                    key={`race-${race.id}`}
                    race={race}
                    racers={race.racers.map(
                      (racerId) => racers.find((racer) => racer.id === racerId)
                    )}
                  />
                ))}

    );
  }
}
<commit_msg>Adding working create racer Modal<commit_after>import React, { Component, PropTypes } from 'react';
import { Modal } from 'react-bootstrap';
import RosterRacer from './Racer';
import RosterRace from './Race';
import style from './roster.css';

export default class Roster extends Component {
  static propTypes = {
    races: PropTypes.array.isRequired,
    addRace: PropTypes.func.isRequired,
    racers: PropTypes.array.isRequired,
    addRacer: PropTypes.func.isRequired,
    editRacer: PropTypes.func
  }

  constructor(props, context) {
    super(props, context);
    this.state = {
      search: '',
      previousSearch: '',
      newRacerName: '',
      selectedRacers: [],
      showModal: false
    };
  }

  handleSearch(e) {
    this.setState({ search: e.target.value });
  }

  handleRacerSelect(racer) {
    const { selectedRacers } = this.state;
    if (~selectedRacers.indexOf(racer.id)) {
      this.setState({
        selectedRacers: selectedRacers.filter((id) => id !== racer.id)
      });
    } else {
      this.setState({
        selectedRacers: [...selectedRacers, racer.id]
      });
    }
  }

  open() {
    const { search } = this.state;
    this.setState({
      newRacerName: search,
      previousSearch: search,
      search: '',
      showModal: true
    });
  }

  cancel() {
    this.setState({
      search: this.state.previousSearch,
      previousSearch: '',
      newRacerName: '',
      showModal: false
    });
  }

  render() {
    let input;
    const { search, selectedRacers } = this.state;
    const { races, addRace, racers, addRacer } = this.props;

    return (

          Roster

                Racers

                  <input
                    type="text"
                    className="form-control"
                    style={{
                      width: '80%'
                    }}
                    placeholder="Search for or create a new racer..."
                    autoFocus="true"
                    value={this.state.search}
                    onChange={this.handleSearch.bind(this)}
                  />
                  <i
                    className={`material-icons md-36 unselectable ${style.addRacerBtn}`}
                    tabIndex="0"
                    onClick={() => { this.open(); }}
                    onKeyDown={(e) => {
                      if (e.keyCode === 13) {
                        this.open();
                      }
                    }}
                  >
                    add_box

              {racers.filter((racer) => {
                if (search && search && search.trim()) {
                  return ~racer.name.toLowerCase().indexOf(search.trim().toLowerCase());
                }
                return true;
              }).map((racer) => (
                <RosterRacer
                  key={`racer-${racer.id}`}
                  racer={racer}
                  selected={(selectedRacers.indexOf(racer.id) > -1)}
                  onClick={() => this.handleRacerSelect(racer)}
                />
              ))}

            Race Setup

              <button
                className={`btn btn-default${(selectedRacers.length > 0 ? '' : ' disabled')}`}
                onClick={() => {
                  if (selectedRacers.length > 0) {
                    addRace(selectedRacers);
                    this.setState({
                      selectedRacers: []
                    });
                  }
                }}
              >
                Add Race with selected Racers
              </button>

                {races.map((race) => (
                  <RosterRace
                    key={`race-${race.id}`}
                    race={race}
                    racers={race.racers.map(
                      (racerId) => racers.find((racer) => racer.id === racerId)
                    )}
                  />
                ))}

        <Modal
          show={this.state.showModal}
          onHide={() => { this.cancel(); }}
          animation={false}
        >
          <Modal.Header closeButton>
            <Modal.Title>Add Racer</Modal.Title>
          </Modal.Header>
          <Modal.Body>

              Name
              <input
                className="form-control"
                type="text"
                id="newRacerName"
                value={this.state.newRacerName}
                onChange={(e) => {
                  this.setState({ newRacerName: e.target.value });
                }}
              />

          </Modal.Body>
          <Modal.Footer>
            <button
              className="btn btn-default"
              onClick={() => { this.cancel(); }}
            >
              Cancel
            </button>
            <button
              className="btn btn-primary"
              onClick={() => {
                const { newRacerName } = this.state;
                if (newRacerName.trim().length > 0) {
                  addRacer({ name: newRacerName.trim() });
                  this.setState({
                    search: '',
                    previousSearch: '',
                    newRacerName: '',
                    showModal: false
                  });
                }
              }}
            >
              Save
            </button>
          </Modal.Footer>
        </Modal>

    );
  }
}
<|endoftext|>


<commit_before>var passport = require('passport');

module.exports = function( app ) {
    var injector = app.get('injector');

    injector.inject( function ( ExampleController, UserController, MongoController, AccountController, RoleController, PermissionController ) {
        app.all('/example/:action/:id?', ExampleController.attach());
        app.all('/example/?:action?', ExampleController.attach());

        app.all('/mongo/:action/:id?', MongoController.attach());
        app.all('/mongo/?:action?', MongoController.attach());

        // Some passport use
        // app.get('/auth/facebook', passport.authenticate('facebook', {
        //     scope: ['email', 'user_location', 'user_photos']
        // }));
        // app.get('/auth/facebook/callback', UserController.attach('facebookLoginAction'));

        app.get('/user/current', UserController.attach());
        app.post('/user/login', UserController.attach());
        app.post('/user', UserController.attach());
        app.all('/user/:action/:id?', UserController.requiresLogin, UserController.attach());
        app.all('/user/?:action?', UserController.requiresLogin, UserController.attach());
    });
};
<commit_msg>hotfix(routes): Don't include MongoController by default<commit_after>var passport = require('passport');

module.exports = function( app ) {
    var injector = app.get('injector');

    injector.inject( function ( ExampleController, UserController, /* MongoController, */ AccountController, RoleController, PermissionController ) {
        app.all('/example/:action/:id?', ExampleController.attach());
        app.all('/example/?:action?', ExampleController.attach());

        // app.all('/mongo/:action/:id?', MongoController.attach());
        // app.all('/mongo/?:action?', MongoController.attach());

        // Some passport use
        // app.get('/auth/facebook', passport.authenticate('facebook', {
        //     scope: ['email', 'user_location', 'user_photos']
        // }));
        // app.get('/auth/facebook/callback', UserController.attach('facebookLoginAction'));

        app.get('/user/current', UserController.attach());
        app.post('/user/login', UserController.attach());
        app.post('/user', UserController.attach());
        app.all('/user/:action/:id?', UserController.requiresLogin, UserController.attach());
        app.all('/user/?:action?', UserController.requiresLogin, UserController.attach());
    });
};
<|endoftext|>


<commit_before>import Ember from 'ember';
import moment from 'moment';

export default Ember.Component.extend({

  // Whenever our stream is mutated
  // (that is, when a new value arrives)
  formattedSeries: Ember.observer('property.stream.@each', function() {
    // Go fetch the whole observation stream
    const observations = this.get('property.stream');
    if (observations.length === 0) {
      this.set('series', null);
      return;
    }

    // Translate to Highcharts format
    const series = observations.map( ({datetime, value}) => {
      if (typeof value === 'number') {
        // Round to 3 decimal places.
        // And pray to the IEEE gods for no weird floating point shit.
        value = Math.round(value*1000)/1000;
      }
      return [moment(datetime).valueOf(), value];
    });
    // Throw it into Highcharts.
    // Be sure to transform to JS Array from Ember Array
    // so that Highcharts doesn't get confused.
    const vType = this.get('viewType');
    const tooltipName = vType === 'live' ? 'Value' : 'Average Over Hour';

    this.set('series', [{
      showInLegend: false,
      data: series,
      name: tooltipName
    }]);
  }),

  chartOptions: Ember.computed('property', function() {
    const viewType = this.get('viewType');
    const prop = this.get('property');
    const liveConfig = {
      chart: {
        type: 'line',
      },
      title: {
        text: prop.name
      },
      xAxis: {
        type: 'datetime',
        dateTimeLabelFormats: { // don't display the dummy year
          second: '%l:%M:%S',
          year: '%b'
        },
        labels: {
          enabled: true,
        }
      },
      tooltip: {
        valueSuffix: ' ' + prop.unit,
        dateTimeLabelFormats: {
          millisecond: '%l:%M:%S %p - %b %e, %Y',
          second: '%l:%M:%S %p - %b %e, %Y',
          minute: '%l:%M:%S %p - %b %e, %Y',
          hour: '%l:%M:%S %p - %b %e, %Y',
          day: '%l:%M:%S %p - %b %e, %Y',
          week: '%l:%M:%S %p - %b %e, %Y',
          month: '%l:%M:%S %p - %b %e, %Y',
          year: '%l:%M:%S %p - %b %e, %Y'
        }
      },
      yAxis: {
        title: {
          text: prop.unit
        }
      },
      legend: {
        enabled: false
      },
      plotOptions: {
      }
    };
    if (viewType === 'history') {
      // Day-long intervals
      liveConfig.xAxis.tickInterval = 86400000;
      liveConfig.tooltip.dateTimeLabelFormats.hour = '%l %p - %b %e, %Y';
    }
    return liveConfig;

  })
});
<commit_msg>Fix X axis on history<commit_after>import Ember from 'ember';
import moment from 'moment';

export default Ember.Component.extend({

  // Whenever our stream is mutated
  // (that is, when a new value arrives)
  formattedSeries: Ember.observer('property.stream.@each', function() {
    // Go fetch the whole observation stream
    const observations = this.get('property.stream');
    if (observations.length === 0) {
      this.set('series', null);
      return;
    }

    // Translate to Highcharts format
    const series = observations.map( ({datetime, value}) => {
      if (typeof value === 'number') {
        // Round to 3 decimal places.
        // And pray to the IEEE gods for no weird floating point shit.
        value = Math.round(value*1000)/1000;
      }
      return [moment(datetime).valueOf(), value];
    });
    // Throw it into Highcharts.
    // Be sure to transform to JS Array from Ember Array
    // so that Highcharts doesn't get confused.
    const vType = this.get('viewType');
    const tooltipName = vType === 'live' ? 'Value' : 'Average Over Hour';

    this.set('series', [{
      showInLegend: false,
      data: series,
      name: tooltipName
    }]);
  }),

  chartOptions: Ember.computed('property', function() {
    const viewType = this.get('viewType');
    const prop = this.get('property');
    const liveConfig = {
      chart: {
        type: 'line',
      },
      title: {
        text: prop.name
      },
      xAxis: {
        type: 'datetime',
        dateTimeLabelFormats: { // don't display the dummy year
          second: '%l:%M:%S',
          year: '%b'
        },
        labels: {
          enabled: true,
        }
      },
      tooltip: {
        valueSuffix: ' ' + prop.unit,
        dateTimeLabelFormats: {
          millisecond: '%l:%M:%S %p - %b %e, %Y',
          second: '%l:%M:%S %p - %b %e, %Y',
          minute: '%l:%M:%S %p - %b %e, %Y',
          hour: '%l:%M:%S %p - %b %e, %Y',
          day: '%l:%M:%S %p - %b %e, %Y',
          week: '%l:%M:%S %p - %b %e, %Y',
          month: '%l:%M:%S %p - %b %e, %Y',
          year: '%l:%M:%S %p - %b %e, %Y'
        }
      },
      yAxis: {
        title: {
          text: prop.unit
        }
      },
      legend: {
        enabled: false
      },
      plotOptions: {
      }
    };
    if (viewType === 'history') {
      // Day-long intervals
      const aDay = 86400000;
      liveConfig.xAxis.tickInterval = aDay;
      liveConfig.xAxis.minRange = aDay * 7;
      liveConfig.xAxis.max = moment().valueOf();
      liveConfig.tooltip.dateTimeLabelFormats.hour = '%l %p - %b %e, %Y';
    }
    return liveConfig;

  })
});
<|endoftext|>


<commit_before>var deadline = 0, retry_interval = 0;
var ti;

function insert(parent, child) {
  var existing = parent.children();
  var before = null;
  existing.each(function () {
    var jq = $(this);
    if (jq.attr('name') < child.attr('name')) {
      before = jq;
    }
  });
  if (before === null) {
    parent.prepend(child);
  } else {
    before.after(child);
  }
}

function apply(ev) {
  var parts = ev.Path.split("/")
  if (parts.length < 2) {
    return
  }
  parts = parts.slice(1); // omit leading empty string
  var dir_parts = parts.slice(0, parts.length - 1);
  var dir = $('#root');
  for (var i = 0; i < dir_parts.length; i++) {
    var part = dir_parts[i];
    var next = dir.find('div[name="'+part+'"] > dd');
    if (next.length < 1) {
      var div = $('
').attr('name', part);
      var dd = $('
');
      div.append($('
').text(part+'/')).append(dd);
      insert(dir.children('dl'), div);
      dd.append('
').append('

');
      next = dd;
    }
    dir = next;
  }

  var basename = parts[parts.length - 1];
  var entry = dir.find('tr[name="'+basename+'"]');
  if (entry.length < 1) {
    var tr = $('
').attr('name', basename);
    insert(dir.children('table').children('tbody'), tr);
    tr.append($('').text(basename)).
      append('').
      append('').
      append('');
    entry = tr;
  }
  entry.children('td.cas').text('('+ev.Cas+')');
  entry.children('td.body').text(ev.Body);
  entry.addClass('new');

  // Kick off the transition in a bit.
  setTimeout(function() { entry.removeClass('new') }, 550);
}

function time_interval(s) {
  if (s < 120) return Math.ceil(s) + 's';
  if (s < 7200) return Math.round(s/60) + 'm';
  return Math.round(s/3600) + 'h';
}

function countdown() {
  var body = $('body');
  var eta = (deadline - new Date().getTime())/1000;
  if (eta < 0) {
    body.removeClass('waiting');
    open();
  } else {
    $('#retrymsg').text("retrying in " + time_interval(eta));
    body.addClass('waiting');
    ti = setTimeout(countdown, Math.max(100, eta*9));
  }
}

function retry() {
  deadline = ((new Date()).getTime()) + retry_interval * 1000;
  retry_interval += (retry_interval + 5) * (Math.random() + .5);
  countdown();
}

function open() {
  var body = $('body');
  var status = $('#status');
  status.text("connecting");
  var ws = new WebSocket("ws://"+location.host+"/events"+path);
  ws.onmessage = function (ev) {
    var jev = JSON.parse(ev.data);
    apply(jev);
  };
  ws.onopen = function(ev) {
    if (retry_interval > 0) {
      body.addClass('wereback');
      setTimeout(function () { body.removeClass('wereback') }, 8000);
    }
    retry_interval = 0;
    status.text('open')
    body.addClass('open').removeClass('loading closed error');
    $('#root > dl > *, #root > table > tbody > *').remove();
  };
  ws.onclose = function(ev) {
    status.text('closed')
    body.addClass('closed').removeClass('loading open error wereback');
    retry();
  };
  ws.onerror = function(ev) {
    status.text('error ' + ev)
    body.addClass('error').removeClass('loading open closed wereback');
    retry();
  };
}

function dr() {
  $('#trynow').click(function() {
    clearTimeout(ti);
    deadline = 0;
    countdown();
  });

  if ("WebSocket" in window) {
    open();
  } else {
    $('#status').text("no websockets");
    $('body').addClass('error nows').removeClass('loading open closed wereback');
  }
}

function jerr() {
  const m = 'could not load jquery (is your network link down?)';
  document.getElementById('status').innerText = m;
  document.getElementsByTagName('body')[0].className = 'error';
}
<commit_msg>web: display the event path exactly<commit_after>var deadline = 0, retry_interval = 0;
var ti;

function insert(parent, child) {
  var existing = parent.children();
  var before = null;
  existing.each(function () {
    var jq = $(this);
    if (jq.attr('name') < child.attr('name')) {
      before = jq;
    }
  });
  if (before === null) {
    parent.prepend(child);
  } else {
    before.after(child);
  }
}

function apply(ev) {
  var parts = ev.Path.split("/")
  if (parts.length < 2) {
    return
  }
  parts = parts.slice(1); // omit leading empty string
  var dir_parts = parts.slice(0, parts.length - 1);
  var dir = $('#root');
  for (var i = 0; i < dir_parts.length; i++) {
    var part = dir_parts[i];
    var next = dir.find('> dl > div[name="'+part+'"] > dd');
    if (next.length < 1) {
      var div = $('
').attr('name', part);
      var dd = $('
');
      div.append($('
').text(part+'/')).append(dd);
      insert(dir.children('dl'), div);
      dd.append('
').append('

');
      next = dd;
    }
    dir = next;
  }

  var basename = parts[parts.length - 1];
  var entry = dir.find('tr[name="'+basename+'"]');
  if (entry.length < 1) {
    var tr = $('
').attr('name', basename);
    insert(dir.children('table').children('tbody'), tr);
    tr.append($('').text(basename)).
      append('').
      append('').
      append('');
    entry = tr;
  }
  entry.children('td.cas').text('('+ev.Cas+')');
  entry.children('td.body').text(ev.Body);
  entry.addClass('new');

  // Kick off the transition in a bit.
  setTimeout(function() { entry.removeClass('new') }, 550);
}

function time_interval(s) {
  if (s < 120) return Math.ceil(s) + 's';
  if (s < 7200) return Math.round(s/60) + 'm';
  return Math.round(s/3600) + 'h';
}

function countdown() {
  var body = $('body');
  var eta = (deadline - new Date().getTime())/1000;
  if (eta < 0) {
    body.removeClass('waiting');
    open();
  } else {
    $('#retrymsg').text("retrying in " + time_interval(eta));
    body.addClass('waiting');
    ti = setTimeout(countdown, Math.max(100, eta*9));
  }
}

function retry() {
  deadline = ((new Date()).getTime()) + retry_interval * 1000;
  retry_interval += (retry_interval + 5) * (Math.random() + .5);
  countdown();
}

function open() {
  var body = $('body');
  var status = $('#status');
  status.text("connecting");
  var ws = new WebSocket("ws://"+location.host+"/events"+path);
  ws.onmessage = function (ev) {
    var jev = JSON.parse(ev.data);
    apply(jev);
  };
  ws.onopen = function(ev) {
    if (retry_interval > 0) {
      body.addClass('wereback');
      setTimeout(function () { body.removeClass('wereback') }, 8000);
    }
    retry_interval = 0;
    status.text('open')
    body.addClass('open').removeClass('loading closed error');
    $('#root > dl > *, #root > table > tbody > *').remove();
  };
  ws.onclose = function(ev) {
    status.text('closed')
    body.addClass('closed').removeClass('loading open error wereback');
    retry();
  };
  ws.onerror = function(ev) {
    status.text('error ' + ev)
    body.addClass('error').removeClass('loading open closed wereback');
    retry();
  };
}

function dr() {
  $('#trynow').click(function() {
    clearTimeout(ti);
    deadline = 0;
    countdown();
  });

  if ("WebSocket" in window) {
    open();
  } else {
    $('#status').text("no websockets");
    $('body').addClass('error nows').removeClass('loading open closed wereback');
  }
}

function jerr() {
  const m = 'could not load jquery (is your network link down?)';
  document.getElementById('status').innerText = m;
  document.getElementsByTagName('body')[0].className = 'error';
}
<|endoftext|>