<commit_before>define([
    'uijet_dir/uijet',
    'modules/data/backbone',
    'underscore',
    'backbone-fetch-cache'
], function (uijet, Backbone, _) {

    uijet.use({
        prop: function (property) {
            return function (obj) {
                return obj[property];
            };
        }
    }, uijet.Utils);

    var
        reverseSorting = function (field) {
            return function (a, b) {
                var a_val = a.get(field),
                    b_val = b.get(field);
                return a_val < b_val ?
                    1 :
                    a_val > b_val ?
                        -1 :
                        0;
            };
        },
        /*
         * Muni (Entity) Model
         */
        Muni = uijet.Model({
            idAttribute : 'id'
        }),
        /*
         * Munis (Entities) Collection
         */
        Munis = uijet.Collection({
            model   : Muni,
            parse   : function (response) {
                //! Array.prototype.filter
                return response.results;
            }
        }),
        /*
         * TemplateNode Model
         */
        Node = uijet.Model({
            idAttribute : 'id'
        }),
        /*
         * TemplateNodes Collection
         */
        Nodes = uijet.Collection({
            model           : Node,
            comparator      : function (a, b) {
                var a_attrs = a.attributes,
                    b_attrs = b.attributes,
                    diff = a_attrs.level - b_attrs.level;
                if ( ! diff ) {
                    diff = a_attrs.code < b_attrs.code;
                    return diff ?
                        -1 :
                        a_attrs.code > b_attrs.code ?
                            1 :
                            0;
                }
                return diff > 0 ? 1 : -1;
            },
            /**
             * Setting `ancestors` array of `id`s, `leaf_node` boolean flag and
             * `level` - a Number representing the level of the node in the tree.
             *
             * @param {Object|Array} response
             * @returns {Object|Array} response
             */
            parse           : function (response) {
                var results = response.results,
                    last = results.length - 1,
                    paths_lookup = {},
                    parent_ids = {},
                    node, n, route, path;
                for ( n = last; node = results[n]; n-- ) {
                    node.ancestors = [];
                    paths_lookup[node.path] = node;
                    if ( node.parent ) {
                        node.parent = node.parent.id || node.parent;
                        if ( ! parent_ids[node.parent] ) {
                            parent_ids[node.parent] = [];
                        }
                        parent_ids[node.parent].push(node.id);
                    }
                }
                for ( n = last; node = results[n]; n-- ) {
                    if ( parent_ids[node.id] ) {
                        node.children = parent_ids[node.id];
                    }
                    else {
                        node.leaf_node = true;
                    }
                    route = node.path.split('|').slice(1);
                    node.level = route.length;
                    while ( route.length ) {
                        path = route.join('|');
                        if ( path in paths_lookup ) {
                            node.ancestors.push(paths_lookup[path].id);
                        }
                        route.shift();
                    }
                }
                paths_lookup = null;
                parent_ids = null;

                return results;
            },
            roots           : function () {
                return this.byParent(null);
            },
            byParent        : function (parent_id) {
                return this.where({
                    parent  : parent_id
                });
            },
            byAncestor      : function (ancestor_id) {
                if ( ancestor_id ) {
                    return this.filter(function (node) {
                        return ~ node.attributes.ancestors.indexOf(ancestor_id);
                    });
                }
                else {
                    return this.models;
                }
            },
            branch          : function (node_id) {
                var tip_node, branch;
                if ( node_id ) {
                    tip_node = this.get(node_id);
                    //! Array.prototype.map
                    branch = tip_node.get('ancestors')
                        .map( function (ancestor_id) {
                            return this.get(ancestor_id);
                        }, this )
                        .sort( function (a, b) {
                            return a.attributes.level - b.attributes.level;
                        } );
                    branch.push(tip_node);
                }
                return branch || [];
            }
        });

    return {
        Munis   : Munis,
        Node    : Node,
        Nodes   : Nodes,
        utils   : {
            reverseSorting  : reverseSorting
        }
    };
});
<commit_msg>Changed random ancestors setting with ordered setting by level<commit_after>define([
    'uijet_dir/uijet',
    'modules/data/backbone',
    'underscore',
    'backbone-fetch-cache'
], function (uijet, Backbone, _) {

    uijet.use({
        prop: function (property) {
            return function (obj) {
                return obj[property];
            };
        }
    }, uijet.Utils);

    var
        reverseSorting = function (field) {
            return function (a, b) {
                var a_val = a.get(field),
                    b_val = b.get(field);
                return a_val < b_val ?
                    1 :
                    a_val > b_val ?
                        -1 :
                        0;
            };
        },
        /*
         * Muni (Entity) Model
         */
        Muni = uijet.Model({
            idAttribute : 'id'
        }),
        /*
         * Munis (Entities) Collection
         */
        Munis = uijet.Collection({
            model   : Muni,
            parse   : function (response) {
                //! Array.prototype.filter
                return response.results;
            }
        }),
        /*
         * TemplateNode Model
         */
        Node = uijet.Model({
            idAttribute : 'id'
        }),
        /*
         * TemplateNodes Collection
         */
        Nodes = uijet.Collection({
            model           : Node,
            comparator      : function (a, b) {
                var a_attrs = a.attributes,
                    b_attrs = b.attributes,
                    diff = a_attrs.level - b_attrs.level;
                if ( ! diff ) {
                    diff = a_attrs.code < b_attrs.code;
                    return diff ?
                        -1 :
                        a_attrs.code > b_attrs.code ?
                            1 :
                            0;
                }
                return diff > 0 ? 1 : -1;
            },
            /**
             * Setting `ancestors` array of `id`s, `leaf_node` boolean flag and
             * `level` - a Number representing the level of the node in the tree.
             *
             * @param {Object|Array} response
             * @returns {Object|Array} response
             */
            parse           : function (response) {
                var results = response.results,
                    last = results.length - 1,
                    paths_lookup = {},
                    parent_ids = {},
                    node, n, route, path, ancestor;
                /*
                 * first loop
                 *
                 * init `ancestor` to `[]`
                 * create `paths_lookup` to look up nodes by `path`
                 * create `parent_ids` to look up child nodes by `parent` (by id later)
                 * set `level` by splitting `path` and checking its `length`
                 * set `parent` to the parent's id
                 */
                for ( n = last; node = results[n]; n-- ) {
                    node.ancestors = [];
                    node.level = node.path.split('|').length - 1;
                    paths_lookup[node.path] = node;
                    if ( node.parent ) {
                        node.parent = node.parent.id || node.parent;
                        if ( ! parent_ids[node.parent] ) {
                            parent_ids[node.parent] = [];
                        }
                        parent_ids[node.parent].push(node.id);
                    }
                }
                /*
                 * second loop
                 *
                 * set `children` to the array in `parent_ids` using `id`
                 * set `leaf_node` to `true` if `id` is not in `parent_ids`
                 * fill `ancestors` array by ancestor `id`s ordered by `level` as index
                 */
                for ( n = last; node = results[n]; n-- ) {
                    if ( parent_ids[node.id] ) {
                        node.children = parent_ids[node.id];
                    }
                    else {
                        node.leaf_node = true;
                    }
                    route = node.path.split('|').slice(1);
                    while ( route.length ) {
                        path = route.join('|');
                        if ( path in paths_lookup ) {
                            ancestor = paths_lookup[path];
                            node.ancestors[ancestor.level] = ancestor.id;
                        }
                        route.shift();
                    }
                }
                paths_lookup = null;
                parent_ids = null;

                return results;
            },
            roots           : function () {
                return this.byParent(null);
            },
            byParent        : function (parent_id) {
                return this.where({
                    parent  : parent_id
                });
            },
            byAncestor      : function (ancestor_id) {
                if ( ancestor_id ) {
                    return this.filter(function (node) {
                        return ~ node.attributes.ancestors.indexOf(ancestor_id);
                    });
                }
                else {
                    return this.models;
                }
            },
            branch          : function (node_id) {
                var tip_node, branch;
                if ( node_id ) {
                    tip_node = this.get(node_id);
                    //! Array.prototype.map
                    branch = tip_node.get('ancestors')
                        .map( function (ancestor_id) {
                            return this.get(ancestor_id);
                        }, this );
                    branch.push(tip_node);
                }
                return branch || [];
            }
        });

    return {
        Munis   : Munis,
        Node    : Node,
        Nodes   : Nodes,
        utils   : {
            reverseSorting  : reverseSorting
        }
    };
});
<|endoftext|>


<commit_before>"use strict";

const Promise = require("bluebird");
const { create: createSubject } = require("most-subject");

const StreamDSL = require("./StreamDSL.js");
const { Window } = require("../actions/index");
const { messageProduceHandle } = require("../messageProduceHandle.js");

const NOOP = () => { };

/**
 * change-log representation of a stream
 */
class KStream extends StreamDSL {

    /**
     * creates a changelog representation of a stream
     * join operations of kstream instances are synchronous
     * and return new instances immediately
     * @param {string} topicName
     * @param {KStorage} storage
     * @param {KafkaClient} kafka
     * @param {boolean} isClone
     */
    constructor(topicName, storage = null, kafka = null, isClone = false) {
        super(topicName, storage, kafka, isClone);

        this.started = false;

        //readability
        if (isClone) {
            this.started = true;
        }
    }

    /**
     * start kafka consumption
     * prepare production of messages if necessary
     * when called with zero or just a single callback argument
     * this function will return a promise and use the callback for errors
     * @param {function|Object} kafkaReadyCallback - can also be an object (config)
     * @param {function} kafkaErrorCallback
     * @param {boolean} withBackPressure
     * @param {Object} outputKafkaConfig
     */
    start(kafkaReadyCallback = null, kafkaErrorCallback = null, withBackPressure = false, outputKafkaConfig = null) {

        if (kafkaReadyCallback && typeof kafkaReadyCallback === "object" && arguments.length < 2) {
            return new Promise((resolve, reject) => {
                this._start(resolve, reject, kafkaReadyCallback.withBackPressure, kafkaReadyCallback.outputKafkaConfig);
            });
        }

        if (arguments.length < 2) {
            return new Promise((resolve, reject) => {
                this._start(resolve, reject, withBackPressure);
            });
        }

        return this._start(kafkaReadyCallback, kafkaErrorCallback, withBackPressure, outputKafkaConfig);
    }

    _start(kafkaReadyCallback = null, kafkaErrorCallback = null, withBackPressure = false, outputKafkaConfig = null) {

        if (this.started) {
            throw new Error("this KStream is already started.");
        }

        this.started = true;

        if (this.noTopicProvided && !this.produceAsTopic) {
            return kafkaReadyCallback();
        }

        let producerReady = false;
        let consumerReady = false;

        const onReady = (type) => {

            switch (type) {
                case "producer": producerReady = true; break;
                case "consumer": consumerReady = true; break;
            }

            //consumer && producer
            if (producerReady && consumerReady && kafkaReadyCallback) {
                kafkaReadyCallback();
            }

            //consumer only
            if (!this.produceAsTopic && consumerReady && kafkaReadyCallback) {
                kafkaReadyCallback();
            }

            //producer only
            if (this.produceAsTopic && producerReady && kafkaReadyCallback && !this.kafka.topic || !this.kafka.topic.length) {
                kafkaReadyCallback();
            }
        };

        //overwrite kafka topics
        this.kafka.overwriteTopics(this.topicName);

        this.kafka.on("message", msg => super.writeToStream(msg));
        this.kafka.start(() => { onReady("consumer"); }, kafkaErrorCallback || NOOP, this.produceAsTopic, withBackPressure);

        if (this.produceAsTopic) {

            this.kafka.setupProducer(this.outputTopicName, this.outputPartitionsCount, () => { onReady("producer"); },
                kafkaErrorCallback, outputKafkaConfig);

            super.forEach(message => {
                messageProduceHandle(
                    this.kafka,
                    message,
                    this.outputTopicName,
                    this.produceType,
                    this.produceCompressionType,
                    this.produceVersion,
                    kafkaErrorCallback
                );
            });

        }
    }

    /**
     * Emits an output when both input sources have records with the same key.
     * s1$:{object} + s2$:{object} -> j$:{left: s1$object, right: s2$object}
     * @param {StreamDSL} stream
     * @param {string} key
     * @param {boolean} windowed
     * @param {function} combine
     * @returns {KStream}
     */
    innerJoin(stream, key = "key", windowed = false, combine = null) {

        let join$ = null;
        if (!windowed) {
            join$ = this._innerJoinNoWindow(stream, key, combine);
        } else {
            throw new Error("not implemented yet."); //TODO implement
        }

        return this._cloneWith(join$);
    }

    _innerJoinNoWindow(stream, key, combine) {

        const existingKeyFilter = (event) => {
            return !!event && typeof event === "object" && typeof event[key] !== "undefined";
        };

        const melt = (left, right) => {
            return {
                left,
                right
            };
        };

        const parent$ = super.multicast().stream$.filter(existingKeyFilter);
        const side$ = stream.multicast().stream$.filter(existingKeyFilter);
        return parent$.zip(combine || melt, side$);
    }

    /**
     * Emits an output for each record in either input source.
     * If only one source contains a key, the other is null
     * @param {StreamDSL} stream
     */
    outerJoin(stream) {
        throw new Error("not implemented yet."); //TODO implement
    }

    /**
     * Emits an output for each record in the left or primary input source.
     * If the other source does not have a value for a given key, it is set to null
     * @param {StreamDSL} stream
     */
    leftJoin(stream) {
        throw new Error("not implemented yet."); //TODO implement
    }

    /**
     * Emits an output for each record in any of the streams.
     * Acts as simple merge of both streams.
     * can be used with KStream or KTable instances
     * returns a NEW KStream instance
     * @param {StreamDSL} stream
     * @returns {KStream}
     */
    merge(stream) {

        if (!(stream instanceof StreamDSL)) {
            throw new Error("stream has to be an instance of KStream or KTable.");
        }

        // multicast prevents replays
        // create a new internal stream that merges both KStream.stream$s
        const newStream$ = this.stream$.multicast().merge(stream.stream$.multicast());
        return this._cloneWith(newStream$);
    }

    _cloneWith(newStream$) {

        const kafkaStreams = this._kafkaStreams;
        if (!kafkaStreams) {
            throw new Error("merging requires a kafka streams reference on the left-hand merger.");
        }

        const newStorage = kafkaStreams.getStorage();
        const newKafkaClient = kafkaStreams.getKafkaClient();

        const newInstance = new KStream(null, newStorage, newKafkaClient, true);
        newInstance.replaceInternalObservable(newStream$);
        newInstance._kafkaStreams = kafkaStreams;

        return newInstance;
    }

    /**
     * creates a new KStream instance from a given most.js
     * stream; the consume topic will be empty and therefore
     * no consumer will be build
     * @param {Object} most.js stream
     * @returns {KStream}
     */
    fromMost(stream$) {
        return this._cloneWith(stream$);
    }

    /**
     * as only joins and window operations return new stream instances
     * you might need a clone sometimes, which can be accomplished
     * using this function
     * @returns {KStream}
     */
    clone() {
        return this._cloneWith(this.stream$.multicast());
    }

    /**
     * Splits a stream into multiple branches based on cloning
     * and filtering it depending on the passed predicates.
     * [ (message) => message.key.startsWith("A"),
     *   (message) => message.key.startsWith("B"),
     *   (message) => true ]
     * ---
     * [ streamA, streamB, streamTrue ]
     * @param {Array<Function>} preds
     * @returns {Array<KStream>}
     */
    branch(preds = []) {

        if (!Array.isArray(preds)) {
            throw new Error("branch predicates must be an array.");
        }

        return preds.map((pred) => {

            if (typeof pred !== "function") {
                throw new Error("branch predicates must be an array of functions: ", pred);
            }

            return this.clone().filter(pred);
        });
    }

    /**
     * builds a window'ed stream across all events of the current kstream
     * when the first event with an exceeding "to" is received (or the abort()
     * callback is called) the window closes and emits its "collected" values to the
     * returned kstream
     * from and to must be unix epoch timestamps in milliseconds (Date.now())
     * etl can be a function that should return the timestamp (event time) of
     * from within the message e.g. m -> m.payload.createdAt
     * if etl is not given, a timestamp of receiving will be used (processing time)
     * for each event
     * encapsulated refers to the result messages (defaults to true, they will be
     * encapsulated in an object: {time, value}
     * @param {number} from
     * @param {number} to
     * @param {function} etl
     * @param {boolean} encapsulated - if event should stay encapsulated {time, value}
     * @param {boolean} collect - if events should be collected first before publishing to result stream
     * @returns {{window: *, abort: abort, stream: *}}
     */
    window(from, to, etl = null, encapsulated = true, collect = true) {

        if (typeof from !== "number" || typeof to !== "number") {
            throw new Error("from & to should be unix epoch ms times.");
        }

        //use this.stream$ as base, but work on a new one
        let stream$ = null;
        if (!etl) {
            stream$ = this.stream$.timestamp();
        } else {
            stream$ = this.stream$.map(element => {
                return {
                    time: etl(element),
                    value: element
                };
            });
        }

        let aborted = false;
        const abort$ = createSubject();
        function abort() {

            if (aborted) {
                return;
            }

            aborted = true;
            abort$.next(null);
        }

        const window = new Window([], collect);
        const window$ = window.getStream();
        stream$
            .skipWhile(event => event.time < from)
            .takeWhile(event => event.time < to)
            .until(abort$)
            .tap(event => window.execute(event, encapsulated))
            .drain().then(_ => {
                window.writeToStream();
                window.flush();
            })
            .catch((error) => {
                window$.error(error);
            });

        return {
            window,
            abort,
            stream: this._cloneWith(window$)
        };
    }

    /**
     * closes the internal stream
     * and all kafka open connections
     * as well as KStorage connections
     * @returns {Promise.<boolean>}
     */
    close() {
        this.stream$ = this.stream$.take(0);
        this.stream$ = null;
        this.kafka.close();
        return this.storage.close();
    }
}

module.exports = KStream;
<commit_msg>window fix<commit_after>"use strict";

const Promise = require("bluebird");
const { async: createSubject } = require("most-subject");

const StreamDSL = require("./StreamDSL.js");
const { Window } = require("../actions/index");
const { messageProduceHandle } = require("../messageProduceHandle.js");

const NOOP = () => { };

/**
 * change-log representation of a stream
 */
class KStream extends StreamDSL {

    /**
     * creates a changelog representation of a stream
     * join operations of kstream instances are synchronous
     * and return new instances immediately
     * @param {string} topicName
     * @param {KStorage} storage
     * @param {KafkaClient} kafka
     * @param {boolean} isClone
     */
    constructor(topicName, storage = null, kafka = null, isClone = false) {
        super(topicName, storage, kafka, isClone);

        this.started = false;

        //readability
        if (isClone) {
            this.started = true;
        }
    }

    /**
     * start kafka consumption
     * prepare production of messages if necessary
     * when called with zero or just a single callback argument
     * this function will return a promise and use the callback for errors
     * @param {function|Object} kafkaReadyCallback - can also be an object (config)
     * @param {function} kafkaErrorCallback
     * @param {boolean} withBackPressure
     * @param {Object} outputKafkaConfig
     */
    start(kafkaReadyCallback = null, kafkaErrorCallback = null, withBackPressure = false, outputKafkaConfig = null) {

        if (kafkaReadyCallback && typeof kafkaReadyCallback === "object" && arguments.length < 2) {
            return new Promise((resolve, reject) => {
                this._start(resolve, reject, kafkaReadyCallback.withBackPressure, kafkaReadyCallback.outputKafkaConfig);
            });
        }

        if (arguments.length < 2) {
            return new Promise((resolve, reject) => {
                this._start(resolve, reject, withBackPressure);
            });
        }

        return this._start(kafkaReadyCallback, kafkaErrorCallback, withBackPressure, outputKafkaConfig);
    }

    _start(kafkaReadyCallback = null, kafkaErrorCallback = null, withBackPressure = false, outputKafkaConfig = null) {

        if (this.started) {
            throw new Error("this KStream is already started.");
        }

        this.started = true;

        if (this.noTopicProvided && !this.produceAsTopic) {
            return kafkaReadyCallback();
        }

        let producerReady = false;
        let consumerReady = false;

        const onReady = (type) => {

            switch (type) {
                case "producer": producerReady = true; break;
                case "consumer": consumerReady = true; break;
            }

            //consumer && producer
            if (producerReady && consumerReady && kafkaReadyCallback) {
                kafkaReadyCallback();
            }

            //consumer only
            if (!this.produceAsTopic && consumerReady && kafkaReadyCallback) {
                kafkaReadyCallback();
            }

            //producer only
            if (this.produceAsTopic && producerReady && kafkaReadyCallback && !this.kafka.topic || !this.kafka.topic.length) {
                kafkaReadyCallback();
            }
        };

        //overwrite kafka topics
        this.kafka.overwriteTopics(this.topicName);

        this.kafka.on("message", msg => super.writeToStream(msg));
        this.kafka.start(() => { onReady("consumer"); }, kafkaErrorCallback || NOOP, this.produceAsTopic, withBackPressure);

        if (this.produceAsTopic) {

            this.kafka.setupProducer(this.outputTopicName, this.outputPartitionsCount, () => { onReady("producer"); },
                kafkaErrorCallback, outputKafkaConfig);

            super.forEach(message => {
                messageProduceHandle(
                    this.kafka,
                    message,
                    this.outputTopicName,
                    this.produceType,
                    this.produceCompressionType,
                    this.produceVersion,
                    kafkaErrorCallback
                );
            });

        }
    }

    /**
     * Emits an output when both input sources have records with the same key.
     * s1$:{object} + s2$:{object} -> j$:{left: s1$object, right: s2$object}
     * @param {StreamDSL} stream
     * @param {string} key
     * @param {boolean} windowed
     * @param {function} combine
     * @returns {KStream}
     */
    innerJoin(stream, key = "key", windowed = false, combine = null) {

        let join$ = null;
        if (!windowed) {
            join$ = this._innerJoinNoWindow(stream, key, combine);
        } else {
            throw new Error("not implemented yet."); //TODO implement
        }

        return this._cloneWith(join$);
    }

    _innerJoinNoWindow(stream, key, combine) {

        const existingKeyFilter = (event) => {
            return !!event && typeof event === "object" && typeof event[key] !== "undefined";
        };

        const melt = (left, right) => {
            return {
                left,
                right
            };
        };

        const parent$ = super.multicast().stream$.filter(existingKeyFilter);
        const side$ = stream.multicast().stream$.filter(existingKeyFilter);
        return parent$.zip(combine || melt, side$);
    }

    /**
     * Emits an output for each record in either input source.
     * If only one source contains a key, the other is null
     * @param {StreamDSL} stream
     */
    outerJoin(stream) {
        throw new Error("not implemented yet."); //TODO implement
    }

    /**
     * Emits an output for each record in the left or primary input source.
     * If the other source does not have a value for a given key, it is set to null
     * @param {StreamDSL} stream
     */
    leftJoin(stream) {
        throw new Error("not implemented yet."); //TODO implement
    }

    /**
     * Emits an output for each record in any of the streams.
     * Acts as simple merge of both streams.
     * can be used with KStream or KTable instances
     * returns a NEW KStream instance
     * @param {StreamDSL} stream
     * @returns {KStream}
     */
    merge(stream) {

        if (!(stream instanceof StreamDSL)) {
            throw new Error("stream has to be an instance of KStream or KTable.");
        }

        // multicast prevents replays
        // create a new internal stream that merges both KStream.stream$s
        const newStream$ = this.stream$.multicast().merge(stream.stream$.multicast());
        return this._cloneWith(newStream$);
    }

    _cloneWith(newStream$) {

        const kafkaStreams = this._kafkaStreams;
        if (!kafkaStreams) {
            throw new Error("merging requires a kafka streams reference on the left-hand merger.");
        }

        const newStorage = kafkaStreams.getStorage();
        const newKafkaClient = kafkaStreams.getKafkaClient();

        const newInstance = new KStream(null, newStorage, newKafkaClient, true);
        newInstance.replaceInternalObservable(newStream$);
        newInstance._kafkaStreams = kafkaStreams;

        return newInstance;
    }

    /**
     * creates a new KStream instance from a given most.js
     * stream; the consume topic will be empty and therefore
     * no consumer will be build
     * @param {Object} most.js stream
     * @returns {KStream}
     */
    fromMost(stream$) {
        return this._cloneWith(stream$);
    }

    /**
     * as only joins and window operations return new stream instances
     * you might need a clone sometimes, which can be accomplished
     * using this function
     * @returns {KStream}
     */
    clone() {
        return this._cloneWith(this.stream$.multicast());
    }

    /**
     * Splits a stream into multiple branches based on cloning
     * and filtering it depending on the passed predicates.
     * [ (message) => message.key.startsWith("A"),
     *   (message) => message.key.startsWith("B"),
     *   (message) => true ]
     * ---
     * [ streamA, streamB, streamTrue ]
     * @param {Array<Function>} preds
     * @returns {Array<KStream>}
     */
    branch(preds = []) {

        if (!Array.isArray(preds)) {
            throw new Error("branch predicates must be an array.");
        }

        return preds.map((pred) => {

            if (typeof pred !== "function") {
                throw new Error("branch predicates must be an array of functions: ", pred);
            }

            return this.clone().filter(pred);
        });
    }

    /**
     * builds a window'ed stream across all events of the current kstream
     * when the first event with an exceeding "to" is received (or the abort()
     * callback is called) the window closes and emits its "collected" values to the
     * returned kstream
     * from and to must be unix epoch timestamps in milliseconds (Date.now())
     * etl can be a function that should return the timestamp (event time) of
     * from within the message e.g. m -> m.payload.createdAt
     * if etl is not given, a timestamp of receiving will be used (processing time)
     * for each event
     * encapsulated refers to the result messages (defaults to true, they will be
     * encapsulated in an object: {time, value}
     * @param {number} from
     * @param {number} to
     * @param {function} etl
     * @param {boolean} encapsulated - if event should stay encapsulated {time, value}
     * @param {boolean} collect - if events should be collected first before publishing to result stream
     * @returns {{window: *, abort: abort, stream: *}}
     */
    window(from, to, etl = null, encapsulated = true, collect = true) {

        if (typeof from !== "number" || typeof to !== "number") {
            throw new Error("from & to should be unix epoch ms times.");
        }

        //use this.stream$ as base, but work on a new one
        let stream$ = null;
        if (!etl) {
            stream$ = this.stream$.timestamp();
        } else {
            stream$ = this.stream$.map(element => {
                return {
                    time: etl(element),
                    value: element
                };
            });
        }

        let aborted = false;
        const abort$ = createSubject();
        function abort() {

            if (aborted) {
                return;
            }

            aborted = true;
            abort$.next(null);
        }

        const window = new Window([], collect);
        const window$ = window.getStream();
        stream$
            .skipWhile(event => event.time < from)
            .takeWhile(event => event.time < to)
            .until(abort$)
            .tap(event => window.execute(event, encapsulated))
            .drain().then(_ => {
                window.writeToStream();
                window.flush();
            })
            .catch((error) => {
                window$.error(error);
            });

        return {
            window,
            abort,
            stream: this._cloneWith(window$)
        };
    }

    /**
     * closes the internal stream
     * and all kafka open connections
     * as well as KStorage connections
     * @returns {Promise.<boolean>}
     */
    close() {
        this.stream$ = this.stream$.take(0);
        this.stream$ = null;
        this.kafka.close();
        return this.storage.close();
    }
}

module.exports = KStream;
<|endoftext|>


<commit_before>describe('queue', function () {
  describe('queue', function () {
    it('should show 2 queuers', function () {
      browser.addMockModule('httpBackendMock', function () {
        angular.module('httpBackendMock', ['ngMockE2E'])
          .run(function ($httpBackend) {
            $httpBackend.whenGET('teams.json').respond([
              {
                name: "Helpdesk",
                filter: true
              }
            ]);
            $httpBackend.whenGET('queue.json').respond([
              { team: 'Helpdesk', language: 'Finnish', time_in_queue: 71 },
              { team: 'Helpdesk', language: 'Swedish', time_in_queue: 34 }
            ]);
            $httpBackend.whenGET('settings.json').respond([
{"colors":{"background":"#87aade","font":"#333333","statuses":{"free":"#37c837","call":"#ffff4d","busy":"#ff3333"}},"others":{"service_height":"300","working_day_start":"8","working_day_end":"18"}}
]);
          });
      });

      browser.addMockModule('ocWebGui.shared.time.service', function () {
        angular.module('ocWebGui.shared.time.service', [])
          .factory('CustomDate', function () {
            return {
              getDate: function () {
                return new Date(2013, 9, 23, 12, 0);
              }
            };
          });
      });

      browser.get('#/queue');

      var queue = element.all(by.className('queuer'));

      expect(queue.count()).toBe(2);

      expect(queue.get(0).element(by.className('queuer-time')).getText()).toBe('01:11');
      expect(queue.get(0).isElementPresent(by.className('queuer-flag-Finnish'))).toBe(true);
      expect(queue.get(1).element(by.className('queuer-time')).getText()).toBe('00:34');
      expect(queue.get(1).isElementPresent(by.className('queuer-flag-Swedish'))).toBe(true);

      expect(browser.isElementPresent(by.className('plus-5'))).toBe(false);
    });

    it('should not show indicator with 5 queuers', function () {
      browser.addMockModule('httpBackendMock', function () {
        angular.module('httpBackendMock', ['ngMockE2E'])
          .run(function ($httpBackend) {
            $httpBackend.whenGET('teams.json').respond([
              {
                name: "Helpdesk",
                filter: true
              }
            ]);
            $httpBackend.whenGET('queue.json').respond([
              { team: 'Helpdesk', language: 'Finnish' },
              { team: 'Helpdesk', language: 'Swedish' },
              { team: 'Helpdesk', language: 'Finnish' },
              { team: 'Helpdesk', language: 'Finnish' },
              { team: 'Helpdesk', language: 'Finnish' }
            ]);
            $httpBackend.whenGET('settings.json').respond([
{"colors":{"background":"#87aade","font":"#333333","statuses":{"free":"#37c837","call":"#ffff4d","busy":"#ff3333"}},"others":{"service_height":"300","working_day_start":"8","working_day_end":"18"}}
]);
          });
      });
      browser.get('#/queue');

      var queue = element.all(by.className('queuer'));
      expect(queue.count()).toBe(5);
      expect(browser.isElementPresent(by.className('plus-5'))).toBe(false);
    });

    it('should show only 5 queuers and indicator of more', function () {
      browser.addMockModule('httpBackendMock', function () {
        angular.module('httpBackendMock', ['ngMockE2E'])
          .run(function ($httpBackend) {
            $httpBackend.whenGET('teams.json').respond([
              {
                name: "Helpdesk",
                filter: true
              }
            ]);
            $httpBackend.whenGET('queue.json').respond([
              { team: 'Helpdesk', language: 'Finnish' },
              { team: 'Helpdesk', language: 'Swedish' },
              { team: 'Helpdesk', language: 'English' },
              { team: 'Helpdesk', language: 'Finnish' },
              { team: 'Helpdesk', language: 'Finnish' },
              { team: 'Helpdesk', language: 'Finnish' }
            ]);
            $httpBackend.whenGET('settings.json').respond([
{"colors":{"background":"#87aade","font":"#333333","statuses":{"free":"#37c837","call":"#ffff4d","busy":"#ff3333"}},"others":{"service_height":"300","working_day_start":"8","working_day_end":"18"}}
]);
          });
      });
      browser.get('#/queue');

      var queue = element.all(by.className('queuer'));
      expect(queue.count()).toBe(5);
      expect(browser.isElementPresent(by.className('plus-5'))).toBe(true);
    });
  });

  describe('stats', function () {
    var rows;

    beforeEach(function () {
      browser.addMockModule('httpBackendMock', function () {
        angular.module('httpBackendMock', ['ngMockE2E'])
          .run(function ($httpBackend) {
            $httpBackend.whenGET('contacts/stats.json').respond({
              answered_calls: 11,
              average_call_duration: 2 * 60 + 15,
              answered_percentage: 100,
              average_after_call_duration: 60 + 5,
              average_queue_duration: 100,
              calls_by_hour: [
                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
              ],
              average_queue_duration_by_hour: [
                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
              ],
              service_level_agreement: 91
            });
            $httpBackend.whenGET('settings.json').respond([
{"colors":{"background":"#87aade","font":"#333333","statuses":{"free":"#37c837","call":"#ffff4d","busy":"#ff3333"}},"others":{"service_height":"300","working_day_start":"8","working_day_end":"18"}}
]);
          });
      });
      browser.get('#/queue');
      var statsTable = element.all(by.className('queue-stats-table'));
      rows = statsTable.all(by.tagName('tr'));
    });

    it('should contain 6 rows', function () {
      expect(rows.count()).toBe(6);
    });

    it('should contain answered calls', function () {
      expect(rows.get(0).element(by.tagName('td')).getText()).toBe('100%');
    });

    it('should contain calls (answered / all)', function() {
      expect(rows.get(1).element(by.tagName('th')).getText()).toBe('Puhelut:');
      expect(rows.get(1).element(by.tagName('td')).getText()).toBe('11 / 11');
    });

    it('should contain average call duration', function () {
      expect(rows.get(2).element(by.tagName('th')).getText()).toBe('Puheluiden ka:');
      expect(rows.get(2).element(by.tagName('td')).getText()).toBe('02:15');
    });

    it('should contain average call duration', function () {
      expect(rows.get(3).element(by.tagName('th')).getText()).toBe('Jälkikirjausten ka:');
      expect(rows.get(3).element(by.tagName('td')).getText()).toBe('01:05');
    });

    it('should contain average queue waiting duration', function () {
      expect(rows.get(4).element(by.tagName('th')).getText()).toBe('Jonotusten ka:');
      expect(rows.get(4).element(by.tagName('td')).getText()).toBe('01:40');
    });

    it('should contain testtest', function () {
      expect(rows.get(5).element(by.tagName('th')).getText()).toBe('Palvelutaso:');
      expect(rows.get(5).element(by.tagName('td')).getText()).toBe('91%');
    });
  });
});
<commit_msg>try fix<commit_after>describe('queue', function () {
  describe('queue', function () {
    it('should show 2 queuers', function () {
      browser.addMockModule('httpBackendMock', function () {
        angular.module('httpBackendMock', ['ngMockE2E'])
          .run(function ($httpBackend) {
            $httpBackend.whenGET('teams.json').respond([
              {
                name: "Helpdesk",
                filter: true
              }
            ]);
            $httpBackend.whenGET('queue.json').respond([
              { team: 'Helpdesk', language: 'Finnish', time_in_queue: 71 },
              { team: 'Helpdesk', language: 'Swedish', time_in_queue: 34 }
            ]);
            $httpBackend.whenGET('settings.json').respond([
{"colors":{"background":"#87aade","font":"#333333","statuses":{"free":"#37c837","call":"#ffff4d","busy":"#ff3333"}},"others":{"service_height":300,"working_day_start":8,"working_day_end":18}}
]);
          });
      });

      browser.addMockModule('ocWebGui.shared.time.service', function () {
        angular.module('ocWebGui.shared.time.service', [])
          .factory('CustomDate', function () {
            return {
              getDate: function () {
                return new Date(2013, 9, 23, 12, 0);
              }
            };
          });
      });

      browser.get('#/queue');

      var queue = element.all(by.className('queuer'));

      expect(queue.count()).toBe(2);

      expect(queue.get(0).element(by.className('queuer-time')).getText()).toBe('01:11');
      expect(queue.get(0).isElementPresent(by.className('queuer-flag-Finnish'))).toBe(true);
      expect(queue.get(1).element(by.className('queuer-time')).getText()).toBe('00:34');
      expect(queue.get(1).isElementPresent(by.className('queuer-flag-Swedish'))).toBe(true);

      expect(browser.isElementPresent(by.className('plus-5'))).toBe(false);
    });

    it('should not show indicator with 5 queuers', function () {
      browser.addMockModule('httpBackendMock', function () {
        angular.module('httpBackendMock', ['ngMockE2E'])
          .run(function ($httpBackend) {
            $httpBackend.whenGET('teams.json').respond([
              {
                name: "Helpdesk",
                filter: true
              }
            ]);
            $httpBackend.whenGET('queue.json').respond([
              { team: 'Helpdesk', language: 'Finnish' },
              { team: 'Helpdesk', language: 'Swedish' },
              { team: 'Helpdesk', language: 'Finnish' },
              { team: 'Helpdesk', language: 'Finnish' },
              { team: 'Helpdesk', language: 'Finnish' }
            ]);
            $httpBackend.whenGET('settings.json').respond([
{"colors":{"background":"#87aade","font":"#333333","statuses":{"free":"#37c837","call":"#ffff4d","busy":"#ff3333"}},"others":{"service_height":300,"working_day_start":8,"working_day_end":18}}
]);
          });
      });
      browser.get('#/queue');

      var queue = element.all(by.className('queuer'));
      expect(queue.count()).toBe(5);
      expect(browser.isElementPresent(by.className('plus-5'))).toBe(false);
    });

    it('should show only 5 queuers and indicator of more', function () {
      browser.addMockModule('httpBackendMock', function () {
        angular.module('httpBackendMock', ['ngMockE2E'])
          .run(function ($httpBackend) {
            $httpBackend.whenGET('teams.json').respond([
              {
                name: "Helpdesk",
                filter: true
              }
            ]);
            $httpBackend.whenGET('queue.json').respond([
              { team: 'Helpdesk', language: 'Finnish' },
              { team: 'Helpdesk', language: 'Swedish' },
              { team: 'Helpdesk', language: 'English' },
              { team: 'Helpdesk', language: 'Finnish' },
              { team: 'Helpdesk', language: 'Finnish' },
              { team: 'Helpdesk', language: 'Finnish' }
            ]);
            $httpBackend.whenGET('settings.json').respond([
{"colors":{"background":"#87aade","font":"#333333","statuses":{"free":"#37c837","call":"#ffff4d","busy":"#ff3333"}},"others":{"service_height":300,"working_day_start":8,"working_day_end":18}}
]);
          });
      });
      browser.get('#/queue');

      var queue = element.all(by.className('queuer'));
      expect(queue.count()).toBe(5);
      expect(browser.isElementPresent(by.className('plus-5'))).toBe(true);
    });
  });

  describe('stats', function () {
    var rows;

    beforeEach(function () {
      browser.addMockModule('httpBackendMock', function () {
        angular.module('httpBackendMock', ['ngMockE2E'])
          .run(function ($httpBackend) {
            $httpBackend.whenGET('contacts/stats.json').respond({
              answered_calls: 11,
              average_call_duration: 2 * 60 + 15,
              answered_percentage: 100,
              average_after_call_duration: 60 + 5,
              average_queue_duration: 100,
              calls_by_hour: [
                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
              ],
              average_queue_duration_by_hour: [
                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
              ],
              service_level_agreement: 91
            });
            $httpBackend.whenGET('settings.json').respond([
{"colors":{"background":"#87aade","font":"#333333","statuses":{"free":"#37c837","call":"#ffff4d","busy":"#ff3333"}},"others":{"service_height":300,"working_day_start":8,"working_day_end":18}}
]);
          });
      });
      browser.get('#/queue');
      var statsTable = element.all(by.className('queue-stats-table'));
      rows = statsTable.all(by.tagName('tr'));
    });

    it('should contain 6 rows', function () {
      expect(rows.count()).toBe(6);
    });

    it('should contain answered calls', function () {
      expect(rows.get(0).element(by.tagName('td')).getText()).toBe('100%');
    });

    it('should contain calls (answered / all)', function() {
      expect(rows.get(1).element(by.tagName('th')).getText()).toBe('Puhelut:');
      expect(rows.get(1).element(by.tagName('td')).getText()).toBe('11 / 11');
    });

    it('should contain average call duration', function () {
      expect(rows.get(2).element(by.tagName('th')).getText()).toBe('Puheluiden ka:');
      expect(rows.get(2).element(by.tagName('td')).getText()).toBe('02:15');
    });

    it('should contain average call duration', function () {
      expect(rows.get(3).element(by.tagName('th')).getText()).toBe('Jälkikirjausten ka:');
      expect(rows.get(3).element(by.tagName('td')).getText()).toBe('01:05');
    });

    it('should contain average queue waiting duration', function () {
      expect(rows.get(4).element(by.tagName('th')).getText()).toBe('Jonotusten ka:');
      expect(rows.get(4).element(by.tagName('td')).getText()).toBe('01:40');
    });

    it('should contain testtest', function () {
      expect(rows.get(5).element(by.tagName('th')).getText()).toBe('Palvelutaso:');
      expect(rows.get(5).element(by.tagName('td')).getText()).toBe('91%');
    });
  });
});
<|endoftext|>


<commit_before>const Constants  = require("./constants.js");
const Commons    = require("./commons.js");
const Cloudevent = require("../../cloudevent.js");
const Spec02     = require("../../specs/spec_0_2.js");

var JSONParser = require("../../formats/json/parser.js");

const jsonParserSpec02 = new JSONParser(new Spec02());

const parsers = {};
parsers[Constants.MIME_JSON]    = jsonParserSpec02;
parsers[Constants.MIME_CE_JSON] = jsonParserSpec02;

const allowed_content_types = [];
allowed_content_types.push(Constants.MIME_CE_JSON);

function validate_args(payload, attributes) {
  if(!payload){
    throw {message: "payload is null or undefined"};
  }

  if(!attributes) {
    throw {message: "attributes is null or undefined"};
  }

  if((typeof payload) !== "object" && (typeof payload) !== "string"){
    throw {message: "payload must be an object or string",
             erros: [typeof payload]};
  }
}

function Receiver(configuration) {

}

Receiver.prototype.check = function(payload, headers) {
  validate_args(payload, headers);

  var sanity_headers = Commons.sanity_and_clone(headers);

  // Validation Level 1
  if(!allowed_content_types
      .includes(sanity_headers[Constants.HEADER_CONTENT_TYPE])){
        throw {message: "invalid content type",
              errors: [sanity_headers[Constants.HEADER_CONTENT_TYPE]]};
  }

  // No erros! Its contains the minimum required attributes
}

Receiver.prototype.parse = function(payload, headers) {
  this.check(payload, headers);

  var sanity_headers = Commons.sanity_and_clone(headers);

  var contentType = sanity_headers[Constants.HEADER_CONTENT_TYPE];

  var parser = parsers[contentType];
  var cloudevent = parser.parse(payload);

  return cloudevent;
}

module.exports = Receiver;
<commit_msg>cleanning the code<commit_after>const Constants  = require("./constants.js");
const Commons    = require("./commons.js");
const Cloudevent = require("../../cloudevent.js");
const Spec02     = require("../../specs/spec_0_2.js");

var JSONParser = require("../../formats/json/parser.js");

const jsonParserSpec02 = new JSONParser(new Spec02());

const parser_by_mime = {};
parser_by_mime[Constants.MIME_JSON]    = jsonParserSpec02;
parser_by_mime[Constants.MIME_CE_JSON] = jsonParserSpec02;

const allowed_content_types = [];
allowed_content_types.push(Constants.MIME_CE_JSON);

function validate_args(payload, attributes) {
  if(!payload){
    throw {message: "payload is null or undefined"};
  }

  if(!attributes) {
    throw {message: "attributes is null or undefined"};
  }

  if((typeof payload) !== "object" && (typeof payload) !== "string"){
    throw {message: "payload must be an object or string",
             erros: [typeof payload]};
  }
}

function Receiver(configuration) {

}

Receiver.prototype.check = function(payload, headers) {
  validate_args(payload, headers);

  var sanity_headers = Commons.sanity_and_clone(headers);

  // Validation Level 1
  if(!allowed_content_types
      .includes(sanity_headers[Constants.HEADER_CONTENT_TYPE])){
        throw {message: "invalid content type",
              errors: [sanity_headers[Constants.HEADER_CONTENT_TYPE]]};
  }

  // No erros! Its contains the minimum required attributes
}

Receiver.prototype.parse = function(payload, headers) {
  this.check(payload, headers);

  var sanity_headers = Commons.sanity_and_clone(headers);

  var contentType = sanity_headers[Constants.HEADER_CONTENT_TYPE];

  var parser = parser_by_mime[contentType];

  var cloudevent = parser.parse(payload);

  return cloudevent;
}

module.exports = Receiver;
<|endoftext|>


<commit_before>const mix = require('laravel-mix');

/**
 * Compile CSS
 */
mix.sass('resources/scss/admin.scss', 'public/css');
mix.sass('resources/scss/public.scss', 'public/css');

/**
 * Compile JS
 */
mix.js('resources/js/admin.js', 'public/js');
mix.js('resources/js/public.js', 'public/js');

/**
 * Copy font-awesome files
 */
mix.copy('node_modules/font-awesome/fonts', 'public/fonts');

/**
 * Copy CKEditor main files
 */
mix.copy('node_modules/ckeditor4/ckeditor.js', 'public/components/ckeditor4/ckeditor.js');
mix.copy('node_modules/ckeditor4/contents.css', 'public/components/ckeditor4/contents.css');

/**
 * Copy CKEditor lang files
 */
mix.copy('node_modules/ckeditor4/lang/fr.js', 'public/components/ckeditor4/lang/fr.js');
mix.copy('node_modules/ckeditor4/lang/es.js', 'public/components/ckeditor4/lang/es.js');
mix.copy('node_modules/ckeditor4/lang/nl.js', 'public/components/ckeditor4/lang/nl.js');
mix.copy('node_modules/ckeditor4/lang/en.js', 'public/components/ckeditor4/lang/en.js');

/**
 * Copy CKEditor plugins files
 */
var plugins = [
    'dialog',
    'dialogadvtab',
    'div',
    'image',
    'image2',
    'justify',
    'link',
    'magicline',
    'panelbutton',
    'pastefromgdocs',
    'pastefromword',
    'pastetools',
    'scayt',
    'showblocks',
    'specialchar',
    'table',
    'tableselection',
    'tabletools',
    'widget',
    'wsc',
];
plugins.forEach(function(plugin) {
    mix.copy('node_modules/ckeditor4/plugins/' + plugin, 'public/components/ckeditor4/plugins/' + plugin);
});

/**
 * Copy CKEditor skins files
 */
mix.copy('node_modules/ckeditor4/skins', 'public/components/ckeditor4/skins');

/**
 * Versioning process
 */
mix.version();

/**
 * BrowserSync
 */
mix.browserSync('typicms.test');

/**
 * Options
 */
mix.options({
    processCssUrls: false,
    autoprefixer: {
        options: {
            overrideBrowserslist: ['last 10 versions'],
        },
    },
});

/**
 * Source maps
 */
// if (!mix.inProduction()) {
//     mix.webpackConfig({
//         devtool: 'source-map',
//     }).sourceMaps();
// }
<commit_msg>Autoprefixer config removed<commit_after>const mix = require('laravel-mix');

/**
 * Compile CSS
 */
mix.sass('resources/scss/admin.scss', 'public/css');
mix.sass('resources/scss/public.scss', 'public/css');

/**
 * Compile JS
 */
mix.js('resources/js/admin.js', 'public/js');
mix.js('resources/js/public.js', 'public/js');

/**
 * Copy font-awesome files
 */
mix.copy('node_modules/font-awesome/fonts', 'public/fonts');

/**
 * Copy CKEditor main files
 */
mix.copy('node_modules/ckeditor4/ckeditor.js', 'public/components/ckeditor4/ckeditor.js');
mix.copy('node_modules/ckeditor4/contents.css', 'public/components/ckeditor4/contents.css');

/**
 * Copy CKEditor lang files
 */
mix.copy('node_modules/ckeditor4/lang/fr.js', 'public/components/ckeditor4/lang/fr.js');
mix.copy('node_modules/ckeditor4/lang/es.js', 'public/components/ckeditor4/lang/es.js');
mix.copy('node_modules/ckeditor4/lang/nl.js', 'public/components/ckeditor4/lang/nl.js');
mix.copy('node_modules/ckeditor4/lang/en.js', 'public/components/ckeditor4/lang/en.js');

/**
 * Copy CKEditor plugins files
 */
var plugins = [
    'dialog',
    'dialogadvtab',
    'div',
    'image',
    'image2',
    'justify',
    'link',
    'magicline',
    'panelbutton',
    'pastefromgdocs',
    'pastefromword',
    'pastetools',
    'scayt',
    'showblocks',
    'specialchar',
    'table',
    'tableselection',
    'tabletools',
    'widget',
    'wsc',
];
plugins.forEach(function(plugin) {
    mix.copy('node_modules/ckeditor4/plugins/' + plugin, 'public/components/ckeditor4/plugins/' + plugin);
});

/**
 * Copy CKEditor skins files
 */
mix.copy('node_modules/ckeditor4/skins', 'public/components/ckeditor4/skins');

/**
 * Versioning process
 */
mix.version();

/**
 * BrowserSync
 */
mix.browserSync('typicms.test');

/**
 * Options
 */
mix.options({
    processCssUrls: false,
});

/**
 * Source maps
 */
// if (!mix.inProduction()) {
//     mix.webpackConfig({
//         devtool: 'source-map',
//     }).sourceMaps();
// }
<|endoftext|>


<commit_before>/*
TODO:
-better serialization/deserialization
-error handling if firebase contains malformed data, since we're not the only
ones who can write to it.
-multi part keys
*/

foam.CLASS({
  package: 'com.firebase',
  name: 'FirebaseDAO',
  extends: 'foam.dao.AbstractDAO',
  requires: [
    'foam.dao.ArraySink',
    'foam.net.HTTPRequest',
    'foam.net.EventSource',
    'foam.mlang.predicate.Gt',
    'foam.mlang.predicate.Constant'
  ],
  properties: [
    'of',
    'apppath',
    'secret',
    'eventSource_',
    {
      name: 'timestampProperty'
    },
    {
      name: 'basepath',
      expression: function(apppath, of) {
        return apppath + of.id.replace(/\./g, '/');
      }
    },
    'startEventsAt_'
  ],
  methods: [
    function put(obj) {
      var req = this.HTTPRequest.create();

      if ( obj.id ) {
        req.method = "PUT";
        req.url = this.basepath
          + "/"
          + encodeURIComponent(obj.id) + ".json";
      } else {
        throw new Error('Server generated IDs not supported.');
        // req.method = 'POST';
        // req.url = this.basepath + '.json';
      }

      if ( this.secret ) {
        req.url += '?auth=' + encodeURIComponent(this.secret);
      }

      req.payload = JSON.stringify({
        data: foam.json.stringify(obj),
        lastUpdate: {
          ".sv": "timestamp"
        }
      });
      req.headers['content-type'] = 'application/json';
      req.headers['accept'] = 'application/json';

      return req.send().then(function(resp) {
        return resp.payload;
      }).then(function(payload) {
        payload = JSON.parse(payload);

        //        if ( obj.id ) {
          var o2 = foam.json.parse(foam.json.parseString(payload.data));
          if ( this.timestampProperty ) {
            this.timestampProperty.set(o2, payload.lastUpdate);
          }
          return o2;
        //        } else {
        //           Server created id
        //        }
      }.bind(this), function(resp) {
        // TODO: Handle various errors.
        return Promise.reject(foam.dao.InternalException.create());
      });
    },
    function remove(obj) {
      var req = this.HTTPRequest.create();
      req.method = "DELETE",
      req.url = this.basepath + "/" + encodeURIComponent(obj.id) + ".json";

      if ( this.secret ) {
        req.url += "?auth=" + encodeURIComponent(this.secret);
      }

      return req.send().then(function() {
        return Promise.resolve();
      }, function() {
        return Promise.reject(foam.dao.InternalException.create());
      });
    },
    function find(id) {
      var req = this.HTTPRequest.create();
      req.method = "GET";
      req.url = this.basepath + "/" + encodeURIComponent(id) + ".json";
      if ( this.secret ) {
        req.url += "?auth=" + encodeURIComponent(this.secret);
      }

      return req.send().then(function(resp) {
        return resp.payload;
      }).then(function(data) {
        if ( data == "null" ) {
          return Promise.reject(foam.dao.ObjectNotFoundException.create({ id: id }));
        }
        try {
          data = JSON.parse(data);

          var obj = foam.json.parse(
            foam.json.parseString(data.data));

          if ( this.timestampProperty ) {
            this.timestampProperty.set(obj, data.lastUpdate);
          }

          return obj;
        } catch(e) {
          return Promise.reject(foam.dao.InternalException.create());
        }
      }.bind(this));
    },
    function startEvents() {
      if ( this.eventSource_ ) {
        return;
      }

      var params = [];
      if ( this.secret ) params.push(['auth', this.secret]);
      if ( this.startEventsAt_ ) {
        params.push(['orderBy', '"lastUpdate"']);
        params.push(['startAt', this.startEventsAt_]);
      }

      var uri = this.basepath + '.json';
      if ( params.length ) {
        uri += '?' + params.map(function(p) { return p.map(encodeURIComponent).join('='); }).join('&');
      }

      this.eventSource_ = this.EventSource.create({
        uri: uri
      });

      this.eventSource_.message.put.sub(this.onPut);
      this.eventSource_.message.patch.sub(this.onPatch);
      this.eventSource_.start();
    },
    function stopEvents() {
      if ( this.eventSource_ ) {
        this.eventSource_.close();
        this.eventSource_.message.put.unsub(this.onPut);
        this.eventSource_.message.patch.unsub(this.onPatch);
        this.clearProperty('eventSource_');
      }
    },
    function select(sink, skip, limit, order, predicate) {
      var req = this.HTTPRequest.create();
      req.method = "GET";

      var params = [];
      if ( this.secret ) params.push(['auth', this.secret]);

      // Efficiently handle GT(lastupdate, #) queries.  Used by the SyncDAO to get
      // all changes.

      if ( predicate && this.timestampProperty &&
           this.Gt.isInstance(predicate) &&
           this.Constant.isInstance(predicate.arg2) &&
           predicate.arg1 === this.timestampProperty ) {

        // TODO: This is a hack to ensure that
        if ( ! this.startEventsAt_ )  {
          this.startEventsAt_ = predicate.arg2.f() + 1;
          this.startEvents();
        }

        params.push(['orderBy', '"lastUpdate"']);
        params.push(['startAt', predicate.arg2.f() + 1]);
      }

      var url = this.basepath + '.json';
      if ( params.length ) {
        url += '?' + params.map(function(p) { return p.map(encodeURIComponent).join('='); }).join('&');
      }

      req.url = url;

      var resultSink = sink || this.ArraySink.create();
      sink = this.decorateSink_(resultSink, skip, limit, order, predicate);

      // TODO: This should be streamed for better handling of large responses.
      return req.send().then(function(resp) {
        if ( ! resp.success ) {
          return Promise.reject(foam.dao.InternalException.create());
        }
        return resp.payload;
      }).then(function(payload) {
        var data = JSON.parse(payload);
        var fc = this.FlowControl.create();

        for ( var key in data ) {
          if ( fc.stopped ) break;
          if ( fc.errorEvt ) {
            sink.error && sink.error(fc.errorEvt);
            future.set(sink);
            break;
          }

          var obj = foam.json.parse(
            foam.json.parseString(data[key].data));
          if ( this.timestampProperty ) {
            this.timestampProperty.set(obj, data[key].lastUpdate);
          }

          sink.put(obj, null, fc);
        }
        sink.eof();

        return resultSink;
      }.bind(this), function(resp) {
        var e = foam.dao.InternalException.create();
        sink.error(e);
        return Promise.reject(e);
      });
    }
  ],
  listeners: [
    function onPut(s, _, _, data) {
      // PATH is one of
      // / -> new objects
      // /key -> new object
      // /key/data -> updated object

      var path = data.path;
      if ( path == "/" ) {
        // All data removed?
        if ( data.data == null ) {
          this.on.reset.pub();
          return;
        }

        for ( var key in data.data ) {
          var obj = foam.json.parse(foam.json.parseString(data.data[key].data));
          if ( this.timestampProperty ) {
            this.timestampProperty.set(obj, data.data[key].lastUpdate);
          }
          this.on.put.pub(obj);
        }
        return;
      } else if ( path.lastIndexOf('/') === 0 ) {
        if ( data.data == null ) {
          var obj = this.of.create();
          obj.id = path.substring(1)
          this.on.remove.pub(obj);
          return;
        }
        var obj = foam.json.parse(foam.json.parseString(data.data.data));
        if ( this.timestampProperty ) {
          this.timestampProperty.set(obj, data.data.lastUpdate);
        }
        this.on.put.pub(obj);
      } else if ( path.indexOf('/data') === path.length - 5 ) {
        // These last two events shouldn't happen unless somebody is editing
        // the underlying firebase data by hand.

        // Data of an existing row updated.
        debugger;
        var id = path.substring(1);
        id = id.substring(0, id.indexOf('/'));
        this.find(id).then(function(obj) {
          this.on.put.pub(obj);
        }.bind(this));

        // var obj = foam.json.parse(foam.json.parseString(data.data));
        // this.on.put.pub(obj);
      } else if ( path.indexOf('/lastUpdate') === path.length - 11 ) {
        // Timestamp of an existing row updated, do anything?
        // presumably if the object itself hasn't been updated we don't care
        // if it has been updated we should get an event for that.

        debugger;
        var id = path.substring(1);
        id = id.substring(0, id.indexOf('/'));
        this.find(id).then(function(obj) {
          this.on.put.pub(obj);
        }.bind(this));
      }
    },
    function onPatch(s, _, _, data) {
          // TODO: What does a patch even look like?
      debugger;
    }
  ]
});
<commit_msg>Add safari version of FirebaseDAO that uses XHRs and doesn't stream events.<commit_after>/*
TODO:
-better serialization/deserialization
-error handling if firebase contains malformed data, since we're not the only
ones who can write to it.
-multi part keys
*/

foam.CLASS({
  package: 'com.firebase',
  name: 'FirebaseDAO',
  extends: 'foam.dao.AbstractDAO',
  requires: [
    'foam.dao.ArraySink',
    'foam.net.HTTPRequest',
    'foam.net.EventSource',
    'foam.mlang.predicate.Gt',
    'foam.mlang.predicate.Constant'
  ],
  properties: [
    'of',
    'apppath',
    'secret',
    'eventSource_',
    {
      name: 'timestampProperty'
    },
    {
      name: 'basepath',
      expression: function(apppath, of) {
        return apppath + of.id.replace(/\./g, '/');
      }
    },
    {
      class: 'Boolean',
      name: 'enableStreaming',
      value: false
    },
    'startEventsAt_'
  ],
  methods: [
    function put(obj) {
      var req = this.HTTPRequest.create();

      if ( obj.id ) {
        req.method = "PUT";
        req.url = this.basepath
          + "/"
          + encodeURIComponent(obj.id) + ".json";
      } else {
        throw new Error('Server generated IDs not supported.');
        // req.method = 'POST';
        // req.url = this.basepath + '.json';
      }

      if ( this.secret ) {
        req.url += '?auth=' + encodeURIComponent(this.secret);
      }

      req.payload = JSON.stringify({
        data: foam.json.stringify(obj),
        lastUpdate: {
          ".sv": "timestamp"
        }
      });
      req.headers['content-type'] = 'application/json';
      req.headers['accept'] = 'application/json';

      return req.send().then(function(resp) {
        return resp.payload;
      }).then(function(payload) {
        payload = JSON.parse(payload);

        //        if ( obj.id ) {
          var o2 = foam.json.parse(foam.json.parseString(payload.data));
          if ( this.timestampProperty ) {
            this.timestampProperty.set(o2, payload.lastUpdate);
          }
          return o2;
        //        } else {
        //           Server created id
        //        }
      }.bind(this), function(resp) {
        // TODO: Handle various errors.
        return Promise.reject(foam.dao.InternalException.create());
      });
    },
    function remove(obj) {
      var req = this.HTTPRequest.create();
      req.method = "DELETE",
      req.url = this.basepath + "/" + encodeURIComponent(obj.id) + ".json";

      if ( this.secret ) {
        req.url += "?auth=" + encodeURIComponent(this.secret);
      }

      return req.send().then(function() {
        return Promise.resolve();
      }, function() {
        return Promise.reject(foam.dao.InternalException.create());
      });
    },
    function find(id) {
      var req = this.HTTPRequest.create();
      req.method = "GET";
      req.url = this.basepath + "/" + encodeURIComponent(id) + ".json";
      if ( this.secret ) {
        req.url += "?auth=" + encodeURIComponent(this.secret);
      }

      return req.send().then(function(resp) {
        return resp.payload;
      }).then(function(data) {
        if ( data == "null" ) {
          return Promise.reject(foam.dao.ObjectNotFoundException.create({ id: id }));
        }
        try {
          data = JSON.parse(data);

          var obj = foam.json.parse(
            foam.json.parseString(data.data));

          if ( this.timestampProperty ) {
            this.timestampProperty.set(obj, data.lastUpdate);
          }

          return obj;
        } catch(e) {
          return Promise.reject(foam.dao.InternalException.create());
        }
      }.bind(this));
    },
    function startEvents() {
      if ( this.eventSource_ || ! this.enableStreaming ) {
        return;
      }

      var params = [];
      if ( this.secret ) params.push(['auth', this.secret]);
      if ( this.startEventsAt_ ) {
        params.push(['orderBy', '"lastUpdate"']);
        params.push(['startAt', this.startEventsAt_]);
      }

      var uri = this.basepath + '.json';
      if ( params.length ) {
        uri += '?' + params.map(function(p) { return p.map(encodeURIComponent).join('='); }).join('&');
      }

      this.eventSource_ = this.EventSource.create({
        uri: uri
      });

      this.eventSource_.message.put.sub(this.onPut);
      this.eventSource_.message.patch.sub(this.onPatch);
      this.eventSource_.start();
    },
    function stopEvents() {
      if ( this.eventSource_ ) {
        this.eventSource_.close();
        this.eventSource_.message.put.unsub(this.onPut);
        this.eventSource_.message.patch.unsub(this.onPatch);
        this.clearProperty('eventSource_');
      }
    },
    function select(sink, skip, limit, order, predicate) {
      var req = this.HTTPRequest.create();
      req.method = "GET";

      var params = [];
      if ( this.secret ) params.push(['auth', this.secret]);

      // Efficiently handle GT(lastupdate, #) queries.  Used by the SyncDAO to get
      // all changes.

      if ( predicate && this.timestampProperty &&
           this.Gt.isInstance(predicate) &&
           this.Constant.isInstance(predicate.arg2) &&
           predicate.arg1 === this.timestampProperty ) {

        // TODO: This is a hack to ensure that
        if ( ! this.startEventsAt_ )  {
          this.startEventsAt_ = predicate.arg2.f() + 1;
          this.startEvents();
        }

        params.push(['orderBy', '"lastUpdate"']);
        params.push(['startAt', predicate.arg2.f() + 1]);
      }

      var url = this.basepath + '.json';
      if ( params.length ) {
        url += '?' + params.map(function(p) { return p.map(encodeURIComponent).join('='); }).join('&');
      }

      req.url = url;

      var resultSink = sink || this.ArraySink.create();
      sink = this.decorateSink_(resultSink, skip, limit, order, predicate);

      // TODO: This should be streamed for better handling of large responses.
      return req.send().then(function(resp) {
        if ( ! resp.success ) {
          return Promise.reject(foam.dao.InternalException.create());
        }
        return resp.payload;
      }).then(function(payload) {
        var data = JSON.parse(payload);
        var fc = this.FlowControl.create();

        for ( var key in data ) {
          if ( fc.stopped ) break;
          if ( fc.errorEvt ) {
            sink.error && sink.error(fc.errorEvt);
            future.set(sink);
            break;
          }

          var obj = foam.json.parse(
            foam.json.parseString(data[key].data));
          if ( this.timestampProperty ) {
            this.timestampProperty.set(obj, data[key].lastUpdate);
          }

          sink.put(obj, null, fc);
        }
        sink.eof();

        return resultSink;
      }.bind(this), function(resp) {
        var e = foam.dao.InternalException.create();
        sink.error(e);
        return Promise.reject(e);
      });
    }
  ],
  listeners: [
    function onPut(s, _, _, data) {
      // PATH is one of
      // / -> new objects
      // /key -> new object
      // /key/data -> updated object

      var path = data.path;
      if ( path == "/" ) {
        // All data removed?
        if ( data.data == null ) {
          this.on.reset.pub();
          return;
        }

        for ( var key in data.data ) {
          var obj = foam.json.parse(foam.json.parseString(data.data[key].data));
          if ( this.timestampProperty ) {
            this.timestampProperty.set(obj, data.data[key].lastUpdate);
          }
          this.on.put.pub(obj);
        }
        return;
      } else if ( path.lastIndexOf('/') === 0 ) {
        if ( data.data == null ) {
          var obj = this.of.create();
          obj.id = path.substring(1)
          this.on.remove.pub(obj);
          return;
        }
        var obj = foam.json.parse(foam.json.parseString(data.data.data));
        if ( this.timestampProperty ) {
          this.timestampProperty.set(obj, data.data.lastUpdate);
        }
        this.on.put.pub(obj);
      } else if ( path.indexOf('/data') === path.length - 5 ) {
        // These last two events shouldn't happen unless somebody is editing
        // the underlying firebase data by hand.

        // Data of an existing row updated.
        debugger;
        var id = path.substring(1);
        id = id.substring(0, id.indexOf('/'));
        this.find(id).then(function(obj) {
          this.on.put.pub(obj);
        }.bind(this));

        // var obj = foam.json.parse(foam.json.parseString(data.data));
        // this.on.put.pub(obj);
      } else if ( path.indexOf('/lastUpdate') === path.length - 11 ) {
        // Timestamp of an existing row updated, do anything?
        // presumably if the object itself hasn't been updated we don't care
        // if it has been updated we should get an event for that.

        debugger;
        var id = path.substring(1);
        id = id.substring(0, id.indexOf('/'));
        this.find(id).then(function(obj) {
          this.on.put.pub(obj);
        }.bind(this));
      }
    },
    function onPatch(s, _, _, data) {
          // TODO: What does a patch even look like?
      debugger;
    }
  ]
});

foam.CLASS({
  package: 'com.firebase',
  name: 'SafariFirebaseDAO',
  extends: 'com.firebase.FirebaseDAO',
  requires: [
    'foam.net.XHRHTTPRequest as HTTPRequest',
    'foam.net.SafariEventSource as EventSource'
  ],
  properties: [
    ['enableStreaming', false]
  ]
});
<|endoftext|>


<commit_before>var editor;

$(document).ready(function() {

  // 构造上中右三个面板
  $('body').layout({
    resizerDblClickToggle: false,
    resizable: false,
    slidable: false,
    togglerLength_open: '100%',
    togglerLength_closed: '100%',
    north: {
      size: '1px', // 只是占位，真实大小由内容决定
      togglerTip_open: 'Hide Toolbar',
      togglerTip_closed: 'Show Toolbar'
    },
    east: {
      size: '50%',
      togglerTip_open: 'Hide Preview',
      togglerTip_closed: 'Show Preview',
      onresize: function() {
        editor.session.setUseWrapMode(false); // ACE的wrap貌似有问题，这里手动触发一下。
        editor.session.setUseWrapMode(true);
      }
    }
  });

  // 左侧编辑器
  editor = ace.edit("editor");
  editor.$blockScrolling = Infinity;
  editor.renderer.setShowPrintMargin(false);
  editor.session.setMode("ace/mode/markdown");
  editor.session.setUseWrapMode(true);
  editor.setFontSize('14px');
  editor.focus();

  // 设置marked
  var renderer = new marked.Renderer();
  renderer.listitem = function(text) {
    if(!/^\[[ x]\]\s/.test(text)) {
      return marked.Renderer.prototype.listitem(text);
    }
    // 任务列表
    var checkbox = $('<input type="checkbox" class="taskbox" disabled="disabled"/>');
    if(/^\[x\]\s/.test(text)) { // 完成的任务列表
      checkbox.attr('checked', true);
    }
    return $(marked.Renderer.prototype.listitem(text.substring(4))).addClass('none-style').prepend(checkbox)[0].outerHTML;
  }
  marked.setOptions({
    renderer: renderer,
    gfm: true,
    tables: true,
    breaks: true,
    pedantic: false,
    sanitize: false,
    smartLists: true,
    smartypants: true
  });

  // 实时监听用户的编辑
  editor.session.on('change', function(){
    $('.markdown-body').html(marked(editor.session.getValue())); // 实时预览
    $('pre').addClass('prettyprint').addClass('linenums');
    prettyPrint(); // 语法高亮
  });

  // toolbar actions
  $('.heading-icon').click(function(){ // h1 - h6 heading
    editor.navigateLineStart();
    editor.insert('#'.repeat($(this).data('level')) + ' ');
    editor.focus();
  });
  $('.styling-icon').click(function(){ // styling icons
    var selectionRange = editor.selection.getRange();
    var selectedText = editor.session.getTextRange(selectionRange);
    var modifier = $(this).data('modifier');
    editor.session.replace(selectionRange, modifier + selectedText + modifier);
    editor.focus();
  });

});
<commit_msg>Styling icons apply to current word if nothing is selected<commit_after>var editor;

$(document).ready(function() {

  // 构造上中右三个面板
  $('body').layout({
    resizerDblClickToggle: false,
    resizable: false,
    slidable: false,
    togglerLength_open: '100%',
    togglerLength_closed: '100%',
    north: {
      size: '1px', // 只是占位，真实大小由内容决定
      togglerTip_open: 'Hide Toolbar',
      togglerTip_closed: 'Show Toolbar'
    },
    east: {
      size: '50%',
      togglerTip_open: 'Hide Preview',
      togglerTip_closed: 'Show Preview',
      onresize: function() {
        editor.session.setUseWrapMode(false); // ACE的wrap貌似有问题，这里手动触发一下。
        editor.session.setUseWrapMode(true);
      }
    }
  });

  // 左侧编辑器
  editor = ace.edit("editor");
  editor.$blockScrolling = Infinity;
  editor.renderer.setShowPrintMargin(false);
  editor.session.setMode("ace/mode/markdown");
  editor.session.setUseWrapMode(true);
  editor.setFontSize('14px');
  editor.focus();

  // 设置marked
  var renderer = new marked.Renderer();
  renderer.listitem = function(text) {
    if(!/^\[[ x]\]\s/.test(text)) {
      return marked.Renderer.prototype.listitem(text);
    }
    // 任务列表
    var checkbox = $('<input type="checkbox" class="taskbox" disabled="disabled"/>');
    if(/^\[x\]\s/.test(text)) { // 完成的任务列表
      checkbox.attr('checked', true);
    }
    return $(marked.Renderer.prototype.listitem(text.substring(4))).addClass('none-style').prepend(checkbox)[0].outerHTML;
  }
  marked.setOptions({
    renderer: renderer,
    gfm: true,
    tables: true,
    breaks: true,
    pedantic: false,
    sanitize: false,
    smartLists: true,
    smartypants: true
  });

  // 实时监听用户的编辑
  editor.session.on('change', function(){
    $('.markdown-body').html(marked(editor.session.getValue())); // 实时预览
    $('pre').addClass('prettyprint').addClass('linenums');
    prettyPrint(); // 语法高亮
  });

  // toolbar actions
  $('.heading-icon').click(function(){ // h1 - h6 heading
    editor.navigateLineStart();
    editor.insert('#'.repeat($(this).data('level')) + ' ');
    editor.focus();
  });
  $('.styling-icon').click(function(){ // styling icons
    var range = editor.selection.getRange();
    if(range.isEmpty()) { // 没有选中任何东西
      range = editor.selection.getWordRange(range.start.row, range.start.column) // 当前单词的range
    }
    var selectedText = editor.session.getTextRange(range);
    var modifier = $(this).data('modifier');
    editor.session.replace(range, modifier + selectedText + modifier);
    editor.focus();
  });

});
<|endoftext|>


<commit_before>import React from 'react'
import { connect } from 'react-redux'
import { bindActionCreators } from 'redux';
import { Route, Router } from 'react-router-dom'
import CSSTransitionGroup from 'react-transition-group/CSSTransitionGroup'
import createHistory from 'history/createHashHistory'
const history = createHistory()

/*
 全局导入less
 */
import './app.less'

import * as global from 'actions/global'
import asyncComponent from './AsyncComponent'

import Home from 'containers/Home/Home'
import ReactChildrenMap from 'utils/ReactChildrenMap'
const Search = asyncComponent(() => import(/* webpackChunkName: "search" */ "./containers/Search/Search"))
const BookList = asyncComponent(() => import(/* webpackChunkName: "bookList" */ "./containers/BookList/BookListContainer"))

@connect (
    state => {return {...state.global}},
    dispatch => bindActionCreators(global, dispatch)
)
export default class App extends React.Component {

    componentDidMount() {
        window.addEventListener('hashchange', () => {
           this.props.currentAnimate('normal')
        })
    }

  render() {
      const { animateCls } = this.props
      return (
          <Router history={history}>
              <Route render={({ location }) => {
                  return(
                      <CSSTransitionGroup
                          transitionName={animateCls}
                          transitionEnter={true}
                          transitionLeave={true}
                          transitionEnterTimeout={400}
                          transitionLeaveTimeout={400}
                      >
                          <ReactChildrenMap key={location.pathname}>
                              <Route location={location} exact path="/" component={Home} />
                              <Route location={location} path="/search" component={Search} />
                              <Route location={location} path="/bookList/:bookId" component={BookList} />
                          </ReactChildrenMap>
                      </CSSTransitionGroup>
                  )
              }}/>
          </Router>
    );
  }
}<commit_msg>app.js路径修改<commit_after>import React from 'react'
import { connect } from 'react-redux'
import { bindActionCreators } from 'redux';
import { Route, Router } from 'react-router-dom'
import CSSTransitionGroup from 'react-transition-group/CSSTransitionGroup'
import createHistory from 'history/createHashHistory'
const history = createHistory()

/*
 全局导入less
 */
import './app.less'

import * as global from 'actions/global'
import asyncComponent from './AsyncComponent'

import Home from 'containers/Home/Home'
import ReactChildrenMap from 'utils/ReactChildrenMap'
const Search = asyncComponent(() => import(/* webpackChunkName: "search" */ "./containers/Search/Search"))
const BookList = asyncComponent(() => import(/* webpackChunkName: "bookList" */ "./containers/BookList/BookList"))

@connect (
    state => {return {...state.global}},
    dispatch => bindActionCreators(global, dispatch)
)
export default class App extends React.Component {

    componentDidMount() {
        window.addEventListener('hashchange', () => {
           this.props.currentAnimate('normal')
        })
    }

  render() {
      const { animateCls } = this.props
      return (
          <Router history={history}>
              <Route render={({ location }) => {
                  return(
                      <CSSTransitionGroup
                          transitionName={animateCls}
                          transitionEnter={true}
                          transitionLeave={true}
                          transitionEnterTimeout={400}
                          transitionLeaveTimeout={400}
                      >
                          <ReactChildrenMap key={location.pathname}>
                              <Route location={location} exact path="/" component={Home} />
                              <Route location={location} path="/search" component={Search} />
                              <Route location={location} path="/bookList/:bookId" component={BookList} />
                          </ReactChildrenMap>
                      </CSSTransitionGroup>
                  )
              }}/>
          </Router>
    );
  }
}<|endoftext|>


<commit_before><commit_msg>Update static/vendors/ace-builds/src-min-noconflict/mode-swig.js<commit_after><|endoftext|>


<commit_before>var colors = require('colors/safe'),
    prompt = require('prompt'),
    moment = require('moment'),
    path = require('./path'),
    shell = require('shelljs'),
    yaml = require('js-yaml'),
    fs = require('fs');

var toTitleCase = function(str) {
    return str.replace(/\w\S*/g, function(text){
        return text.charAt(0).toUpperCase() + text.substr(1).toLowerCase();
    });
};

var saveConfig = function(result) {
    var config = {
        title: result.title,
        date: result.date,
        author: toTitleCase(result.author),
        public_dir: path.trimRight(result.public_dir),
        url: result.url,
        pages: path.inside(result.pages),
        http_server: result.http_server,
        use_markdown: true,
        theme: result.theme,
        style: {
            docs: path.inside(result['style.docs']),
            css: result['style.css'],
            images: path.inside(result['style.images']),
            fonts: path.inside(result['style.fonts'])
        }
    };
    var configFile = process.cwd() + '/a-pollo.yml';
    fs.writeFileSync(process.cwd() + '/a-pollo.yml', yaml.safeDump(config));
    console.log('Configuration successfully saved to ' + configFile.toString().yellow);
    console.log('If you\'d like to customize default theme header and footer please check out the config example here: ' + 'https://www.npmjs.com/package/a-pollo'.yellow);
    console.log('Now you can run a-pollo without '+ 'init'.yellow +' parameter');
};

var proceed = function () {
    prompt.start();
    prompt.message = '';
    prompt.delimiter = '';

    prompt.get([
        {
            name: 'title',
            description: 'title'.yellow,
            default: 'Untitled client project',
            type: 'string'
        },{
            name: 'date',
            description: 'date'.yellow,
            default: moment().format('YYYY-MM-DD'),
            type: 'string'
        },{
            name: 'author',
            description: 'author'.yellow + ' (Your Name)'.red,
            required: true,
            message: 'Please, insert your name',
            type: 'string'
        },{
            name: 'public_dir',
            description: 'public_dir'.yellow,
            default: 'public',
            type: 'string'
        },{
            name: 'url',
            description: 'url'.yellow,
            default: 'http://localhost:7777',
            type: 'string'
        },{
            name: 'pages',
            description: 'pages'.yellow + ' (Path to markdown or HTML static pages, you can leave it empty)'.white,
            type: 'string'
        },{
            name: 'http_server',
            description: 'http_server'.yellow,
            default: true,
            type: 'string'
        },{
            name: 'theme',
            description: 'theme'.yellow,
            default: 'a-pollo',
            type: 'string'
        },{
            name: 'style.docs',
            description: 'style.docs'.yellow + ' (Path to documented files, SASS, LESS or CSS supported)'.red,
            required: true,
            message: 'Insert something like: ' + 'path/to/widgets/'.yellow,
            type: 'string'
        },{
            name: 'style.css',
            description: 'style.css'.yellow + ' (Path to generated CSS)'.red,
            required: true,
            message: 'A-pollo will copy CSS inside the generated style guide, something like: ' + 'path/to/css/'.yellow,
            type: 'string'
        },{
            name: 'style.images',
            description: 'style.images'.yellow + ' (Path to images loaded by your CSS)'.red,
            type: 'string'
        },{
            name: 'style.fonts',
            description: 'style.fonts'.yellow + ' (Path to fonts loaded by your CSS)'.red,
            type: 'string'
        }
    ], function (err, result) {
        saveConfig(result);
    });
};

exports.start = function () {

    var filename = process.cwd() + 'a-pollo.yml';
    if (shell.test('-e', filename)) {
        console.log('Config file ' + colors.bgBlack(colors.green(' a-pollo.yml ')) + ' found.');
        console.log('If you want to create it again, please delete it first, or run a-pollo without ' + 'init'.yellow + ' param.');
    } else {
        console.log('This procell will help you to generate the config ' + colors.bgBlack(colors.green(' a-pollo.yml ')) + ' file into your project.');
        proceed();
    }
};
<commit_msg>Fix grammar for init command step<commit_after>var colors = require('colors/safe'),
    prompt = require('prompt'),
    moment = require('moment'),
    path = require('./path'),
    shell = require('shelljs'),
    yaml = require('js-yaml'),
    fs = require('fs');

var toTitleCase = function(str) {
    return str.replace(/\w\S*/g, function(text){
        return text.charAt(0).toUpperCase() + text.substr(1).toLowerCase();
    });
};

var saveConfig = function(result) {
    var config = {
        title: result.title,
        date: result.date,
        author: toTitleCase(result.author),
        public_dir: path.trimRight(result.public_dir),
        url: result.url,
        pages: path.inside(result.pages),
        http_server: result.http_server,
        use_markdown: true,
        theme: result.theme,
        style: {
            docs: path.inside(result['style.docs']),
            css: result['style.css'],
            images: path.inside(result['style.images']),
            fonts: path.inside(result['style.fonts'])
        }
    };
    var configFile = process.cwd() + '/a-pollo.yml';
    fs.writeFileSync(process.cwd() + '/a-pollo.yml', yaml.safeDump(config));
    console.log('Configuration successfully saved to ' + configFile.toString().yellow);
    console.log('If you\'d like to customize default theme header and footer please check out the config example here: ' + 'https://www.npmjs.com/package/a-pollo'.yellow);
    console.log('Now you can run a-pollo without '+ 'init'.yellow +' parameter');
};

var proceed = function () {
    prompt.start();
    prompt.message = '';
    prompt.delimiter = '';

    prompt.get([
        {
            name: 'title',
            description: 'title'.yellow,
            default: 'Untitled client project',
            type: 'string'
        },{
            name: 'date',
            description: 'date'.yellow,
            default: moment().format('YYYY-MM-DD'),
            type: 'string'
        },{
            name: 'author',
            description: 'author'.yellow + ' (Your Name)'.red,
            required: true,
            message: 'Please, insert your name',
            type: 'string'
        },{
            name: 'public_dir',
            description: 'public_dir'.yellow,
            default: 'public',
            type: 'string'
        },{
            name: 'url',
            description: 'url'.yellow,
            default: 'http://localhost:7777',
            type: 'string'
        },{
            name: 'pages',
            description: 'pages'.yellow + ' (Path to markdown or HTML static pages, you can leave it empty)'.white,
            type: 'string'
        },{
            name: 'http_server',
            description: 'http_server'.yellow,
            default: true,
            type: 'string'
        },{
            name: 'theme',
            description: 'theme'.yellow,
            default: 'a-pollo',
            type: 'string'
        },{
            name: 'style.docs',
            description: 'style.docs'.yellow + ' (Path to documented files you will write, SASS, LESS or CSS supported)'.red,
            required: true,
            message: 'Insert something like: ' + 'path/to/widgets/'.yellow,
            type: 'string'
        },{
            name: 'style.css',
            description: 'style.css'.yellow + ' (Path to generated CSS)'.red,
            required: true,
            message: 'A-pollo will copy CSS inside the generated style guide, something like: ' + 'path/to/css/'.yellow,
            type: 'string'
        },{
            name: 'style.images',
            description: 'style.images'.yellow + ' (Path to images loaded by your CSS)'.red,
            type: 'string'
        },{
            name: 'style.fonts',
            description: 'style.fonts'.yellow + ' (Path to fonts loaded by your CSS)'.red,
            type: 'string'
        }
    ], function (err, result) {
        saveConfig(result);
    });
};

exports.start = function () {

    var filename = process.cwd() + 'a-pollo.yml';
    if (shell.test('-e', filename)) {
        console.log('Config file ' + colors.bgBlack(colors.green(' a-pollo.yml ')) + ' found.');
        console.log('If you want to create it again, please delete it first, or run a-pollo without ' + 'init'.yellow + ' param.');
    } else {
        console.log('This procell will help you to generate the config ' + colors.bgBlack(colors.green(' a-pollo.yml ')) + ' file into your project.');
        proceed();
    }
};
<|endoftext|>