<commit_before>/**
 * Shopware 4.0
 * Copyright © 2012 shopware AG
 *
 * According to our dual licensing model, this program can be used either
 * under the terms of the GNU Affero General Public License, version 3,
 * or under a proprietary license.
 *
 * The texts of the GNU Affero General Public License with an additional
 * permission and of our proprietary license can be found at and
 * in the LICENSE file you have received along with this program.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Affero General Public License for more details.
 *
 * "Shopware" is a registered trademark of shopware AG.
 * The licensing of the program under the AGPLv3 does not imply a
 * trademark license. Therefore any rights, title and interest in
 * our trademarks remain entirely with us.
 */
/**
 * Custom Ext.loader getPath method
 *
 * This bends the controller/model/store/view paths
 * to our shopware default paths.
 *
 *
 * @category   Enlight
 * @package    Enlight_ExtJs
 * @copyright  Copyright (c) 2011, shopware AG (http://www.shopware.de)
 * @license    http://enlight.de/license     New BSD License
 */

(function() {
    /**
     * Currently open loader requests
     *
     * @type { Object }
     */
    var requestMap = {};

    /**
     * Create and return a requestKey (cacheKey) for the given path and files
     *
     * @param { string } path
     * @param { string|array } files
     * @return { string }
     */
    var getRequestKey = Ext.bind(function(path, files) {
        files = (typeof files == 'string') ? [files] : files;

        return path + ',' + files.join(',');
    }, Ext.Loader);

    /**
     * Abort the currently running async request with the given requestInfo
     *
     * @param { object }
     */
    var abortAsyncRequest = Ext.bind(function(requestInfo) {
        switch(requestInfo.mode) {
            case 'xhr':
                Ext.Ajax.abort(requestInfo.identifier);
                this.numPendingFiles -= requestInfo.fileCount;
                break;
            default:
                Ext.Error.raise("Unknown requestInfo type. Can not abort");
        }
    }, Ext.Loader);

    /**
     * Take a requestKey and stop a possibly running asynchronous request for it
     *
     * @param { string } requestKey
     */
    var cleanIfAsyncRequestExists = Ext.bind(function(requestKey) {
        if (requestMap.hasOwnProperty(requestKey)) {
            abortAsyncRequest(requestMap[requestKey]);
            delete requestMap[requestKey];
        }
    }, Ext.Loader);

    /**
     * Load all the classes using bulk load specified by the given namespace array
     *
     * @param { array } namespaces
     */
    var loadNamespacedClasses = Ext.bind(function(namespaces) {

        var host = window.location.protocol + "//" + window.location.hostname;

        Ext.iterate(namespaces, function(key, namespace){
            var path = namespace.path,
                cacheKey,
                disableCachingValue = this.getConfig('disableCachingValue'),
                requestMethod = "post",
                tmpPath,
                files = [];

            // Get request of main subapplication app.js
            if (namespace.files.length <= 1 && namespace.files[0].indexOf('?file') !== -1) {
                path += namespace.files[0];
                requestMethod = "get";
            } else {
                // If BulkRequest check if GET-Request is possible, if not POST-Fallback is used
                tmpPath = path;
                tmpPath += "?f=";

                files = [];
                Ext.each(namespace.files, function (file) {
                    // shrink filenames, will be expanded in ScriptRenderer-Plugin
                    file = file.replace('/^model\//', 'm/');
                    file = file.replace('/^controller\//', 'c/');
                    file = file.replace('/^view\//', 'f/');

                    files.push(file);
                });

                tmpPath += files.join('|');

                // see: http://stackoverflow.com/questions/417142/what-is-the-maximum-length-of-a-url-in-different-browsers
                // 2000 - 50 Chars Buffer for disableCachingParam etc.
                if (tmpPath.length + host.length < 1950) {
                    requestMethod = "get";
                    path = tmpPath;
                }
            }

            if (!this.getConfig('caching')) {
                path += (requestMethod === 'get') ? '&' : '?';
                path += this.getConfig('disableCachingParam') + '=' + disableCachingValue;
            }

            cacheKey = getRequestKey(path, namespace.files);

            if (this.syncModeEnabled) {
                cleanIfAsyncRequestExists(cacheKey);
            } else {
                // An asynchrounous request for the given requestKey may already be running and waiting for completion.
                // In this case loading it a second time should not be done.
                if (requestMap.hasOwnProperty(cacheKey)) {
                    return;
                }
            }

            var xhr = Ext.Ajax.request({
                url: path,
                method: requestMethod,
                disableCaching: false,
                async: !this.syncModeEnabled,
                params: (requestMethod === 'get')
                        ? (null)
                        : ({ 'file[]': namespace.files }),
                scope: this,
                success: function(response) {
                    Ext.globalEval(response.responseText + "\n//@ sourceURL=" + path);

                    this.onFilesLoaded(namespace.classNames);

                    // Remove handled request from requestMap
                    if (requestMap.hasOwnProperty(cacheKey)) {
                        delete requestMap[cacheKey];
                    }
                },
                failure: function(xhr) {
                    cleanIfAsyncRequestExists(cacheKey);
                    // Re-request classes. The old callbacks stays inside the
                    // queue and will be triggered when loading is ready.
                    Ext.require(namespace.classNames);
                }
            });

            if (!this.syncModeEnabled) {
                requestMap[cacheKey] = {
                    mode: 'xhr',
                    identifier: xhr,
                    fileCount: namespace.files.length
                };
            }
        }, this);
    }, Ext.Loader);

    /**
     * Get the loader path for the given classname and prefix
     *
     * @param { string } className
     * @param { string } prefix
     * @return { array }
     */
    Ext.Loader.getPath = function(className, prefix) {
        var path = '',
            paths = this.config.paths,
            suffix = this.config.suffixes[prefix] !== undefined ? this.config.suffixes[prefix] : '.js';

        if (prefix.length > 0) {
            if (prefix === className) {
                return paths[prefix];
            }

            path = paths[prefix];
            className = className.substring(prefix.length + 1);
        }

        if (path.length > 0) {
            path = path.replace(/\/+$/, '') + '/';
        }

        return [path.replace(/\/\.\//g, '/'), className.replace(/\./g, "/") + suffix];
    };

    Ext.Loader.config.disableCaching = false;
    Ext.Loader.config.caching = true;

    Ext.Loader.requestQueue = [];

    Ext.Loader.require = function(expressions, fn, scope, excludes) {
        var Manager = Ext.ClassManager;
        var filePath, expression, exclude, className, excluded = {},
            excludedClassNames = [],
            possibleClassNames = [],
            possibleClassName, classNames = [],
            namespaces = {}, separatedPath, prefix,
            i, j, ln, subLn;

        if(!this.getConfig('disableCachingValue')) {
            this.setConfig('disableCachingValue', Ext.Date.now());
        }
        if(this.getConfig('disableCaching')) {
            this.setConfig('caching', false);
            this.setConfig('disableCaching', false);
        }

        var disableCachingValue = this.getConfig('disableCachingValue'),
                disableCaching = !this.getConfig('caching');

        expressions = Ext.Array.from(expressions);
        excludes = Ext.Array.from(excludes);

        fn = fn || Ext.emptyFn;

        scope = scope || Ext.global;

        for (i = 0, ln = excludes.length; i < ln; i++) {
            exclude = excludes[i];

            if (typeof exclude === 'string' && exclude.length > 0) {
                excludedClassNames = Manager.getNamesByExpression(exclude);

                for (j = 0, subLn = excludedClassNames.length; j < subLn; j++) {
                    excluded[excludedClassNames[j]] = true;
                }
            }
        }

        for (i = 0, ln = expressions.length; i < ln; i++) {
            expression = expressions[i];

            if (typeof expression === 'string' && expression.length > 0) {
                possibleClassNames = Manager.getNamesByExpression(expression);

                for (j = 0, subLn = possibleClassNames.length; j < subLn; j++) {
                    possibleClassName = possibleClassNames[j];

                    if (!excluded.hasOwnProperty(possibleClassName) && !Manager.isCreated(possibleClassName)) {
                        Ext.Array.include(classNames, possibleClassName);
                    }
                }
            }
        }

        // If the dynamic dependency feature is not being used, throw an error
        // if the dependencies are not defined
        if (!this.config.enabled) {
            if (classNames.length > 0) {
                Ext.Error.raise({
                    sourceClass: "Ext.Loader",
                    sourceMethod: "require",
                    msg: "Ext.Loader is not enabled, so dependencies cannot be resolved dynamically. " +
                            "Missing required class" + ((classNames.length > 1) ? "es" : "") + ": " + classNames.join(', ')
                });
            }
        }

        if (classNames.length === 0) {
            fn.call(scope);
            return this;
        }

        // If the request is synchronous pushing into the queue is not needed
        if (!this.syncModeEnabled) {
            this.queue.push({
                requires: classNames,
                callback: fn,
                scope: scope
            });
        }

        classNames = classNames.slice();

        for (i = 0, ln = classNames.length; i < ln; i++) {
            className = classNames[i];

            if (!this.isFileLoaded.hasOwnProperty(className) || !this.isFileLoaded[className]) {
                this.isFileLoaded[className] = false;

                prefix = this.getPrefix(className);
                separatedPath = this.getPath(className, prefix);
                filePath = separatedPath.join('');

                this.numPendingFiles++;

                // Collect and sort bulk loaded files by prefix
                if(!namespaces[prefix]) {
                    namespaces[prefix] = { 'prefix': prefix, 'path': separatedPath[0], 'files': [], 'classNames': [] };
                }
                namespaces[prefix]['files'].push(separatedPath[1]);
                namespaces[prefix]['classNames'].push(className);
            } else {
                // Asynchrounous request, with already loaded deoendency:
                // Process queue to ensure the callback is executed.
                if (!this.syncModeEnabled) {
                    this.refreshQueue();
                }
            }
        }

        loadNamespacedClasses(namespaces);

        // Callbacks are not executed through the queue in syncmode, therefore it needs to be done manually
        if (this.syncModeEnabled) {
            fn.call(scope);
        }

        return this;
    };

    /**
     * @private
     * @param { String } classNames
     */
    Ext.Loader.onFilesLoaded = function(classNames) {
        var me = this;

        Ext.iterate(classNames, function(className){
            me.numLoadedFiles++;
            me.isFileLoaded[className] = true;
            me.numPendingFiles--;
        });

        me.refreshQueue();
    };

    /**
     * Sets the path of a namespace. For Example:
     *
     *     Ext.Loader.setPath('Ext', '.');
     *
     * @param { String/Object } name See { @link Ext.Function#flexSetter flexSetter }
     * @param { String } path See { @link Ext.Function#flexSetter flexSetter }
     * @param bulk
     * @param suffix
     * @return { Ext.Loader } this
     * @method
     */
    Ext.Loader.setPath = function(name, path, suffix, bulk) {
        this.config.paths[name] = path;
        if(this.config.suffixes === undefined) {
            this.config.suffixes = [];
        }
        if(suffix !== undefined) {
            this.config.suffixes[name] = suffix;
        }
        return this;
    };
})();
<commit_msg>SW-5847 - Fix regex to shorten extjs-filenames<commit_after>/**
 * Shopware 4.0
 * Copyright © 2012 shopware AG
 *
 * According to our dual licensing model, this program can be used either
 * under the terms of the GNU Affero General Public License, version 3,
 * or under a proprietary license.
 *
 * The texts of the GNU Affero General Public License with an additional
 * permission and of our proprietary license can be found at and
 * in the LICENSE file you have received along with this program.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Affero General Public License for more details.
 *
 * "Shopware" is a registered trademark of shopware AG.
 * The licensing of the program under the AGPLv3 does not imply a
 * trademark license. Therefore any rights, title and interest in
 * our trademarks remain entirely with us.
 */
/**
 * Custom Ext.loader getPath method
 *
 * This bends the controller/model/store/view paths
 * to our shopware default paths.
 *
 *
 * @category   Enlight
 * @package    Enlight_ExtJs
 * @copyright  Copyright (c) 2011, shopware AG (http://www.shopware.de)
 * @license    http://enlight.de/license     New BSD License
 */

(function() {
    /**
     * Currently open loader requests
     *
     * @type { Object }
     */
    var requestMap = {};

    /**
     * Create and return a requestKey (cacheKey) for the given path and files
     *
     * @param { string } path
     * @param { string|array } files
     * @return { string }
     */
    var getRequestKey = Ext.bind(function(path, files) {
        files = (typeof files == 'string') ? [files] : files;

        return path + ',' + files.join(',');
    }, Ext.Loader);

    /**
     * Abort the currently running async request with the given requestInfo
     *
     * @param { object }
     */
    var abortAsyncRequest = Ext.bind(function(requestInfo) {
        switch(requestInfo.mode) {
            case 'xhr':
                Ext.Ajax.abort(requestInfo.identifier);
                this.numPendingFiles -= requestInfo.fileCount;
                break;
            default:
                Ext.Error.raise("Unknown requestInfo type. Can not abort");
        }
    }, Ext.Loader);

    /**
     * Take a requestKey and stop a possibly running asynchronous request for it
     *
     * @param { string } requestKey
     */
    var cleanIfAsyncRequestExists = Ext.bind(function(requestKey) {
        if (requestMap.hasOwnProperty(requestKey)) {
            abortAsyncRequest(requestMap[requestKey]);
            delete requestMap[requestKey];
        }
    }, Ext.Loader);

    /**
     * Load all the classes using bulk load specified by the given namespace array
     *
     * @param { array } namespaces
     */
    var loadNamespacedClasses = Ext.bind(function(namespaces) {

        var host = window.location.protocol + "//" + window.location.hostname;

        Ext.iterate(namespaces, function(key, namespace){
            var path = namespace.path,
                cacheKey,
                disableCachingValue = this.getConfig('disableCachingValue'),
                requestMethod = "post",
                tmpPath,
                files = [];

            // Get request of main subapplication app.js
            if (namespace.files.length <= 1 && namespace.files[0].indexOf('?file') !== -1) {
                path += namespace.files[0];
                requestMethod = "get";
            } else {
                // If BulkRequest check if GET-Request is possible, if not POST-Fallback is used
                tmpPath = path;
                tmpPath += "?f=";

                files = [];
                Ext.each(namespace.files, function (file) {
                    // shrink filenames, will be expanded in ScriptRenderer-Plugin
                    file = file.replace(/^model\//, 'm/');
                    file = file.replace(/^controller\//, 'c/');
                    file = file.replace(/^view\//, 'v/');

                    files.push(file);
                });

                tmpPath += files.join('|');

                // see: http://stackoverflow.com/questions/417142/what-is-the-maximum-length-of-a-url-in-different-browsers
                // 2000 - 50 Chars Buffer for disableCachingParam etc.
                if (tmpPath.length + host.length < 1950) {
                    requestMethod = "get";
                    path = tmpPath;
                }
            }

            if (!this.getConfig('caching')) {
                path += (requestMethod === 'get') ? '&' : '?';
                path += this.getConfig('disableCachingParam') + '=' + disableCachingValue;
            }

            cacheKey = getRequestKey(path, namespace.files);

            if (this.syncModeEnabled) {
                cleanIfAsyncRequestExists(cacheKey);
            } else {
                // An asynchrounous request for the given requestKey may already be running and waiting for completion.
                // In this case loading it a second time should not be done.
                if (requestMap.hasOwnProperty(cacheKey)) {
                    return;
                }
            }

            var xhr = Ext.Ajax.request({
                url: path,
                method: requestMethod,
                disableCaching: false,
                async: !this.syncModeEnabled,
                params: (requestMethod === 'get')
                        ? (null)
                        : ({ 'file[]': namespace.files }),
                scope: this,
                success: function(response) {
                    Ext.globalEval(response.responseText + "\n//@ sourceURL=" + path);

                    this.onFilesLoaded(namespace.classNames);

                    // Remove handled request from requestMap
                    if (requestMap.hasOwnProperty(cacheKey)) {
                        delete requestMap[cacheKey];
                    }
                },
                failure: function(xhr) {
                    cleanIfAsyncRequestExists(cacheKey);
                    // Re-request classes. The old callbacks stays inside the
                    // queue and will be triggered when loading is ready.
                    Ext.require(namespace.classNames);
                }
            });

            if (!this.syncModeEnabled) {
                requestMap[cacheKey] = {
                    mode: 'xhr',
                    identifier: xhr,
                    fileCount: namespace.files.length
                };
            }
        }, this);
    }, Ext.Loader);

    /**
     * Get the loader path for the given classname and prefix
     *
     * @param { string } className
     * @param { string } prefix
     * @return { array }
     */
    Ext.Loader.getPath = function(className, prefix) {
        var path = '',
            paths = this.config.paths,
            suffix = this.config.suffixes[prefix] !== undefined ? this.config.suffixes[prefix] : '.js';

        if (prefix.length > 0) {
            if (prefix === className) {
                return paths[prefix];
            }

            path = paths[prefix];
            className = className.substring(prefix.length + 1);
        }

        if (path.length > 0) {
            path = path.replace(/\/+$/, '') + '/';
        }

        return [path.replace(/\/\.\//g, '/'), className.replace(/\./g, "/") + suffix];
    };

    Ext.Loader.config.disableCaching = false;
    Ext.Loader.config.caching = true;

    Ext.Loader.requestQueue = [];

    Ext.Loader.require = function(expressions, fn, scope, excludes) {
        var Manager = Ext.ClassManager;
        var filePath, expression, exclude, className, excluded = {},
            excludedClassNames = [],
            possibleClassNames = [],
            possibleClassName, classNames = [],
            namespaces = {}, separatedPath, prefix,
            i, j, ln, subLn;

        if(!this.getConfig('disableCachingValue')) {
            this.setConfig('disableCachingValue', Ext.Date.now());
        }
        if(this.getConfig('disableCaching')) {
            this.setConfig('caching', false);
            this.setConfig('disableCaching', false);
        }

        var disableCachingValue = this.getConfig('disableCachingValue'),
                disableCaching = !this.getConfig('caching');

        expressions = Ext.Array.from(expressions);
        excludes = Ext.Array.from(excludes);

        fn = fn || Ext.emptyFn;

        scope = scope || Ext.global;

        for (i = 0, ln = excludes.length; i < ln; i++) {
            exclude = excludes[i];

            if (typeof exclude === 'string' && exclude.length > 0) {
                excludedClassNames = Manager.getNamesByExpression(exclude);

                for (j = 0, subLn = excludedClassNames.length; j < subLn; j++) {
                    excluded[excludedClassNames[j]] = true;
                }
            }
        }

        for (i = 0, ln = expressions.length; i < ln; i++) {
            expression = expressions[i];

            if (typeof expression === 'string' && expression.length > 0) {
                possibleClassNames = Manager.getNamesByExpression(expression);

                for (j = 0, subLn = possibleClassNames.length; j < subLn; j++) {
                    possibleClassName = possibleClassNames[j];

                    if (!excluded.hasOwnProperty(possibleClassName) && !Manager.isCreated(possibleClassName)) {
                        Ext.Array.include(classNames, possibleClassName);
                    }
                }
            }
        }

        // If the dynamic dependency feature is not being used, throw an error
        // if the dependencies are not defined
        if (!this.config.enabled) {
            if (classNames.length > 0) {
                Ext.Error.raise({
                    sourceClass: "Ext.Loader",
                    sourceMethod: "require",
                    msg: "Ext.Loader is not enabled, so dependencies cannot be resolved dynamically. " +
                            "Missing required class" + ((classNames.length > 1) ? "es" : "") + ": " + classNames.join(', ')
                });
            }
        }

        if (classNames.length === 0) {
            fn.call(scope);
            return this;
        }

        // If the request is synchronous pushing into the queue is not needed
        if (!this.syncModeEnabled) {
            this.queue.push({
                requires: classNames,
                callback: fn,
                scope: scope
            });
        }

        classNames = classNames.slice();

        for (i = 0, ln = classNames.length; i < ln; i++) {
            className = classNames[i];

            if (!this.isFileLoaded.hasOwnProperty(className) || !this.isFileLoaded[className]) {
                this.isFileLoaded[className] = false;

                prefix = this.getPrefix(className);
                separatedPath = this.getPath(className, prefix);
                filePath = separatedPath.join('');

                this.numPendingFiles++;

                // Collect and sort bulk loaded files by prefix
                if(!namespaces[prefix]) {
                    namespaces[prefix] = { 'prefix': prefix, 'path': separatedPath[0], 'files': [], 'classNames': [] };
                }
                namespaces[prefix]['files'].push(separatedPath[1]);
                namespaces[prefix]['classNames'].push(className);
            } else {
                // Asynchrounous request, with already loaded deoendency:
                // Process queue to ensure the callback is executed.
                if (!this.syncModeEnabled) {
                    this.refreshQueue();
                }
            }
        }

        loadNamespacedClasses(namespaces);

        // Callbacks are not executed through the queue in syncmode, therefore it needs to be done manually
        if (this.syncModeEnabled) {
            fn.call(scope);
        }

        return this;
    };

    /**
     * @private
     * @param { String } classNames
     */
    Ext.Loader.onFilesLoaded = function(classNames) {
        var me = this;

        Ext.iterate(classNames, function(className){
            me.numLoadedFiles++;
            me.isFileLoaded[className] = true;
            me.numPendingFiles--;
        });

        me.refreshQueue();
    };

    /**
     * Sets the path of a namespace. For Example:
     *
     *     Ext.Loader.setPath('Ext', '.');
     *
     * @param { String/Object } name See { @link Ext.Function#flexSetter flexSetter }
     * @param { String } path See { @link Ext.Function#flexSetter flexSetter }
     * @param bulk
     * @param suffix
     * @return { Ext.Loader } this
     * @method
     */
    Ext.Loader.setPath = function(name, path, suffix, bulk) {
        this.config.paths[name] = path;
        if(this.config.suffixes === undefined) {
            this.config.suffixes = [];
        }
        if(suffix !== undefined) {
            this.config.suffixes[name] = suffix;
        }
        return this;
    };
})();
<|endoftext|>


<commit_before>'use strict';

let Session = require("ticket-session");
let moment = require("moment-timezone");

class AggregatorSection {
	constructor(patchwerk, name, keydata = {}) {
		this.name = name;
		this.keydata = keydata;
		this.patchwerk = patchwerk;

		this.keymap = {};
		this.data = [];
		this.rendered = [];

		this.filtering = null;
		this.ordering = null;
		this._invalid = true;
	}

	updateKeydata(value) {
		this.keydata = value;
		return this;
	}

	addr() {
		return this.keydata.emit_path;
	}

	moment() {
		return moment.tz(this.keydata.org_timezone);
	}

	//search
	session(id) {
		// console.log("GETSESSION", code, this.keymap);
		return this.data[this.keymap[id]];
	}

	ticket(idx) {
		return this.rendered[idx];
	}

	//update
	updateLeaf(leaf) {
		//@FIXIT: switch to ticket models
		let session = this.session(leaf.session);
		let tick = session.find(leaf.id);
		tick.getContainer()
			.update(leaf);
		console.log("UPDATE", leaf.id, tick);
		this.render();
		this.order();
	}

	next(curr_idx) {
		let session = this.session(this.rendered[curr_idx].get('session'));
		return session.next();
	}

	order(params = {}) {
		let curr_moment = this.moment();
		params.date = curr_moment.format('YYYY-MM-DD');
		params.now = curr_moment.diff(curr_moment.clone()
			.startOf('day'), 'seconds');
		this.ordering.run(params, false, this.getRendered());
		return this;
	}

	filter(params = {}) {
		let curr_moment = this.moment();
		params.prebook_show_interval = this.keydata.prebook_show_interval;
		params.now = curr_moment.diff(curr_moment.clone()
			.startOf('day'), 'seconds');
		params.state = params.state || '*';
		return this.filtering.run(params, this.ordering.out(), this.getRendered());
	}

	isAppliable(params = {}, entity) {
		return !!(this.filtering.run(params, ['0'], [entity]))[0];
	}

	setIndexers(filter, order) {
		this.filtering = filter;
		this.ordering = order;
	}

	render() {
		let result = [],
			l = this.data.length;
		this.rendered = [];
		while (l--) {
			if (!this.data[l].isInactive())
				this.rendered = this.rendered.concat(this.data[l].render());
		}
		console.log("RENDER");
		this.validate();
		return this.rendered;
	}

	getRendered() {
		//can implement render expiration here
		//if(expired) return this.render()
		if (this.invalid()) {
			this.render();
		}
		return this.rendered;
	}

	invalidate() {
		console.log("INVALIDATE", this.constructor.name);
		this._invalid = true;
	}

	invalid() {
		return this._invalid;
	}

	validate() {
		console.log("VALIDATE");
		this._invalid = false;
	}

	flush() {
		this.keymap = {};
		this.data = [];
		this.rendered = [];
		this.invalid();
		//mb destruct all sessions? they have circular dependencies
	}

	add(session) {
		//only today
		if (this.moment()
			.format('YYYY-MM-DD') !== session.dedication())
			return this;

		let id = session.identifier();
		session.onUpdate(this.invalidate.bind(this));

		if (this.keymap[id] === undefined) {
			this.data.push(session);
			this.keymap[id] = this.data.length - 1;
		} else {
			this.data[this.keymap[id]] = session;
		}
		this.invalidate();
		return this;
	}

	loadIfOutdated() {
		//it is logical because only today sessions can be added
		if (this.data.length > 0 && this.data[0].dedication() < this.moment()
			.format('YYYY-MM-DD')) {
			console.log("OUTDATED");
			this.flush();
			return this.load()
				.then(res => this.render())
				.then(res => this.order());
		} else {
			return Promise.resolve(true);
		}
	}

	load(spec_date) {
		let date = spec_date || this.moment()
			.format('YYYY-MM-DD');
		this.flush();
		return Promise.all([this.patchwerk.get('TicketSession', {
				department: this.name,
				date: date,
				counter: '*'
			}), this.patchwerk.get('Ticket', {
				department: this.name,
				date: date,
				counter: '*'
			})])
			.then(res => {
				// console.log(res);
				let sessions = res[0],
					l = sessions.length,
					session_data;

				while (l--) {
					session_data = sessions[l];
					//@FIXIT
					if (session_data.properties.description !== undefined) {
						this.add(Session(session_data, res[1]));
					}
				}

				// console.log("SESSIONS", this);
				return this;
			})
	}

	saveSession(session) {
		let model = session.extract();
		let date = this.moment()
			.format('YYYY-MM-DD');
		return this.patchwerk.save(model, {
				department: this.name,
				date: date
			})
			.then(res => this.patchwerk.create('TicketSessionLookup', {
				content: session.identifier()
			}, {
				code: session.code()
			}))
			.then(lookup => this.patchwerk.save(lookup, {
				code: session.code()
			}))
			.then(res => session);
	}

	createSession(data) {
		let tmp_session;
		return this.patchwerk.create('TicketSession', data, {
				department: data.organization,
				date: data.dedicated_date,
				counter: "*"
			})
			.then((session) => {
				tmp_session = session;
				return Promise.map(data.uses, t_id =>
					this.patchwerk.get('Ticket', {
						key: t_id
					}));
			})
			.then(t_data => {
				return Session(tmp_session, t_data);
			});

	}

	virtualizeTicket(t_data) {
		let service_data;
		return this.patchwerk.get('Service', {
				department: this.keydata.id,
				counter: _.last(_.split(t_data.service, '-'))
			})
			.then(srv => {
				service_data = srv;
				return this.patchwerk.create('Ticket', t_data, {
					department: t_data.org_destination,
					date: t_data.dedicated_date,
					counter: "*"
				});
			})
			.then(tick => {
				// console.log("a-s crvirticks", tick);
				tick.unlockField('operator')
					.unlockField('destination')
					.modifyPriority('service', service_data.get('priority'));
				let hst = tick.get("history");
				_.map(hst, h_entry => {
					h_entry.local_time = this.moment()
						.format();
				});
				tick.set("history", hst);
				tick.set("called", 0);
				tick.set("inheritance_counter", 0);
				tick.set("source", null);
				tick.set("operator", null);
				tick.set("destination", null);

				if (tick.get('booking_method') == 'live') {
					tick.set('time_description', service_data.live_operation_time);
				} else {
					let td = tick.time_description;
					tick.set("time_description", [td[0], td[0] + service_data.prebook_operation_time * tick.get("service_count")])
				}
				return tick;
			});
	}

	createTickets(data) {
		let b_data = data.constructor === Array ? data : [data];

		return Promise.map(b_data, t_data => {
			t_data.booking_date = this.moment()
				.format();
			console.log("TDATA", t_data);

			let service_data;
			return this.patchwerk.get('Service', {
					department: this.keydata.id,
					counter: _.last(_.split(t_data.service, '-'))
				})
				.then(srv => {
					service_data = srv;
					return this.patchwerk.create('Ticket', t_data, {
						department: t_data.org_destination,
						date: t_data.dedicated_date,
						counter: "*"
					});
				})
				.then(tick => {
					// console.log("a-s crticks", tick);
					tick.lockField('operator')
						.lockField('destination')
						.modifyPriority('service', service_data.get('priority'))
						.modifyLabel(service_data.get('prefix'));
					if (tick.get("booking_method") == "prebook")
						tick.modifyLabel(this.keydata.prebook_label_prefix, "prepend");
					// console.log("a-s crticks II", tick);
					if (t_data.label)
						tick.set("label", t_data.label);
					if (tick.get('booking_method') == 'live')
						tick.set('time_description', service_data.live_operation_time);
					else {
						let td = tick.get("time_description");
						tick.set('time_description', [td[0], td[0] + service_data.prebook_operation_time * (tick.get("service_count") || 1)]);
					}
					return tick;
				});
		})
	}
}

module.exports = AggregatorSection;<commit_msg>validation<commit_after>'use strict';

let Session = require("ticket-session");
let moment = require("moment-timezone");

class AggregatorSection {
	constructor(patchwerk, name, keydata = {}) {
		this.name = name;
		this.keydata = keydata;
		this.patchwerk = patchwerk;

		this.keymap = {};
		this.data = [];
		this.rendered = [];

		this.filtering = null;
		this.ordering = null;
		this._invalid = true;
	}

	updateKeydata(value) {
		this.keydata = value;
		return this;
	}

	addr() {
		return this.keydata.emit_path;
	}

	moment() {
		return moment.tz(this.keydata.org_timezone);
	}

	//search
	session(id) {
		// console.log("GETSESSION", code, this.keymap);
		return this.data[this.keymap[id]];
	}

	ticket(idx) {
		return this.rendered[idx];
	}

	//update
	updateLeaf(leaf) {
		//@FIXIT: switch to ticket models
		let session = this.session(leaf.session);
		let tick = session.find(leaf.id);
		tick.update(leaf);
		session.invalidate();
		// tick.getContainer()
		// 	.update(leaf);
		console.log("UPDATE", leaf.id, tick);
		this.render();
		this.order();
	}

	next(curr_idx) {
		let session = this.session(this.rendered[curr_idx].get('session'));
		return session.next();
	}

	order(params = {}) {
		let curr_moment = this.moment();
		params.date = curr_moment.format('YYYY-MM-DD');
		params.now = curr_moment.diff(curr_moment.clone()
			.startOf('day'), 'seconds');
		this.ordering.run(params, false, this.getRendered());
		return this;
	}

	filter(params = {}) {
		let curr_moment = this.moment();
		params.prebook_show_interval = this.keydata.prebook_show_interval;
		params.now = curr_moment.diff(curr_moment.clone()
			.startOf('day'), 'seconds');
		params.state = params.state || '*';
		return this.filtering.run(params, this.ordering.out(), this.getRendered());
	}

	isAppliable(params = {}, entity) {
		return !!(this.filtering.run(params, ['0'], [entity]))[0];
	}

	setIndexers(filter, order) {
		this.filtering = filter;
		this.ordering = order;
	}

	render() {
		let result = [],
			l = this.data.length;
		this.rendered = [];
		while (l--) {
			if (!this.data[l].isInactive())
				this.rendered = this.rendered.concat(this.data[l].render());
		}
		console.log("RENDER");
		this.validate();
		return this.rendered;
	}

	getRendered() {
		//can implement render expiration here
		//if(expired) return this.render()
		if (this.invalid()) {
			this.render();
		}
		return this.rendered;
	}

	invalidate() {
		console.log("INVALIDATE", this.constructor.name);
		this._invalid = true;
	}

	invalid() {
		return this._invalid;
	}

	validate() {
		console.log("VALIDATE");
		this._invalid = false;
	}

	flush() {
		this.keymap = {};
		this.data = [];
		this.rendered = [];
		this.invalid();
		//mb destruct all sessions? they have circular dependencies
	}

	add(session) {
		//only today
		if (this.moment()
			.format('YYYY-MM-DD') !== session.dedication())
			return this;

		let id = session.identifier();
		session.onUpdate(this.invalidate.bind(this));

		if (this.keymap[id] === undefined) {
			this.data.push(session);
			this.keymap[id] = this.data.length - 1;
		} else {
			this.data[this.keymap[id]] = session;
		}
		this.invalidate();
		return this;
	}

	loadIfOutdated() {
		//it is logical because only today sessions can be added
		if (this.data.length > 0 && this.data[0].dedication() < this.moment()
			.format('YYYY-MM-DD')) {
			console.log("OUTDATED");
			this.flush();
			return this.load()
				.then(res => this.render())
				.then(res => this.order());
		} else {
			return Promise.resolve(true);
		}
	}

	load(spec_date) {
		let date = spec_date || this.moment()
			.format('YYYY-MM-DD');
		this.flush();
		return Promise.all([this.patchwerk.get('TicketSession', {
				department: this.name,
				date: date,
				counter: '*'
			}), this.patchwerk.get('Ticket', {
				department: this.name,
				date: date,
				counter: '*'
			})])
			.then(res => {
				// console.log(res);
				let sessions = res[0],
					l = sessions.length,
					session_data;

				while (l--) {
					session_data = sessions[l];
					//@FIXIT
					if (session_data.properties.description !== undefined) {
						this.add(Session(session_data, res[1]));
					}
				}

				// console.log("SESSIONS", this);
				return this;
			})
	}

	saveSession(session) {
		let model = session.extract();
		let date = this.moment()
			.format('YYYY-MM-DD');
		return this.patchwerk.save(model, {
				department: this.name,
				date: date
			})
			.then(res => this.patchwerk.create('TicketSessionLookup', {
				content: session.identifier()
			}, {
				code: session.code()
			}))
			.then(lookup => this.patchwerk.save(lookup, {
				code: session.code()
			}))
			.then(res => session);
	}

	createSession(data) {
		let tmp_session;
		return this.patchwerk.create('TicketSession', data, {
				department: data.organization,
				date: data.dedicated_date,
				counter: "*"
			})
			.then((session) => {
				tmp_session = session;
				return Promise.map(data.uses, t_id =>
					this.patchwerk.get('Ticket', {
						key: t_id
					}));
			})
			.then(t_data => {
				return Session(tmp_session, t_data);
			});

	}

	virtualizeTicket(t_data) {
		let service_data;
		return this.patchwerk.get('Service', {
				department: this.keydata.id,
				counter: _.last(_.split(t_data.service, '-'))
			})
			.then(srv => {
				service_data = srv;
				return this.patchwerk.create('Ticket', t_data, {
					department: t_data.org_destination,
					date: t_data.dedicated_date,
					counter: "*"
				});
			})
			.then(tick => {
				// console.log("a-s crvirticks", tick);
				tick.unlockField('operator')
					.unlockField('destination')
					.modifyPriority('service', service_data.get('priority'));
				let hst = tick.get("history");
				_.map(hst, h_entry => {
					h_entry.local_time = this.moment()
						.format();
				});
				tick.set("history", hst);
				tick.set("called", 0);
				tick.set("inheritance_counter", 0);
				tick.set("source", null);
				tick.set("operator", null);
				tick.set("destination", null);

				if (tick.get('booking_method') == 'live') {
					tick.set('time_description', service_data.live_operation_time);
				} else {
					let td = tick.time_description;
					tick.set("time_description", [td[0], td[0] + service_data.prebook_operation_time * tick.get("service_count")])
				}
				return tick;
			});
	}

	createTickets(data) {
		let b_data = data.constructor === Array ? data : [data];

		return Promise.map(b_data, t_data => {
			t_data.booking_date = this.moment()
				.format();
			console.log("TDATA", t_data);

			let service_data;
			return this.patchwerk.get('Service', {
					department: this.keydata.id,
					counter: _.last(_.split(t_data.service, '-'))
				})
				.then(srv => {
					service_data = srv;
					return this.patchwerk.create('Ticket', t_data, {
						department: t_data.org_destination,
						date: t_data.dedicated_date,
						counter: "*"
					});
				})
				.then(tick => {
					// console.log("a-s crticks", tick);
					tick.lockField('operator')
						.lockField('destination')
						.modifyPriority('service', service_data.get('priority'))
						.modifyLabel(service_data.get('prefix'));
					if (tick.get("booking_method") == "prebook")
						tick.modifyLabel(this.keydata.prebook_label_prefix, "prepend");
					// console.log("a-s crticks II", tick);
					if (t_data.label)
						tick.set("label", t_data.label);
					if (tick.get('booking_method') == 'live')
						tick.set('time_description', service_data.live_operation_time);
					else {
						let td = tick.get("time_description");
						tick.set('time_description', [td[0], td[0] + service_data.prebook_operation_time * (tick.get("service_count") || 1)]);
					}
					return tick;
				});
		})
	}
}

module.exports = AggregatorSection;<|endoftext|>


<commit_before>const logger = require('logger');
const config = require('config');
const appConstants = require('app.constants');
const MicroserviceModel = require('models/microservice.model');
const EndpointModel = require('models/endpoint.model');
const VersionModel = require('models/version.model');
const MicroserviceDuplicated = require('errors/microserviceDuplicated');
const MicroserviceNotExist = require('errors/microserviceNotExist');
const request = require('request-promise');
const url = require('url');
const crypto = require('crypto');
const pathToRegexp = require('path-to-regexp');
const NotificationService = require('services/notification.service.js');
const Promise = require('bluebird');
const JWT = Promise.promisifyAll(require('jsonwebtoken'));

const MICRO_STATUS_PENDING = 'pending';
const MICRO_STATUS_ACTIVE = 'active';
const MICRO_STATUS_DEACTIVATED = 'deactivated';
const MICRO_STATUS_ERROR = 'error';

class Microservice {

    static getFilters(endpoint) {
        logger.debug('Checking filters in endpoint', endpoint);
        let filters = null;
        if (endpoint.filters) {
            for (let i = 0, length = endpoint.filters.length; i < length; i++) {
                logger.debug(endpoint.filters[i]);
                let pathKeys = [];
                const pathRegex = pathToRegexp(endpoint.filters[i].path, pathKeys);
                if (pathKeys && pathKeys.length > 0) {
                    pathKeys = pathKeys.map((key) => key.name);
                }
                if (!filters) {
                    filters = [];
                }
                filters.push({
                    name: endpoint.filters[i].name,
                    path: endpoint.filters[i].path,
                    method: endpoint.filters[i].method,
                    pathRegex,
                    pathKeys,
                    params: endpoint.filters[i].params,
                    compare: endpoint.filters[i].compare,
                });
            }
        }
        return filters;
    }

    static async saveEndpoint(endpoint, micro, version) {
        logger.info(`Saving endpoint ${endpoint.path} with version ${version}`);
        logger.debug(`Searching if exist ${endpoint.path} in endpoints`);
        endpoint.redirect.url = micro.url;
        // searching
        const oldEndpoint = await EndpointModel.findOne({
            path: endpoint.path,
            method: endpoint.method,
            version,
        }).exec();
        if (oldEndpoint) {
            logger.debug(`Exist path. Check if exist redirect with url ${endpoint.redirect.url}`);
            const oldRedirect = await EndpointModel.findOne({
                path: endpoint.path,
                method: endpoint.method,
                'redirect.url': endpoint.redirect.url,
                version,
            }).exec();
            if (!oldRedirect) {
                logger.debug('Not exist redirect');
                endpoint.redirect.filters = Microservice.getFilters(endpoint);
                oldEndpoint.redirect.push(endpoint.redirect);
                await oldEndpoint.save();
            } else {
                logger.debug('Exist redirect. Updating', oldRedirect);
                oldRedirect.redirect[0].method = endpoint.redirect.method;
                oldRedirect.redirect[0].path = endpoint.redirect.path;
                oldRedirect.redirect[0].filters = Microservice.getFilters(endpoint);
                await oldRedirect.save();
            }

        } else {
            logger.debug('Not exist path. Registering new');
            let pathKeys = [];
            const pathRegex = pathToRegexp(endpoint.path, pathKeys);
            if (pathKeys && pathKeys.length > 0) {
                pathKeys = pathKeys.map((key) => key.name);
            }
            logger.debug('Saving new endpoint');
            endpoint.redirect.filters = Microservice.getFilters(endpoint);
            logger.debug('filters', endpoint.redirect.filters);
            logger.debug('regesx', pathRegex);
            const endpointPepe = await new EndpointModel({
                path: endpoint.path,
                method: endpoint.method,
                pathRegex,
                pathKeys,
                authenticated: endpoint.authenticated,
                binary: endpoint.binary,
                redirect: [endpoint.redirect],
                version,
            }).save();
            logger.debug('Endpoint saved', endpointPepe);
        }
    }

    static async saveEndpoints(micro, info, version) {
        logger.info('Saving endpoints');
        if (info.endpoints && info.endpoints.length > 0) {
            for (let i = 0, length = info.endpoints.length; i < length; i++) {
                await Microservice.saveEndpoint(info.endpoints[i], micro, version);
            }
        }
    }

    static generateUrlInfo(urlInfo, token, internalUrl) {
        logger.debug('Generating url info to microservice with url', urlInfo);
        const queryParams = `token=${token}&url=${internalUrl}`;
        if (urlInfo.indexOf('?') >= 0) {
            return `${urlInfo}&${queryParams}`;
        }
        return `${urlInfo}?${queryParams}`;
    }

    static formatFilters(endpoint) {
        if (endpoint) {
            if (endpoint.filters) {
                if (endpoint.filters) {
                    const filters = [];
                    filters.push({
                        name: endpoint.paramProvider || 'dataset',
                        path: endpoint.pathProvider || '/dataset/:dataset',
                        method: 'GET',
                        params: {
                            dataset: 'dataset',
                        },
                        compare: endpoint.filters,
                    });
                    return filters;
                }
            }
        }
        return null;
    }

    static transformToNewVersion(info) {
        logger.info('Checking if is necesary transform to new version');
        if (info.urls) {
            info.endpoints = info.urls.map((endpoint) => ({
                path: endpoint.url,
                method: endpoint.method,
                redirect: endpoint.endpoints[0],
                filters: Microservice.formatFilters(endpoint),
                authenticated: endpoint.authenticated || false,
                binary: endpoint.binary || false,
            }));
            delete info.urls;
        }
        return info;
    }

    static async generateToken(micro) {
        const token = JWT.sign(micro, config.get('jwt.token'), {});
        return token;
    }

    static async getInfoMicroservice(micro, version) {
        logger.info(`Obtaining info of the microservice with name ${micro.name} and version ${version}`);
        let urlInfo = url.resolve(micro.url, micro.pathInfo);
        logger.debug('Generating token');
        const token = await Microservice.generateToken(micro);
        urlInfo = Microservice.generateUrlInfo(urlInfo, token, config.get('server.internalUrl'));
        logger.debug(`Doing request to ${urlInfo}`);
        let result = null;
        try {
            result = await request({
                uri: urlInfo,
                json: true,
            });
            logger.debug('Updating microservice');
            result = Microservice.transformToNewVersion(result);
            micro.endpoints = result.endpoints;

            logger.debug('Microservice info', result.endpoints[0]);
            micro.swagger = JSON.stringify(result.swagger);
            micro.updatedAt = Date.now();
            micro.token = token;
            if (result.tags) {
                if (!micro.tags) {
                    micro.tags = [];
                }
                micro.tags = micro.tags.concat(result.tags);
            }
            await micro.save();
            await Microservice.saveEndpoints(micro, result, version);
            return true;
        } catch (err) {
            logger.error(err);
            return false;
        }
    }

    static async register(info, ver) {
        let version = ver;
        if (!version) {
            const versionFound = await VersionModel.findOne({
                name: appConstants.ENDPOINT_VERSION,
            });
            version = versionFound.version;
        }
        logger.info(`Registering new microservice with name ${info.name} and url ${info.url}`);
        logger.debug('Search if exist');
        const exist = await MicroserviceModel.findOne({
            url: info.url,
            version,
        });
        if (exist) {
            if (!config.get('microservice.overrideDuplicated')) {
                logger.debug('Not override activated');
                throw new MicroserviceDuplicated(`Microservice with url ${info.url} exists`);
            } else {
                logger.debug('Override activated, Removing old version of microservice');
                await Microservice.remove(exist._id); // eslint-disable-line no-underscore-dangle
            }
        }

        logger.debug(`Creating microservice with status ${MICRO_STATUS_PENDING}`);

        const micro = await new MicroserviceModel({
            name: info.name,
            status: MICRO_STATUS_PENDING,
            url: info.url,
            pathInfo: info.pathInfo,
            swagger: info.swagger,
            token: crypto.randomBytes(20).toString('hex'),
            tags: info.tags,
            version,
        }).save();

        logger.debug('Saved correct');
        const correct = await Microservice.getInfoMicroservice(micro, version);
        if (correct) {
            logger.info(`Updating state of microservice with name ${micro.name}`);
            micro.status = MICRO_STATUS_ACTIVE;
            await micro.save();
            logger.info('Updated successfully');
        } else {
            logger.info(`Updated to error state microservice with name ${micro.name}`);
            micro.status = MICRO_STATUS_ERROR;
            await micro.save();
        }

        return micro;
    }

    static async removeEndpointOfMicroservice(micro) {
        logger.info(`Removing endpoints of microservice with url ${micro.url}`);
        if (micro && micro.endpoints) {
            for (let i = 0, length = micro.endpoints.length; i < length; i++) {
                const endpoint = await EndpointModel.findOne({
                    method: micro.endpoints[i].method,
                    path: micro.endpoints[i].path,
                }).exec();
                if (endpoint) {
                    endpoint.redirect = endpoint.redirect.filter((red) => red.url !== micro.url);
                    if (endpoint.redirect && endpoint.redirect.length > 0) {
                        logger.debug('Updating endpoint');
                        await endpoint.save();
                    } else {
                        logger.debug('Endpoint empty. Removing endpoint');
                        await endpoint.remove();
                    }
                }
            }
        }
    }

    static async remove(id) {
        logger.info(`Removing microservice with id ${id}`);
        const micro = await MicroserviceModel.findById(id, {
            __v: 0,
        });
        if (!micro) {
            throw new MicroserviceNotExist(`Microservice with id ${id} does not exist`);
        }
        logger.debug('Removing endpoints');
        await Microservice.removeEndpointOfMicroservice(micro);
        await micro.remove();
        return micro;
    }

    static async checkLiveMicro(micro) {
        logger.debug(`Checking live of microservice: ${micro.name} `);
        const urlLive = url.resolve(micro.url, micro.pathLive);
        logger.debug(`Doing request to ${urlLive}`);
        if (!micro.infoStatus) {
            micro.infoStatus = {};
        }
        try {
            await request({
                uri: urlLive,
            });
            if (micro.status === MICRO_STATUS_ERROR) {
                logger.info('Sending event of restore microservice');
                await NotificationService.sendAlertMicroserviceRestore(micro.name, micro.url);
            }
            micro.infoStatus.lastCheck = new Date();
            micro.infoStatus.error = null;
            micro.infoStatus.numRetries = 0;
            micro.status = MICRO_STATUS_ACTIVE;
            await micro.save();
            logger.debug(`Microservice ${micro.name} is live`);
        } catch (err) {
            logger.error(`Microservice ${micro.name} is DOWN`, err);
            micro.infoStatus.lastCheck = new Date();
            micro.infoStatus.numRetries++;
            micro.status = MICRO_STATUS_ERROR;
            micro.infoStatus.error = err.message;
            await micro.save();

            if (micro.infoStatus.numRetries === 3) {
                await NotificationService.sendAlertMicroserviceDown(micro.name, micro.url, err);
            }
            return false;
        }
        return true;
    }

    static async checkLiveMicroservice() {
        logger.info('Check live microservices');

        const versionFound = await VersionModel.findOne({
            name: appConstants.ENDPOINT_VERSION,
        });
        logger.debug('Found', versionFound);

        logger.info('Obtaining microservices with version ', versionFound);
        const microservices = await MicroserviceModel.find({
            version: versionFound.version
        });
        if (!microservices || microservices.length === 0) {
            logger.info('Not exist registered microservices');
            return;
        }
        for (let i = 0, length = microservices.length; i < length; i++) {
            await Microservice.checkLiveMicro(microservices[i]);
        }
        logger.info('Finished checking');
    }

    static async registerPackMicroservices(microservices) {
        logger.info('Refreshing all microservices');
        logger.debug('Obtaining new version');
        const versionFound = await VersionModel.findOne({
            name: appConstants.ENDPOINT_VERSION,
        });
        logger.debug('Found', versionFound);
        const newVersion = versionFound.version + 1;
        logger.debug('New version is ', newVersion);

        if (microservices) {
            for (let i = 0, length = microservices.length; i < length; i++) {
                try {
                    if (microservices[i].name !== null && microservices[i].url !== null) {
                        logger.debug(`Registering microservice with name ${microservices[i].name}`);
                        await Microservice.register(microservices[i], newVersion);
                    }
                } catch (err) {
                    logger.error('Error registering microservice', err);
                }
            }
        }
        logger.info('Updating version of ENDPOINT_VERSION');
        await VersionModel.update({
            name: appConstants.ENDPOINT_VERSION,
        }, {
            $set: {
                version: newVersion,
            },
        });
        logger.info('Registered successfully');
    }

}

module.exports = Microservice;
<commit_msg>add conditions in filters<commit_after>const logger = require('logger');
const config = require('config');
const appConstants = require('app.constants');
const MicroserviceModel = require('models/microservice.model');
const EndpointModel = require('models/endpoint.model');
const VersionModel = require('models/version.model');
const MicroserviceDuplicated = require('errors/microserviceDuplicated');
const MicroserviceNotExist = require('errors/microserviceNotExist');
const request = require('request-promise');
const url = require('url');
const crypto = require('crypto');
const pathToRegexp = require('path-to-regexp');
const NotificationService = require('services/notification.service.js');
const Promise = require('bluebird');
const JWT = Promise.promisifyAll(require('jsonwebtoken'));

const MICRO_STATUS_PENDING = 'pending';
const MICRO_STATUS_ACTIVE = 'active';
const MICRO_STATUS_DEACTIVATED = 'deactivated';
const MICRO_STATUS_ERROR = 'error';

class Microservice {

    static getFilters(endpoint) {
        logger.debug('Checking filters in endpoint', endpoint);
        let filters = null;
        if (endpoint.filters) {
            for (let i = 0, length = endpoint.filters.length; i < length; i++) {
                logger.debug(endpoint.filters[i]);
                let pathKeys = [];
                const pathRegex = pathToRegexp(endpoint.filters[i].path, pathKeys);
                if (pathKeys && pathKeys.length > 0) {
                    pathKeys = pathKeys.map((key) => key.name);
                }
                if (!filters) {
                    filters = [];
                }
                filters.push({
                    name: endpoint.filters[i].name,
                    path: endpoint.filters[i].path,
                    method: endpoint.filters[i].method,
                    condition: endpoint.filters[i].condition,
                    pathRegex,
                    pathKeys,
                    params: endpoint.filters[i].params,
                    compare: endpoint.filters[i].compare,
                });
            }
        }
        return filters;
    }

    static async saveEndpoint(endpoint, micro, version) {
        logger.info(`Saving endpoint ${endpoint.path} with version ${version}`);
        logger.debug(`Searching if exist ${endpoint.path} in endpoints`);
        endpoint.redirect.url = micro.url;
        // searching
        const oldEndpoint = await EndpointModel.findOne({
            path: endpoint.path,
            method: endpoint.method,
            version,
        }).exec();
        if (oldEndpoint) {
            logger.debug(`Exist path. Check if exist redirect with url ${endpoint.redirect.url}`);
            const oldRedirect = await EndpointModel.findOne({
                path: endpoint.path,
                method: endpoint.method,
                'redirect.url': endpoint.redirect.url,
                version,
            }).exec();
            if (!oldRedirect) {
                logger.debug('Not exist redirect');
                endpoint.redirect.filters = Microservice.getFilters(endpoint);
                oldEndpoint.redirect.push(endpoint.redirect);
                await oldEndpoint.save();
            } else {
                logger.debug('Exist redirect. Updating', oldRedirect);
                oldRedirect.redirect[0].method = endpoint.redirect.method;
                oldRedirect.redirect[0].path = endpoint.redirect.path;
                oldRedirect.redirect[0].filters = Microservice.getFilters(endpoint);
                await oldRedirect.save();
            }

        } else {
            logger.debug('Not exist path. Registering new');
            let pathKeys = [];
            const pathRegex = pathToRegexp(endpoint.path, pathKeys);
            if (pathKeys && pathKeys.length > 0) {
                pathKeys = pathKeys.map((key) => key.name);
            }
            logger.debug('Saving new endpoint');
            endpoint.redirect.filters = Microservice.getFilters(endpoint);
            logger.debug('filters', endpoint.redirect.filters);
            logger.debug('regesx', pathRegex);
            const endpointPepe = await new EndpointModel({
                path: endpoint.path,
                method: endpoint.method,
                pathRegex,
                pathKeys,
                authenticated: endpoint.authenticated,
                binary: endpoint.binary,
                redirect: [endpoint.redirect],
                version,
            }).save();
            logger.debug('Endpoint saved', endpointPepe);
        }
    }

    static async saveEndpoints(micro, info, version) {
        logger.info('Saving endpoints');
        if (info.endpoints && info.endpoints.length > 0) {
            for (let i = 0, length = info.endpoints.length; i < length; i++) {
                await Microservice.saveEndpoint(info.endpoints[i], micro, version);
            }
        }
    }

    static generateUrlInfo(urlInfo, token, internalUrl) {
        logger.debug('Generating url info to microservice with url', urlInfo);
        const queryParams = `token=${token}&url=${internalUrl}`;
        if (urlInfo.indexOf('?') >= 0) {
            return `${urlInfo}&${queryParams}`;
        }
        return `${urlInfo}?${queryParams}`;
    }

    static formatFilters(endpoint) {
        if (endpoint) {
            if (endpoint.filters) {
                if (endpoint.filters) {
                    const filters = [];
                    filters.push({
                        name: endpoint.paramProvider || 'dataset',
                        path: endpoint.pathProvider || '/dataset/:dataset',
                        method: 'GET',
                        params: {
                            dataset: 'dataset',
                        },
                        compare: endpoint.filters,
                    });
                    return filters;
                }
            }
        }
        return null;
    }

    static transformToNewVersion(info) {
        logger.info('Checking if is necesary transform to new version');
        if (info.urls) {
            info.endpoints = info.urls.map((endpoint) => ({
                path: endpoint.url,
                method: endpoint.method,
                redirect: endpoint.endpoints[0],
                filters: Microservice.formatFilters(endpoint),
                authenticated: endpoint.authenticated || false,
                binary: endpoint.binary || false,
            }));
            delete info.urls;
        }
        return info;
    }

    static async generateToken(micro) {
        const token = JWT.sign(micro, config.get('jwt.token'), {});
        return token;
    }

    static async getInfoMicroservice(micro, version) {
        logger.info(`Obtaining info of the microservice with name ${micro.name} and version ${version}`);
        let urlInfo = url.resolve(micro.url, micro.pathInfo);
        logger.debug('Generating token');
        const token = await Microservice.generateToken(micro);
        urlInfo = Microservice.generateUrlInfo(urlInfo, token, config.get('server.internalUrl'));
        logger.debug(`Doing request to ${urlInfo}`);
        let result = null;
        try {
            result = await request({
                uri: urlInfo,
                json: true,
            });
            logger.debug('Updating microservice');
            result = Microservice.transformToNewVersion(result);
            micro.endpoints = result.endpoints;

            logger.debug('Microservice info', result.endpoints[0]);
            micro.swagger = JSON.stringify(result.swagger);
            micro.updatedAt = Date.now();
            micro.token = token;
            if (result.tags) {
                if (!micro.tags) {
                    micro.tags = [];
                }
                micro.tags = micro.tags.concat(result.tags);
            }
            await micro.save();
            await Microservice.saveEndpoints(micro, result, version);
            return true;
        } catch (err) {
            logger.error(err);
            return false;
        }
    }

    static async register(info, ver) {
        let version = ver;
        if (!version) {
            const versionFound = await VersionModel.findOne({
                name: appConstants.ENDPOINT_VERSION,
            });
            version = versionFound.version;
        }
        logger.info(`Registering new microservice with name ${info.name} and url ${info.url}`);
        logger.debug('Search if exist');
        const exist = await MicroserviceModel.findOne({
            url: info.url,
            version,
        });
        if (exist) {
            if (!config.get('microservice.overrideDuplicated')) {
                logger.debug('Not override activated');
                throw new MicroserviceDuplicated(`Microservice with url ${info.url} exists`);
            } else {
                logger.debug('Override activated, Removing old version of microservice');
                await Microservice.remove(exist._id); // eslint-disable-line no-underscore-dangle
            }
        }

        logger.debug(`Creating microservice with status ${MICRO_STATUS_PENDING}`);

        const micro = await new MicroserviceModel({
            name: info.name,
            status: MICRO_STATUS_PENDING,
            url: info.url,
            pathInfo: info.pathInfo,
            swagger: info.swagger,
            token: crypto.randomBytes(20).toString('hex'),
            tags: info.tags,
            version,
        }).save();

        logger.debug('Saved correct');
        const correct = await Microservice.getInfoMicroservice(micro, version);
        if (correct) {
            logger.info(`Updating state of microservice with name ${micro.name}`);
            micro.status = MICRO_STATUS_ACTIVE;
            await micro.save();
            logger.info('Updated successfully');
        } else {
            logger.info(`Updated to error state microservice with name ${micro.name}`);
            micro.status = MICRO_STATUS_ERROR;
            await micro.save();
        }

        return micro;
    }

    static async removeEndpointOfMicroservice(micro) {
        logger.info(`Removing endpoints of microservice with url ${micro.url}`);
        if (micro && micro.endpoints) {
            for (let i = 0, length = micro.endpoints.length; i < length; i++) {
                const endpoint = await EndpointModel.findOne({
                    method: micro.endpoints[i].method,
                    path: micro.endpoints[i].path,
                }).exec();
                if (endpoint) {
                    endpoint.redirect = endpoint.redirect.filter((red) => red.url !== micro.url);
                    if (endpoint.redirect && endpoint.redirect.length > 0) {
                        logger.debug('Updating endpoint');
                        await endpoint.save();
                    } else {
                        logger.debug('Endpoint empty. Removing endpoint');
                        await endpoint.remove();
                    }
                }
            }
        }
    }

    static async remove(id) {
        logger.info(`Removing microservice with id ${id}`);
        const micro = await MicroserviceModel.findById(id, {
            __v: 0,
        });
        if (!micro) {
            throw new MicroserviceNotExist(`Microservice with id ${id} does not exist`);
        }
        logger.debug('Removing endpoints');
        await Microservice.removeEndpointOfMicroservice(micro);
        await micro.remove();
        return micro;
    }

    static async checkLiveMicro(micro) {
        logger.debug(`Checking live of microservice: ${micro.name} `);
        const urlLive = url.resolve(micro.url, micro.pathLive);
        logger.debug(`Doing request to ${urlLive}`);
        if (!micro.infoStatus) {
            micro.infoStatus = {};
        }
        try {
            await request({
                uri: urlLive,
            });
            if (micro.status === MICRO_STATUS_ERROR) {
                logger.info('Sending event of restore microservice');
                await NotificationService.sendAlertMicroserviceRestore(micro.name, micro.url);
            }
            micro.infoStatus.lastCheck = new Date();
            micro.infoStatus.error = null;
            micro.infoStatus.numRetries = 0;
            micro.status = MICRO_STATUS_ACTIVE;
            await micro.save();
            logger.debug(`Microservice ${micro.name} is live`);
        } catch (err) {
            logger.error(`Microservice ${micro.name} is DOWN`, err);
            micro.infoStatus.lastCheck = new Date();
            micro.infoStatus.numRetries++;
            micro.status = MICRO_STATUS_ERROR;
            micro.infoStatus.error = err.message;
            await micro.save();

            if (micro.infoStatus.numRetries === 3) {
                await NotificationService.sendAlertMicroserviceDown(micro.name, micro.url, err);
            }
            return false;
        }
        return true;
    }

    static async checkLiveMicroservice() {
        logger.info('Check live microservices');

        const versionFound = await VersionModel.findOne({
            name: appConstants.ENDPOINT_VERSION,
        });
        logger.debug('Found', versionFound);

        logger.info('Obtaining microservices with version ', versionFound);
        const microservices = await MicroserviceModel.find({
            version: versionFound.version
        });
        if (!microservices || microservices.length === 0) {
            logger.info('Not exist registered microservices');
            return;
        }
        for (let i = 0, length = microservices.length; i < length; i++) {
            await Microservice.checkLiveMicro(microservices[i]);
        }
        logger.info('Finished checking');
    }

    static async registerPackMicroservices(microservices) {
        logger.info('Refreshing all microservices');
        logger.debug('Obtaining new version');
        const versionFound = await VersionModel.findOne({
            name: appConstants.ENDPOINT_VERSION,
        });
        logger.debug('Found', versionFound);
        const newVersion = versionFound.version + 1;
        logger.debug('New version is ', newVersion);

        if (microservices) {
            for (let i = 0, length = microservices.length; i < length; i++) {
                try {
                    if (microservices[i].name !== null && microservices[i].url !== null) {
                        logger.debug(`Registering microservice with name ${microservices[i].name}`);
                        await Microservice.register(microservices[i], newVersion);
                    }
                } catch (err) {
                    logger.error('Error registering microservice', err);
                }
            }
        }
        logger.info('Updating version of ENDPOINT_VERSION');
        await VersionModel.update({
            name: appConstants.ENDPOINT_VERSION,
        }, {
            $set: {
                version: newVersion,
            },
        });
        logger.info('Registered successfully');
    }

}

module.exports = Microservice;
<|endoftext|>


<commit_before>
((module) => {
	'use strict';

	var createClassFromSuper = require('simple-class-utils').createClass.super;
	var createClass = require('./create-class.js');
	var Root = require('./root.js').class;
	var transformIterable = require('./utils/transform-iterable.js');

	var _key_iterator = Symbol.iterator;

	class AdvancedContainerTemplate {

		Set(Container, equal) {

			Container = createClass(Container);

			class AdvSet extends AdvancedContainerTemplate.Set.Root {

				constructor(...args) {
					super();
					this.container = new Container(...args);
				}

				[_key_iterator]() {
					return transformIterable(this.container, (element) => element.value);
				}

				findPositionOf(value) {
					return this.container.find((element) => equal(value, element.value, this));
				}

			}

			return createClass(AdvSet);

		}

		Map(Container, equal) {

		}

	}

	module.exports = new AdvancedContainerTemplate();

	var SupRoot = AdvancedContainerTemplate.Root = createClassFromSuper(Root);
	((proto) => {
		var SubRoot = proto.Root = createClassFromSuper(SupRoot);
		proto.Set.Root = createClassFromSuper(SubRoot);
		proto.Map.Root = createClassFromSuper(SubRoot);
	})(AdvancedContainerTemplate.prototype);

})(module);
<commit_msg>update<commit_after>
((module) => {
	'use strict';

	var createClassFromSuper = require('simple-class-utils').createClass.super;
	var createClass = require('./create-class.js');
	var Root = require('./root.js').class;
	var transformIterable = require('./utils/transform-iterable.js');

	var _key_iterator = Symbol.iterator;

	class AdvancedContainerTemplate {

		Set(Container, equal) {

			Container = createClass(Container);

			class AdvSet extends AdvancedContainerTemplate.Set.Root {

				constructor(...args) {
					super();
					this.container = new Container(...args);
				}

				[_key_iterator]() {
					return transformIterable(this.container, (element) => element.value);
				}

				entries() {
					return transformIterable(this, (element) => new Entry(element, element));
				}

				findPositionOf(value) {
					return this.container.find((element) => equal(value, element.value, this));
				}

				has(value) {
					return Boolean(this.container.findPositionOf(value));
				}

				add(value) {
					this.has(value) && this.container.add(new AdvSet.Element(value));
					return this;
				}

				clear() {
					this.container.clear();
					return this;
				}

				get size() {
					return this.container.size;
				}

			}

			AdvSet.Element = createClassFromSuper(AdvSet.Element);

			return createClass(AdvSet);

		}

		Map(Container, equal) {

		}

	}

	module.exports = new AdvancedContainerTemplate();

	var SupRoot = AdvancedContainerTemplate.Root = createClassFromSuper(Root);
	var SupElement = AdvancedContainerTemplate.Element = createClassFromSuper(Root);
	((proto) => {

		var SubRoot = proto.Root = class extends SupRoot {

			keys() {
				return transformIterable(this.entries(), (entry) => entry.key);
			}

			values() {
				return transformIterable(this.entries(), (entry) => entry.value);
			}

		};

		proto.Set.Root = createClassFromSuper(SubRoot);

		proto.Map.Root = createClassFromSuper(SubRoot);

		var SubElement = proto.Element = createClassFromSuper(SupElement);

		proto.Set.Element = class extends SubElement {
			constructor(value) {
				super();
				this.value = value;
			}
		};

		proto.Map.Element = class extends SubElement {
			constructor(key, value) {
				super();
				this.key = key;
				this.value = value;
			}
		};

	})(AdvancedContainerTemplate.prototype);

	class Entry extends Array {

		get key() {
			return this[0];
		}

		get value() {
			return this[1];
		}

	}

	AdvancedContainerTemplate.Entry = Entry;

})(module);
<|endoftext|>


<commit_before>/**
 *  Copyright (c) 2015, Facebook, Inc.
 *  All rights reserved.
 *
 *  This source code is licensed under the BSD-style license found in the
 *  LICENSE file in the root directory of this source tree. An additional grant
 *  of patent rights can be found in the PATENTS file in the same directory.
 */

// Model types
class Game extends Object {}
class HidingSpot extends Object {}

// Mock data
var game = new Game();
game.id = '1';

var hidingSpots = [];
(function() {
  var hidingSpot;
  var indexOfSpotWithTreasure = Math.floor(Math.random() * 9);
  for (var i = 0; i < 9; i++) {
    hidingSpot = new HidingSpot();
    hidingSpot.id = `${i}`;
    hidingSpot.hasTreasure = (i === indexOfSpotWithTreasure);
    hidingSpot.hasBeenChecked = false;
    hidingSpots.push(hidingSpot);
  }
})();

var turnsRemaining = 3;

export function checkHidingSpotForTreasure(id) {
  if (hidingSpots.some(hs => hs.hasTreasure && hs.hasBeenChecked)) {
    return;
  }
  turnsRemaining--;
  var hidingSpot = getHidingSpot(id);
  hidingSpot.hasBeenChecked = true;
};
export function getHidingSpot(id) {
  return hidingSpots.find(hs => hs.id === id)
}
export function getGame() { return game; }
export function getHidingSpots() { return hidingSpots; }
export function getTurnsRemaining() { return turnsRemaining; }
<commit_msg>export Game and HidingSpot class<commit_after>/**
 *  Copyright (c) 2015, Facebook, Inc.
 *  All rights reserved.
 *
 *  This source code is licensed under the BSD-style license found in the
 *  LICENSE file in the root directory of this source tree. An additional grant
 *  of patent rights can be found in the PATENTS file in the same directory.
 */

// Model types
export class Game extends Object {}
export class HidingSpot extends Object {}

// Mock data
var game = new Game();
game.id = '1';

var hidingSpots = [];
(function() {
  var hidingSpot;
  var indexOfSpotWithTreasure = Math.floor(Math.random() * 9);
  for (var i = 0; i < 9; i++) {
    hidingSpot = new HidingSpot();
    hidingSpot.id = `${i}`;
    hidingSpot.hasTreasure = (i === indexOfSpotWithTreasure);
    hidingSpot.hasBeenChecked = false;
    hidingSpots.push(hidingSpot);
  }
})();

var turnsRemaining = 3;

export function checkHidingSpotForTreasure(id) {
  if (hidingSpots.some(hs => hs.hasTreasure && hs.hasBeenChecked)) {
    return;
  }
  turnsRemaining--;
  var hidingSpot = getHidingSpot(id);
  hidingSpot.hasBeenChecked = true;
};
export function getHidingSpot(id) {
  return hidingSpots.find(hs => hs.id === id)
}
export function getGame() { return game; }
export function getHidingSpots() { return hidingSpots; }
export function getTurnsRemaining() { return turnsRemaining; }
<|endoftext|>


<commit_before>// ==UserScript==
// @name        BigKinjo
// @namespace   http://www.acid-chicken.com/greasemonkey
// @description アメちゃんを左下にピタッ！ご近所さんを真ん中にドーン！
// @include     https://mstdn.osaka/*
// @require     https://code.jquery.com/jquery-1.11.1.min.js
// @version     1.4.1
// @grant       none
// ==/UserScript==
const home = '';
const script = '';
$(document).on('ready page:load',() => {
  if (window.matchMedia('(min-width: 1025px)').matches) {
    $('body').append(script); // ウチのスクリプトを追加すんで
    $('.column:eq(0)').attr('id', 'home'); // ウチ欄をウチと命名すんで
    $('.column:eq(1)').attr('id', 'candy'); // 通知欄をアメちゃんと命名すんで
    $('.column-icon-clear').css('top', '0'); // 消しゴムのズレを直すで
    $('.drawer').css('display', 'flex'); // 書き込み欄をflex配置にすんで
    $('.drawer__pager').css('flex', '0 0 237px'); // 書き込み欄が消えんのを防ぐで
    $('.drawer__tab:eq(2)').after(home); // 書き込み欄のタブ上の四番目にウチボタンを追加すんで
    $('#candy').appendTo('.drawer'); // アメちゃんを書き込み欄に突っ込むで
    $('#candy').css({ // 突っ込むにあたっていろいろと設定すんで
      'flex': '1 1 auto',
      'height': '100%',
      'padding': '0',
      'margin-top': '10px',
      'width': 'initial'
    });
    $('#home').hide(); // ウチを消すで
    setInterval(() => {
      if (window.matchMedia('(min-width: 1025px)').matches) { // ページを移動すると元に戻ってしまうのを防ぐで
        $('.columns-area').children().css('flex', '1'); // 全体をflexで伸びるようにすんで
        if ($('#home').css('display') === 'none') $('.column:eq(2)').css('flex', '3'); // ウチがなかったら近所のサイズを3倍にすんで
        else $('.column:eq(2)').css('flex', '2'); // ウチがあったらやっぱり2倍にすんで
      }
    }, 16);
  }
});
<commit_msg>Update bigkinjo.user.js<commit_after>// ==UserScript==
// @name        BigKinjo
// @namespace   http://www.acid-chicken.com/greasemonkey
// @description アメちゃんを左下にピタッ！ご近所さんを真ん中にドーン！
// @include     https://mstdn.osaka/*
// @require     https://code.jquery.com/jquery-1.11.1.min.js
// @version     1.5
// @grant       none
// ==/UserScript==
const home = '';
const script = '';
$(document).on('ready page:load',() => {
  if (window.matchMedia('(min-width: 1025px)').matches) {
    $('body').append(script); // ウチのスクリプトを追加すんで
    $('.column:eq(0)').attr('id', 'home'); // ウチ欄をウチと命名すんで
    $('.column:eq(1)').attr('id', 'candy'); // 通知欄をアメちゃんと命名すんで
    $('.column-icon-clear').css('top', '0'); // 消しゴムのズレを直すで
    $('.drawer').css('display', 'flex'); // 書き込み欄をflex配置にすんで
    $('.drawer__pager').css('flex', '0 0 237px'); // 書き込み欄が消えんのを防ぐで
    $('.drawer__tab:eq(2)').after(home); // 書き込み欄のタブ上の四番目にウチボタンを追加すんで
    $('#candy').appendTo('.drawer'); // アメちゃんを書き込み欄に突っ込むで
    $('#candy').css({ // 突っ込むにあたっていろいろと設定すんで
      'flex': '1 1 auto',
      'height': '100%',
      'padding': '0',
      'margin-top': '10px',
      'width': 'initial'
    });
    $('#home').hide(); // ウチを消すで
    setInterval(() => {
      if (window.matchMedia('(min-width: 1025px)').matches) { // ページを移動すると元に戻ってしまうのを防ぐで
        $('.columns-area').children().css('flex', '1'); // 全体をflexで伸びるようにすんで
        if ($('#home').css('display') === 'none') $('.column:eq(2)').css('flex', '3'); // ウチがなかったら近所のサイズを3倍にすんで
        else $('.column:eq(2)').css('flex', '2'); // ウチがあったらやっぱり2倍にすんで
      }
    }, 16);
  }
});
<|endoftext|>


<commit_before>app.core.router.Router = (function (module) {
  'use strict';

  angular
    .module(module.ID, [])
    .factory('appRouter', AppRouter)
    .run(function ($rootScope, $urlRouter, appRouter) {

      $rootScope.$on('$stateChangeStart', function (event, toState, toParams, fromState, fromParams) {
        appRouter.addStateChangeListener(event, toState, toParams, fromState, fromParams);
      });

      $urlRouter.listen();

    });

  function AppRouter($state, $urlRouter, AppRouterLayer, AppRouterStart, AppRouterDestination) {

    var Router = function Router() {
      this.stack = [];
      this.previousState = {};
    };

    Router.prototype.use = function (fn) {
      var layer;
      if (typeof fn !== 'function') {
        layer = new AppRouterLayer(arguments[1], arguments[0]);
      } else {
        layer = new AppRouterLayer(fn);
      }

      if (layer) {
        this.stack.push(layer);
      }
    };

    Router.prototype.addStateChangeListener = function (event, toState, toParams, fromState, fromParams) {
      if (this.stack.length > 0 && this.previousState.name !== toState.name) {
        event.preventDefault();
        this.previousState = toState;
        this.dispatch(
          new AppRouterStart(fromState, fromParams),
          new AppRouterDestination(toState, toParams),
          function (err) {
            if (!err) {
              $state.go(toState.name);
            }
          });
      }
    };

    Router.prototype.dispatch = function (start, destination, done) {
      var idx = 0;
      var stack = this.stack;
      if (stack.length === 0) {
        return done();
      }

      next();
      ////////////////////////////////////

      function next(err) {
        if (err) {
          return done(err);
        }
        var layer = stack[idx++];
        if (!layer) {
          return done();
        }
        try {
          if (!layer.hasRoute() || (layer.hasRoute() && layer.matchesState(destination.state.name))) {
            layer.handle(
              start,
              destination,
              next,
              done
            );
          } else {
            return next();
          }
        } catch (err) {
          next(err);
        }
      }
    };

    /////////////////////////////////
    var router = new Router();
    return router;

  }

  return module;

}(app.core.router.add('Router')));
<commit_msg>feat(AppRouter): adds status attribute to the $rootScope<commit_after>app.core.router.Router = (function (module) {
  'use strict';

  angular
    .module(module.ID, [])
    .factory('appRouter', AppRouter)
    .run(function ($rootScope, $urlRouter, appRouter) {

      $rootScope.appRouterIsWorking = false;
      $rootScope.$on('$stateChangeStart', function (event, toState, toParams, fromState, fromParams) {
        appRouter.addStateChangeListener(event, toState, toParams, fromState, fromParams);
      });

      $urlRouter.listen();

    });

  function AppRouter($state, $urlRouter, $rootScope, AppRouterLayer, AppRouterStart, AppRouterDestination) {

    var Router = function Router() {
      this.stack = [];
      this.previousState = {};
    };

    Router.prototype.use = function (fn) {
      var layer;
      if (typeof fn !== 'function') {
        layer = new AppRouterLayer(arguments[1], arguments[0]);
      } else {
        layer = new AppRouterLayer(fn);
      }

      if (layer) {
        this.stack.push(layer);
      }
    };

    Router.prototype.addStateChangeListener = function (event, toState, toParams, fromState, fromParams) {
      if (this.stack.length > 0 && this.previousState.name !== toState.name) {
        event.preventDefault();
        this.previousState = toState;
        this.dispatch(
          new AppRouterStart(fromState, fromParams),
          new AppRouterDestination(toState, toParams),
          function (err) {
            $rootScope.appRouterIsWorking = false;
            if (!err) {
              $state.go(toState.name);
            }
          });
      }
    };

    Router.prototype.dispatch = function (start, destination, done) {
      var idx = 0;
      var stack = this.stack;
      if (stack.length === 0) {
        return done();
      }

      $rootScope.appRouterIsWorking = true;
      next();
      ////////////////////////////////////

      function next(err) {
        if (err) {
          return done(err);
        }
        var layer = stack[idx++];
        if (!layer) {
          return done();
        }
        try {
          if (!layer.hasRoute() || (layer.hasRoute() && layer.matchesState(destination.state.name))) {
            layer.handle(
              start,
              destination,
              next,
              done
            );
          } else {
            return next();
          }
        } catch (err) {
          next(err);
        }
      }
    };

    /////////////////////////////////
    var router = new Router();
    return router;

  }

  return module;

}(app.core.router.add('Router')));
<|endoftext|>


<commit_before>'use strict';

import React from 'react';
import { shallow } from 'enzyme';
import { expect } from 'chai';
import WeatherMessage, { conditionMap }  from '../../components/WeatherMessage.jsx';

describe.only('Weather Message', () => {
	it('should render', () => {
		const message = shallow(<WeatherMessage location="" temp={45} condition={{}}/>);
		expect(message).to.exist;
	});

	it('displays the given temp', () => {
		const temp = 45.01;
		const message = shallow(<WeatherMessage location="" temp={temp} condition={{}}/>);
		expect(message.text()).to.contain(temp);
	});

	it('displays the given location', () => {
		const location = "Moscow";
		const message = shallow(<WeatherMessage location={location} temp={45} condition={{}}/>);
		expect(message.text()).to.contain(location);
	});

	it('displays the main condition, if specified', () => {
		const condition = {
			main: 'Clear'
		};
		const conditionValue = conditionMap['Clear'];
		const message = shallow(<WeatherMessage location="" temp={45} condition={condition} />);
		expect(message.text()).to.contain(conditionValue);
	});
})
<commit_msg>Remove accidental `.only`<commit_after>'use strict';

import React from 'react';
import { shallow } from 'enzyme';
import { expect } from 'chai';
import WeatherMessage, { conditionMap }  from '../../components/WeatherMessage.jsx';

describe('Weather Message', () => {
	it('should render', () => {
		const message = shallow(<WeatherMessage location="" temp={45} condition={{}}/>);
		expect(message).to.exist;
	});

	it('displays the given temp', () => {
		const temp = 45.01;
		const message = shallow(<WeatherMessage location="" temp={temp} condition={{}}/>);
		expect(message.text()).to.contain(temp);
	});

	it('displays the given location', () => {
		const location = "Moscow";
		const message = shallow(<WeatherMessage location={location} temp={45} condition={{}}/>);
		expect(message.text()).to.contain(location);
	});

	it('displays the main condition, if specified', () => {
		const condition = {
			main: 'Clear'
		};
		const conditionValue = conditionMap['Clear'];
		const message = shallow(<WeatherMessage location="" temp={45} condition={condition} />);
		expect(message.text()).to.contain(conditionValue);
	});
})
<|endoftext|>


<commit_before>import React, { Component, PropTypes } from 'react';
import { defineMessages, injectIntl, intlShape } from 'react-intl';
import Tabs from 'react-simpletabs';
import { Annotations, SourceHeader, Tags } from './';
import Medias from '../media/Medias';

const messages = defineMessages({
  annotationsTab: {
    id: 'sourceComponent.annotationsTab',
    defaultMessage: 'Annotations',
  },
  mediasTab: {
    id: 'sourceComponent.mediasTab',
    defaultMessage: 'Medias',
  },
});

class SourceComponent extends Component {
  render() {
    const source = this.props.source;

    return (

        <SourceHeader source={source} />

        <Tags tags={source.tags.edges} annotated={source} annotatedType="Source" />

        <Tabs className="tabs">
          <Tabs.Panel title={this.props.intl.formatMessage(messages.annotationsTab)}>
            <Annotations annotations={source.annotations.edges} annotated={source} annotatedType="Source" />
          </Tabs.Panel>
          <Tabs.Panel title={this.props.intl.formatMessage(messages.mediasTab)}>
            <Medias medias={source.medias.edges} />
          </Tabs.Panel>
        </Tabs>

    );
  }
}

SourceComponent.propTypes = {
  intl: intlShape.isRequired,
};

export default injectIntl(SourceComponent);
<commit_msg>WIP Source header and medias display #5958<commit_after>import React, { Component } from 'react';
import Relay from 'react-relay';
import PropTypes from 'prop-types';
import {
  FormattedMessage,
  FormattedHTMLMessage,
  FormattedDate,
  defineMessages,
  injectIntl,
  intlShape,
} from 'react-intl';
import TextField from 'material-ui/TextField';
import Checkbox from 'material-ui/Checkbox';
import FlatButton from 'material-ui/FlatButton';
import { Card, CardActions, CardHeader, CardText } from 'material-ui/Card';
import IconButton from 'material-ui/IconButton';
import MdChevronRight from 'react-icons/lib/md/chevron-right';
import MDEdit from 'react-icons/lib/md/edit';
import { List, ListItem } from 'material-ui/List';
import PageTitle from '../PageTitle';
import Medias from '../media/Medias';
import MappedMessage from '../MappedMessage';
// import UpdateSourceMutation from '../../relay/UpdateSourceMutation';
import Message from '../Message';
import CreateProject from '../project/CreateProject';
import Can from '../Can';
import CheckContext from '../../CheckContext';
import ContentColumn from '../layout/ContentColumn';
import ParsedText from '../ParsedText';
import {
  highlightBlue,
  titleStyle,
  listItemStyle,
  listStyle,
} from '../../../../config-styles';

const messages = defineMessages({
  editError: {
    id: 'sourceComponent.editError',
    defaultMessage: 'Sorry, could not edit the source',
  },
  editSuccess: {
    id: 'sourceComponent.editSuccess',
    defaultMessage: 'Source information updated successfully!',
  },
});

class SourceComponent extends Component {

  constructor(props) {
    super(props);
    const source = this.props.source;
    this.state = {
      message: null,
      isEditing: false,
      submitDisabled: false,
      values: {
        name: source.name,
        description: source.description,
      },
    };
  }

  componentDidMount() {
    this.setContextSource();
  }

  componentDidUpdate() {
    this.setContextSource();
  }

  setContextSource() {
    // const context = new CheckContext(this);
    // const store = context.getContextStore();
    // const { team, project_id, source_id } = this.props.source;
    //
    // console.log('team');
    // console.log(team);
    // console.log('project_id');
    // console.log(project_id);
    // console.log('source_id');
    // console.log(source_id);
    //
    // const sourceUrl = `/${team.slug}/project/${project_id}/source/${source_id}`;
    //
    // if (!store.team || store.team.slug !== team.slug) {
    //   context.setContextStore({ team });
    //   // const path = `/${team.slug}`;
    //   store.history.push(sourceUrl);
    // }
  }

  render() {
    const source = this.props.source;
    const isEditing = this.state.isEditing;

    return (
      <PageTitle prefix={source.name} skipTeam={false} team={source.team}>

          <Card className="team__profile team__profile--editing">
            <ContentColumn>
              <Message message={this.state.message} />

                      <div
                        className="team__avatar"
                        style={{ backgroundImage: `url(${source.image})` }}
                      />

                          {source.name}

                            {<ParsedText text={source.description} /> ||
                              <MappedMessage
                                msgObj={messages}
                                msgKey="verificationTeam"
                              />}

                        <FormattedHTMLMessage id="sourceComponent.dateAdded" defaultMessage="Added {date} • Source of {number} links"
                          values={{
                            date: this.props.intl.formatDate(source.created_at, { year: 'numeric', month: 'short', day: '2-digit'}),
                            number: source.medias.edges.length,
                          }}
                        />

                    <Can
                      permissions={source.permissions}
                      permission="update Source"
                    >
                      <IconButton
                        className="team__edit-button"
                        tooltip={
                          <FormattedMessage
                            id="teamComponent.editButton"
                            defaultMessage="Edit profile"
                          />
                        }
                        tooltipPosition="top-center"
                      >
                        <MDEdit />
                      </IconButton>
                    </Can>

                <CardActions className="source-component__tabs">
            </ContentColumn>
              <FlatButton label={<FormattedMessage id="sourceComponent.notes" defaultMessage="Notes" />} />
              <FlatButton label={<FormattedMessage id="sourceComponent.medias" defaultMessage="Media" />} />
              <FlatButton label={<FormattedMessage id="sourceComponent.network" defaultMessage="Network" />} />
            </CardActions>
          </Card>
          <ContentColumn>
            <Medias medias={source.medias.edges} />
          </ContentColumn>

      </PageTitle>
    );
  }
}

SourceComponent.propTypes = {
  intl: intlShape.isRequired,
  source: PropTypes.object,
};

SourceComponent.contextTypes = {
  store: React.PropTypes.object,
};

export default injectIntl(SourceComponent);
<|endoftext|>