<commit_before>"use strict";

var Container,

    Wrap = require('./Wrap'),
    Loader = require('../Loader/Loader'),

    ensure = require('ensure.js'),
    Nullable = ensure.Nullable,
    introspect = require('retrieve-arguments');

/**
 * Enclosure Container
 *
 * An IOC Container
 *
 * @constructor
 */
Container = function () {
    /**
     * Container bindings
     *
     * @type {Array}
     */
    this.bindings = [];

    /**
     * Singleton instances
     *
     * @type {Array}
     */
    this.instances = [];

    /**
     * Factory functions
     *
     * @type {Array}
     */
    this.factories = [];

    /**
     * Abstract types that should be shared (singletons after built)
     *
     * @type {Array}
     */
    this.shared = [];

    this.buildStack = [];

    /**
     * Class loader
     *
     * @type {null|Loader}
     */
    this.loader = null;

    /**
     * The max depth dependencies will be explored
     *
     * Circular dependencies or overly complex applications
     * might cause the container to reach this limit and bail.
     *
     * If you are encountering this issue, you can increase the value below
     *
     * @type {number}
     */
    this.maxDepth = 255;

    /**
     * Make the container available as a service
     */
    this.instance('EnclosureContainer', this);
};

/**
 * Bind a singleton instance to an abstract
 *
 * @param abstract
 * @param instance
 */
Container.prototype.instance = function (abstract, instance) {
    // If the abstract is an array, we will assume it is an array of strings
    // of each each abstract we want to bind the instance to
    if (ensure.isArray(abstract)) {
        abstract.forEach(function (single) {
            ensure(single, String);

            this.instances[single] = instance;
        }.bind(this));
    } else {
        ensure(abstract, String);

        this.instances[abstract] = instance;
    }
};

/**
 * Bind an abstract with a concrete with an abstract
 *
 * Acceptable concrete types are Wrap objects or a String
 * reference to another abstract type which eventually
 * should resolve into a concrete
 *
 * @param abstract
 * @param concrete
 * @param shared
 */
Container.prototype.bind = function (abstract, concrete, shared) {
    ensure(abstract, String);
    // TODO: Type-check concrete param once ensure.js supports Maybe

    // If the concrete implementation is either a string or a Wrap,
    // we just create a binding
    if (concrete instanceof Wrap
        || concrete instanceof Function
        || ensure.isString(concrete)) {
        this.bindings[abstract] = concrete;

        if (shared) {
            this.shared[abstract] = true;
        }

        return;
    }

    throw new Error('Unsupported binding type');
};

/**
 * Bind a factory function to an abstract
 *
 * @param abstract
 * @param concrete
 * @param shared
 */
Container.prototype.factory = function (abstract, concrete, shared) {
    ensure(abstract, String);
    ensure(concrete, Function);

    this.factories[abstract] = concrete;

    if (shared) {
        this.shared[abstract] = true;
    }
};

/**
 * Attempt to find the concrete implementation associated with
 * an abstract
 *
 * @param abstract
 * @returns {*}
 */
Container.prototype.getConcrete = function (abstract) {
    // If the abstract is not defined in the bindings array
    // then we can't find a concrete, so we have to bail
    if (!(abstract in this.bindings) && !(abstract in this.factories)) {
        throw new Error(
            'Unable to resolve concrete type: ' + abstract
        );
    }

    if (abstract in this.bindings) {
        var concrete = this.bindings[abstract];

        // If the concrete is a string, then it still is abstract
        // so we need to recurse and try to find it's concrete
        if (ensure.isString(concrete)) {
            return this.getConcrete(concrete);
        }

        // If there is a Wrap or constructor bound to the abstract, then we know
        // it is actually already concrete already
        if (concrete instanceof Wrap || concrete instanceof Function) {
            return abstract;
        }
    } else if (abstract in this.factories) {
        // If there is a factory function for the abstract, then we know
        // it is actually a concrete already
        return abstract;
    }

    throw new Error('Unable to resolve concrete type. Unknown binding type');
};

/**
 * Resolve the abstract in the container
 *
 * @param abstract
 * @returns {*}
 */
Container.prototype.make = function (abstract) {
    // If there is a singleton instance being managed, return it
    if (abstract in this.instances) {
        return this.instances[abstract];
    }

    // Get concrete
    var concrete = abstract;
    try {
        concrete = this.getConcrete(abstract);

        // If buildable, build one
        if (this.isBuildable(concrete)) {
            var instance = this.build(concrete);

            // If the abstract type is marked as shared, we will cache the
            // instance as a singleton so subsequent calls to make will return
            // the same instance
            if (abstract in this.shared) {
                this.instance(abstract, instance);
            }

            return instance;
        }
    } catch (err) {
        // Fall back to building a class using the loader (if it is present)
        if (this.loader && this.loader.has(abstract)) {
            var constructor = this.loader.get(abstract);
            var dependencies = this.resolveDependencies(constructor);

            var instance = Object.create(constructor.prototype);

            constructor.apply(instance, dependencies);

            return instance;
        }

        throw err;
    }

    throw new Error('Unable to build abstract: ' + abstract);
};

Container.prototype.build = function (concrete, parameters) {
    parameters = parameters || [];

    // Check if there is a factory function defined for this function
    // If there is one, we will use it to build the instance. This
    // allows functions to be defined as more refined resolvers
    if (concrete in this.factories) {
        var factoryArguments = [this].concat(parameters);

        var factoryFunction = this.factories[concrete];

        return factoryFunction.apply(
            Object.create(factoryFunction.prototype),
            factoryArguments
        );
    }

    this.buildStack.push(concrete);

    // Check if we have descended too much into the dependency tree.
    // This could mean we have a circular dependency or a very complex
    // application
    if (this.buildStack.length > this.maxDepth) {
        throw new Error(
            'Max dependency depth reached.'
            + 'Possible circular dependency'
        );
    }

    // If the concrete is a Wrap object, we can resolve its dependencies
    // and then construct an instance
    if (this.isWrapped(concrete)) {
        var wrap = this.bindings[concrete];

        var dependencies = this.resolveDependencies(wrap);

        // When calling the constructor in the Wrap object, we pass a reference
        // to this container, and all the dependencies as arguments
        var constructorArguments = [this].concat(dependencies, parameters);

        var constructor =  wrap.getConstructor();

        this.buildStack.pop();

        return constructor.apply(
            Object.create(constructor.prototype),
            constructorArguments
        );
    }

    // If the concrete is just a function, then we will assume it is a service
    // constructor. We will use introspection to find out which are its
    // dependencies
    if (
        concrete in this.bindings
        && this.bindings[concrete] instanceof Function
    ) {
        var constructor = this.bindings[concrete];

        var dependencies = this.resolveDependencies(constructor);

        this.buildStack.pop();

        // Do some magic to call new with a variable number of arguments
        // See http://goo.gl/R7Dpt
        var instance = Object.create(constructor.prototype);

        constructor.apply(instance, dependencies);

        return instance;
    }

    throw new Error('Unable to resolve. The concrete type is not instantiable');
};

/**
 * Use the container to get the dependencies of a Wrap or a constructor function
 *
 * @param construct
 * @returns {Array}
 */
Container.prototype.resolveDependencies = function (construct) {
    var dependenciesNames = [],
        dependencies = [];

    if (construct instanceof Wrap) {
        dependenciesNames = construct.getDependencies();
    } else if (construct instanceof Function) {
        dependenciesNames = introspect(construct);
    } else {
        throw new Error('Expected either a Wrap or function');
    }

    dependenciesNames.forEach(function (dependencyName) {
        dependencies.push(this.make(dependencyName))
    }.bind(this));

    return dependencies;
};

/**
 * Check that a concrete object is wrapped in an Enclosure wrap
 *
 * @param concrete
 * @returns {boolean}
 */
Container.prototype.isWrapped = function (concrete) {
    return (concrete in this.bindings &&
        this.bindings[concrete] instanceof Wrap);
};

/**
 * Check if an abstract is resolvable by this container
 *
 * @param abstract
 * @returns {boolean}
 */
Container.prototype.isResolvable = function (abstract) {
    if (this.instances[abstract]) {
        return true;
    }

    try {
        var concrete = this.getConcrete(abstract);

        return true;
    } catch (err) {
        return false;
    }
};

/**
 * Get whether a concrete type can be built by this container
 *
 * @param concrete
 * @returns {boolean}
 */
Container.prototype.isBuildable = function (concrete) {
    // If we have a factory function, we can build the type
    if (concrete in this.factories) {
        return true;
    }

    // If we have a wrap or constructor, we can also build it
    if (concrete in this.bindings
        && (this.bindings[concrete] instanceof Wrap)
        || (this.bindings[concrete] instanceof Function)) {
        return true;
    }

    return false;
};

/**
 * Set the loader to use for automatic class loading and instantiation
 *
 * @param loader
 */
Container.prototype.setLoader = function (loader) {
    ensure(loader, Loader);

    this.loader = loader;

    this.instance('Chromabits/Loader/Loader', loader);
};

/**
 * Load a class constructor
 *
 * A simple alias for the Loader's get method
 *
 * @param fullClassName
 * @returns {Function}
 */
Container.prototype.use = function (fullClassName) {
    if (this.loader) {
        return this.loader.get(fullClassName);
    }

    throw new Error('This container does not have a loader attached');
};

/**
 * Installs container shortcut properties into a specific object
 *
 * This is useful for making the container available on the global or window
 * contexts.
 *
 * @param target
 */
Container.prototype.installTo = function (target) {
    ensure(target, Object);

    target.container = this;
    target.use = this.use.bind(this);
};

module.exports = Container;
<commit_msg>Loosen up how dependencies are resolved<commit_after>"use strict";

var Container,

    Wrap = require('./Wrap'),
    Loader = require('../Loader/Loader'),

    ensure = require('ensure.js'),
    Nullable = ensure.Nullable,
    introspect = require('retrieve-arguments');

/**
 * Enclosure Container
 *
 * An IOC Container
 *
 * @constructor
 */
Container = function () {
    /**
     * Container bindings
     *
     * @type {Array}
     */
    this.bindings = [];

    /**
     * Singleton instances
     *
     * @type {Array}
     */
    this.instances = [];

    /**
     * Factory functions
     *
     * @type {Array}
     */
    this.factories = [];

    /**
     * Abstract types that should be shared (singletons after built)
     *
     * @type {Array}
     */
    this.shared = [];

    this.buildStack = [];

    /**
     * Class loader
     *
     * @type {null|Loader}
     */
    this.loader = null;

    /**
     * The max depth dependencies will be explored
     *
     * Circular dependencies or overly complex applications
     * might cause the container to reach this limit and bail.
     *
     * If you are encountering this issue, you can increase the value below
     *
     * @type {number}
     */
    this.maxDepth = 255;

    /**
     * Make the container available as a service
     */
    this.instance('EnclosureContainer', this);
};

/**
 * Bind a singleton instance to an abstract
 *
 * @param abstract
 * @param instance
 */
Container.prototype.instance = function (abstract, instance) {
    // If the abstract is an array, we will assume it is an array of strings
    // of each each abstract we want to bind the instance to
    if (ensure.isArray(abstract)) {
        abstract.forEach(function (single) {
            ensure(single, String);

            this.instances[single] = instance;
        }.bind(this));
    } else {
        ensure(abstract, String);

        this.instances[abstract] = instance;
    }
};

/**
 * Bind an abstract with a concrete with an abstract
 *
 * Acceptable concrete types are Wrap objects or a String
 * reference to another abstract type which eventually
 * should resolve into a concrete
 *
 * @param abstract
 * @param concrete
 * @param shared
 */
Container.prototype.bind = function (abstract, concrete, shared) {
    ensure(abstract, String);
    // TODO: Type-check concrete param once ensure.js supports Maybe

    // If the concrete implementation is either a string or a Wrap,
    // we just create a binding
    if (concrete instanceof Wrap
        || concrete instanceof Function
        || ensure.isString(concrete)) {
        this.bindings[abstract] = concrete;

        if (shared) {
            this.shared[abstract] = true;
        }

        return;
    }

    throw new Error('Unsupported binding type');
};

/**
 * Bind a factory function to an abstract
 *
 * @param abstract
 * @param concrete
 * @param shared
 */
Container.prototype.factory = function (abstract, concrete, shared) {
    ensure(abstract, String);
    ensure(concrete, Function);

    this.factories[abstract] = concrete;

    if (shared) {
        this.shared[abstract] = true;
    }
};

/**
 * Attempt to find the concrete implementation associated with
 * an abstract
 *
 * @param abstract
 * @returns {*}
 */
Container.prototype.getConcrete = function (abstract) {
    // If the abstract is not defined in the bindings array
    // then we can't find a concrete, so we have to bail
    if (!(abstract in this.bindings) && !(abstract in this.factories)) {
        throw new Error(
            'Unable to resolve concrete type: ' + abstract
        );
    }

    if (abstract in this.bindings) {
        var concrete = this.bindings[abstract];

        // If the concrete is a string, then it still is abstract
        // so we need to recurse and try to find it's concrete
        if (ensure.isString(concrete)) {
            return this.getConcrete(concrete);
        }

        // If there is a Wrap or constructor bound to the abstract, then we know
        // it is actually already concrete already
        if (concrete instanceof Wrap || concrete instanceof Function) {
            return abstract;
        }
    } else if (abstract in this.factories) {
        // If there is a factory function for the abstract, then we know
        // it is actually a concrete already
        return abstract;
    }

    throw new Error('Unable to resolve concrete type. Unknown binding type');
};

/**
 * Resolve the abstract in the container
 *
 * @param abstract
 * @returns {*}
 */
Container.prototype.make = function (abstract) {
    // If there is a singleton instance being managed, return it
    if (abstract in this.instances) {
        return this.instances[abstract];
    }

    // Get concrete
    var concrete = abstract;
    try {
        concrete = this.getConcrete(abstract);

        // If buildable, build one
        if (this.isBuildable(concrete)) {
            var instance = this.build(concrete);

            // If the abstract type is marked as shared, we will cache the
            // instance as a singleton so subsequent calls to make will return
            // the same instance
            if (abstract in this.shared) {
                this.instance(abstract, instance);
            }

            return instance;
        }
    } catch (err) {
        // Fall back to building a class using the loader (if it is present)
        if (this.loader && this.loader.has(abstract)) {
            var constructor = this.loader.get(abstract);
            var dependencies = this.resolveDependencies(constructor);

            var instance = Object.create(constructor.prototype);

            constructor.apply(instance, dependencies);

            return instance;
        }

        throw err;
    }

    throw new Error('Unable to build abstract: ' + abstract);
};

Container.prototype.build = function (concrete, parameters) {
    parameters = parameters || [];

    // Check if there is a factory function defined for this function
    // If there is one, we will use it to build the instance. This
    // allows functions to be defined as more refined resolvers
    if (concrete in this.factories) {
        var factoryArguments = [this].concat(parameters);

        var factoryFunction = this.factories[concrete];

        return factoryFunction.apply(
            Object.create(factoryFunction.prototype),
            factoryArguments
        );
    }

    this.buildStack.push(concrete);

    // Check if we have descended too much into the dependency tree.
    // This could mean we have a circular dependency or a very complex
    // application
    if (this.buildStack.length > this.maxDepth) {
        throw new Error(
            'Max dependency depth reached.'
            + 'Possible circular dependency'
        );
    }

    // If the concrete is a Wrap object, we can resolve its dependencies
    // and then construct an instance
    if (this.isWrapped(concrete)) {
        var wrap = this.bindings[concrete];

        var dependencies = this.resolveDependencies(wrap);

        // When calling the constructor in the Wrap object, we pass a reference
        // to this container, and all the dependencies as arguments
        var constructorArguments = [this].concat(dependencies, parameters);

        var constructor =  wrap.getConstructor();

        this.buildStack.pop();

        return constructor.apply(
            Object.create(constructor.prototype),
            constructorArguments
        );
    }

    // If the concrete is just a function, then we will assume it is a service
    // constructor. We will use introspection to find out which are its
    // dependencies
    if (
        concrete in this.bindings
        && this.bindings[concrete] instanceof Function
    ) {
        var constructor = this.bindings[concrete];

        var dependencies = this.resolveDependencies(constructor);

        this.buildStack.pop();

        // Do some magic to call new with a variable number of arguments
        // See http://goo.gl/R7Dpt
        var instance = Object.create(constructor.prototype);

        constructor.apply(instance, dependencies);

        return instance;
    }

    throw new Error('Unable to resolve. The concrete type is not instantiable');
};

/**
 * Use the container to get the dependencies of a Wrap or a constructor function
 *
 * @param construct
 * @returns {Array}
 */
Container.prototype.resolveDependencies = function (construct) {
    var dependenciesNames = [],
        dependencies = [];

    if (construct instanceof Wrap) {
        dependenciesNames = construct.getDependencies();
    } else if (construct instanceof Function) {
        dependenciesNames = introspect(construct);
    }

    dependenciesNames.forEach(function (dependencyName) {
        dependencies.push(this.make(dependencyName))
    }.bind(this));

    return dependencies;
};

/**
 * Check that a concrete object is wrapped in an Enclosure wrap
 *
 * @param concrete
 * @returns {boolean}
 */
Container.prototype.isWrapped = function (concrete) {
    return (concrete in this.bindings &&
        this.bindings[concrete] instanceof Wrap);
};

/**
 * Check if an abstract is resolvable by this container
 *
 * @param abstract
 * @returns {boolean}
 */
Container.prototype.isResolvable = function (abstract) {
    if (this.instances[abstract]) {
        return true;
    }

    try {
        var concrete = this.getConcrete(abstract);

        return true;
    } catch (err) {
        return false;
    }
};

/**
 * Get whether a concrete type can be built by this container
 *
 * @param concrete
 * @returns {boolean}
 */
Container.prototype.isBuildable = function (concrete) {
    // If we have a factory function, we can build the type
    if (concrete in this.factories) {
        return true;
    }

    // If we have a wrap or constructor, we can also build it
    if (concrete in this.bindings
        && (this.bindings[concrete] instanceof Wrap)
        || (this.bindings[concrete] instanceof Function)) {
        return true;
    }

    return false;
};

/**
 * Set the loader to use for automatic class loading and instantiation
 *
 * @param loader
 */
Container.prototype.setLoader = function (loader) {
    ensure(loader, Loader);

    this.loader = loader;

    this.instance('Chromabits/Loader/Loader', loader);
};

/**
 * Load a class constructor
 *
 * A simple alias for the Loader's get method
 *
 * @param fullClassName
 * @returns {Function}
 */
Container.prototype.use = function (fullClassName) {
    if (this.loader) {
        return this.loader.get(fullClassName);
    }

    throw new Error('This container does not have a loader attached');
};

/**
 * Installs container shortcut properties into a specific object
 *
 * This is useful for making the container available on the global or window
 * contexts.
 *
 * @param target
 */
Container.prototype.installTo = function (target) {
    ensure(target, Object);

    target.container = this;
    target.use = this.use.bind(this);
};

module.exports = Container;
<|endoftext|>


<commit_before>// Build User: ${build.user}
// Version: ${build.version}
// Build Date: ${build.date}

(function(root, factory) {
    'use strict';

    // Determine the module system (if any)
    if ('function' === typeof define && define.amd) {
        // AMD
        define([root], factory);
    } else {
        // Node
        if ('undefined' !== typeof exports) {
            module.exports = factory(root);
        } else {
            // None
            root.ChromeExtensionSettingsManager = factory(root);
        }
    }
})(window || this, function(global) {
    'use strict';

    var isFunction = function isFunction(func) {
        return 'function' === typeof func;
    },
    ChromeExtensionSettingsManager = function ChromeExtensionSettingsManager() {

        if (!(this instanceof ChromeExtensionSettingsManager)) {
            return new ChromeExtensionSettingsManager();
        }

        var load = function(successCallback, errorCallback) {
            global.chrome.storage.sync.get(function(settings) {
                if (!!global.chrome.runtime.lastError && isFunction(errorCallback)) {
                    errorCallback.call(null);
                } else if (!global.chrome.runtime.lastError && isFunction(successCallback)) {
                    successCallback.call(null, settings);
                }
            });
        },
        save = function(settings, successCallback, errorCallback) {
            global.chrome.storage.sync.set(settings, function() {
                if (!!global.chrome.runtime.lastError && isFunction(errorCallback)) {
                    errorCallback.call(null);
                } else if (!global.chrome.runtime.lastError && isFunction(successCallback)) {
                    successCallback.call(null);
                }
            });
        },
        clear = function(successCallback, errorCallback) {
            global.chrome.storage.sync.clear(function() {
                if (!!global.chrome.runtime.lastError && isFunction(errorCallback)) {
                    errorCallback.call(null);
                } else if (!global.chrome.runtime.lastError && isFunction(successCallback)) {
                    successCallback.call(null);
                }
            });
        };

        return {
            load: load,
            save: save,
            clear: clear
        };

    };

    // Place the version as a member in the function
    ChromeExtensionSettingsManager.version = '${build.version}';

    return ChromeExtensionSettingsManager;
});<commit_msg>Added documentation<commit_after>// Build User: ${build.user}
// Version: ${build.version}
// Build Date: ${build.date}

(function(root, factory) {
    'use strict';

    // Determine the module system (if any)
    if ('function' === typeof define && define.amd) {
        // AMD
        define([root], factory);
    } else {
        // Node
        if ('undefined' !== typeof exports) {
            module.exports = factory(root);
        } else {
            // None
            root.ChromeExtensionSettingsManager = factory(root);
        }
    }
})(window || this, function(global) {
    'use strict';

    var isFunction = function isFunction(func) {
        return 'function' === typeof func;
    },
    /**
     * Implementation for SettingsManager adapter for the Chrome Extension Settings API.
     */
    ChromeExtensionSettingsManager = function ChromeExtensionSettingsManager() {

        if (!(this instanceof ChromeExtensionSettingsManager)) {
            return new ChromeExtensionSettingsManager();
        }

        /**
         * Loads values.
         *
         * @param {Function} successCallback the callback invoked on success (with parameter {})
         */
        var load = function(successCallback, errorCallback) {
            global.chrome.storage.sync.get(function(settings) {
                if (!!global.chrome.runtime.lastError && isFunction(errorCallback)) {
                    errorCallback.call(null);
                } else if (!global.chrome.runtime.lastError && isFunction(successCallback)) {
                    successCallback.call(null, settings);
                }
            });
        },
        /**
         * Saves values.
         *
         * @param {Object} settings the settings to save
         * @param {Function} successCallback the success callback to invoke on success
         */
        save = function(settings, successCallback, errorCallback) {
            global.chrome.storage.sync.set(settings, function() {
                if (!!global.chrome.runtime.lastError && isFunction(errorCallback)) {
                    errorCallback.call(null);
                } else if (!global.chrome.runtime.lastError && isFunction(successCallback)) {
                    successCallback.call(null);
                }
            });
        },
        /**
         * Clears values.
         *
         * @param {Function} successCallback the success callback to invoke on success
         */
        clear = function(successCallback, errorCallback) {
            global.chrome.storage.sync.clear(function() {
                if (!!global.chrome.runtime.lastError && isFunction(errorCallback)) {
                    errorCallback.call(null);
                } else if (!global.chrome.runtime.lastError && isFunction(successCallback)) {
                    successCallback.call(null);
                }
            });
        };

        return {
            load: load,
            save: save,
            clear: clear
        };

    };

    // Place the version as a member in the function
    ChromeExtensionSettingsManager.version = '${build.version}';

    return ChromeExtensionSettingsManager;
});<|endoftext|>


<commit_before>import React, {Component} from 'react';

import Widget from 'src/Widget';
import WidgetHeader from 'src/WidgetHeader';
import PropTypeDescTable from '../PropTypeDescTable';
import Paper from 'src/Paper';
import Tree from 'src/Tree';
import doc from 'examples/assets/propTypes/Tree.json';

import 'sass/containers/app/modules/layout/TreeExamples.scss';

export default class TreeExamples extends Component {

    constructor(props) {

        super(props);

        this.data = [{
            id: '0',
            text: 'Root',
            desc: 'Root',
            children: [{
                id: '00',
                text: 'Children 0 - 0',
                desc: 'Children 0 - 0'
            }, {
                id: '01',
                text: 'Children 0 - 1',
                desc: 'Children 0 - 1',
                children: [{
                    id: '010',
                    text: 'Children 0 - 1 - 0',
                    desc: 'Children 0 - 1 - 0'
                }, {
                    id: '011',
                    text: 'Children 0 - 1 - 1',
                    desc: 'Children 0 - 1 - 1'
                }, {
                    id: '012',
                    text: 'Children 0 - 1 - 2',
                    desc: 'Children 0 - 1 - 2'
                }]
            }, {
                id: '02',
                text: 'Children 0 - 2',
                desc: 'Children 0 - 2'
            }]
        }];

        this.changeHandler = this::this.changeHandler;

    }

    nodeSelectHandler(node, path) {
        console.log('Node Selected::', node, path);
    }

    changeHandler(value) {
        console.log('Changed::', value);
    }

    render() {
        return (

Tree

                    Tree can fully display the hierarchy, and has interactive functions such as
                    expansion, withdrawal and selection.

Examples

                <Widget>

                    <WidgetHeader className="example-header"
                                  title="Basic"/>

Treesimple example.

                                <Paper className="tree-wrapper">
                                    <Tree data={this.data}
                                          onNodeSelect={this.nodeSelectHandler}
                                          onChange={this.changeHandler}/>
                                </Paper>

                </Widget>

                <Widget>

                    <WidgetHeader className="example-header"
                                  title="Self Define Node Renderer"/>

                                <Paper className="tree-wrapper">
                                    <Tree data={this.data}
                                          collapsedIconCls="fa fa-plus-square-o"
                                          expandedIconCls="fa fa-minus-square-o"
                                          renderer={node => {
                                              return

                                                  {node.id}
                                                  {node.text}
                                                  {node.desc}

;
                                          }}
                                          onNodeSelect={this.nodeSelectHandler}
                                          onChange={this.changeHandler}/>
                                </Paper>

                </Widget>

                <Widget>

                    <WidgetHeader className="example-header"
                                  title="Multi Select"/>

                                <Paper className="tree-wrapper">
                                    <Tree selectMode={Tree.SelectMode.MULTI_SELECT}
                                          data={this.data}
                                          onNodeSelect={this.nodeSelectHandler}
                                          onChange={this.changeHandler}/>
                                </Paper>

                </Widget>

Properties

                <PropTypeDescTable data={doc}/>

        );
    }
};<commit_msg>update Tree examples<commit_after>import React, {Component} from 'react';

import Widget from 'src/Widget';
import WidgetHeader from 'src/WidgetHeader';
import PropTypeDescTable from '../PropTypeDescTable';
import Paper from 'src/Paper';
import Tree from 'src/Tree';
import doc from 'examples/assets/propTypes/Tree.json';

import 'sass/containers/app/modules/layout/TreeExamples.scss';

export default class TreeExamples extends Component {

    constructor(props) {

        super(props);

        this.data = {
            id: '0',
            text: 'Root',
            desc: 'Root',
            children: [{
                id: '00',
                text: 'Children 0 - 0',
                desc: 'Children 0 - 0'
            }, {
                id: '01',
                text: 'Children 0 - 1',
                desc: 'Children 0 - 1',
                children: [{
                    id: '010',
                    text: 'Children 0 - 1 - 0',
                    desc: 'Children 0 - 1 - 0'
                }, {
                    id: '011',
                    text: 'Children 0 - 1 - 1',
                    desc: 'Children 0 - 1 - 1'
                }, {
                    id: '012',
                    text: 'Children 0 - 1 - 2',
                    desc: 'Children 0 - 1 - 2'
                }]
            }, {
                id: '02',
                text: 'Children 0 - 2',
                desc: 'Children 0 - 2'
            }]
        };

        this.changeHandler = this::this.changeHandler;

    }

    nodeSelectHandler(node, path) {
        console.log('Node Selected::', node, path);
    }

    changeHandler(value) {
        console.log('Changed::', value);
    }

    render() {
        return (

Tree

                    Tree can fully display the hierarchy, and has interactive functions such as
                    expansion, withdrawal and selection.

Examples

                <Widget>

                    <WidgetHeader className="example-header"
                                  title="Basic"/>

Treesimple example.

                                <Paper className="tree-wrapper">
                                    <Tree data={this.data}
                                          onNodeSelect={this.nodeSelectHandler}
                                          onChange={this.changeHandler}/>
                                </Paper>

                </Widget>

                <Widget>

                    <WidgetHeader className="example-header"
                                  title="Self Define Node Renderer"/>

                                <Paper className="tree-wrapper">
                                    <Tree data={this.data}
                                          collapsedIconCls="fa fa-plus-square-o"
                                          expandedIconCls="fa fa-minus-square-o"
                                          renderer={node => {
                                              return

                                                  {node.id}
                                                  {node.text}
                                                  {node.desc}

;
                                          }}
                                          onNodeSelect={this.nodeSelectHandler}
                                          onChange={this.changeHandler}/>
                                </Paper>

                </Widget>

                <Widget>

                    <WidgetHeader className="example-header"
                                  title="Multi Select"/>

                                <Paper className="tree-wrapper">
                                    <Tree selectMode={Tree.SelectMode.MULTI_SELECT}
                                          data={this.data}
                                          onNodeSelect={this.nodeSelectHandler}
                                          onChange={this.changeHandler}/>
                                </Paper>

                </Widget>

Properties

                <PropTypeDescTable data={doc}/>

        );
    }
};<|endoftext|>


<commit_before>var tags = [],
	textLen = text.length;

foreach(matches, function(m)
{
	var bbcodeName = m[1][0].toUpperCase();

	if (!config.bbcodesConfig[bbcodeName])
	{
		// Not a known BBCode
		return;
	}

	var bbcodeConfig = config.bbcodesConfig[bbcodeName],
	    tagName      = bbcodeConfig.tagName;

	/**
	* Position of the first character of current BBCode, which should be a [
	*/
	var lpos = m[0][1];

	/**
	* Position of the last character of current BBCode, starts as the position of
	* the =, ] or : char, then moves to the right as the BBCode is parsed
	*/
	var rpos = lpos + m[0][0].length;

	/**
	* Attributes parsed from the text
	*/
	var attrs = {};

	/**
	* Check for BBCode suffix
	*
	* Used to skip the parsing of closing BBCodes, e.g.
	*   [code:1][code]type your code here[/code][/code:1]
	*
	*/
	var suffix = '';

	if (text[rpos] === ':')
	{
		/**
		* [code:1] or [/code:1]
		* suffix = ':1'
		*/
		suffix  = /^[0-9]*/.exec(text.substr(++rpos))[0];
		rpos   += suffix.length;
	}

	var type;

	if (m[0][0][1] === '/')
	{
		if (text[rpos] !== ']')
		{
			log('warning', {
				'pos'    : rpos,
				'len'    : 1,
				'msg'    : 'Unexpected character: expected %1$s found %2$s',
				'params' : [']', text[rpos]]
			});
			return;
		}

		type = END_TAG;
	}
	else
	{
		type = START_TAG;

		var wellFormed = false,
		    attrName   = '';

		if (text[rpos] === '=')
		{
			/**
			* [quote=
			*
			* Set the default param. If there's no default param, we issue a warning and
			* reuse the BBCode's name instead
			*/
			if (bbcodeConfig.defaultAttr)
			{
				attrName = bbcodeConfig.defaultAttr;
			}
			else
			{
				attrName = bbcodeName.toLowerCase();

				log('debug', {
					'pos'    : rpos,
					'len'    : 1,
					'msg'    : 'BBCode %1$s does not have a default attribute, using BBCode name as attribute name',
					'params' : [bbcodeName]
				});
			}

			++rpos;
		}

		while (rpos < textLen)
		{
			var c = text[rpos];

			if (c === ']' || c === '/')
			{
				/**
				* We're closing this tag
				*/
				if (attrName)
				{
					/**
					* [quote=]
					* [quote username=]
					*/
					log('warning', {
						'pos'    : rpos,
						'len'    : 1,
						'msg'    : 'Unexpected character %s',
						'params' : [c]
					});
					return;
				}

				if (c === '/')
				{
					/**
					* Self-closing tag, e.g. [foo/]
					*/
					type = SELF_CLOSING_TAG;
					++rpos;

					if (rpos === textLen)
					{
						// text ends with [some tag/
						return;
					}

					c = text[rpos];
					if (c !== ']')
					{
						log('warning', {
							'pos'    : rpos,
							'len'    : 1,
							'msg'    : 'Unexpected character: expected %1$s found %2$s',
							'params' : [']', c]
						});
						return;
					}
				}

				wellFormed = true;
				break;
			}

			if (c === ' ')
			{
				++rpos;
				continue;
			}

			if (!attrName)
			{
				/**
				* Capture the attribute name
				*/
				attrName = /^[a-z_0-9]*/i.exec(text.substr(rpos))[0].toLowerCase();

				if (!attrName)
				{
					log('warning', {
						'pos'    : rpos,
						'len'    : 1,
						'msg'    : 'Unexpected character %s',
						'params' : [c]
					});
					return;
				}

				if (rpos + attrName.length >= textLen)
				{
					log('debug', {
						'pos' : rpos,
						'len' : attrName.length,
						'msg' : 'Attribute name seems to extend till the end of text'
					});
					return;
				}

				rpos += attrName.length;

				if (text[rpos] !== '=')
				{
					log('debug', {
						'pos'    : rpos,
						'len'    : 1,
						'msg'    : 'Unexpected character: expected %1$s found %2$s',
						'params' : ['=', text[rpos]]
					});
					return;
				}

				++rpos;
				continue;
			}

			if (c === '"' || c === "'")
			{
				var valuePos = rpos + 1;

				while (++rpos < textLen)
				{
					rpos = text.indexOf(c, rpos);

					if (rpos === -1)
					{
						/**
						* No matching quote, apparently that string never ends...
						*/
						log('warning', {
							'pos' : valuePos - 1,
							'len' : 1,
							'msg' : 'Could not find matching quote'
						});
						return;
					}

					if (text[rpos - 1] === '\\')
					{
						var n = 1;
						do
						{
							++n;
						}
						while (text[rpos - n] === '\\');

						if (n % 2 === 0)
						{
							continue;
						}
					}

					break;
				}

				value = text.substr(valuePos, rpos - valuePos).replace(/\\(.)/g, '$1');

				// Skip past the closing quote
				++rpos;
			}
			else
			{
				value = /^[^\] \n\r]*/.exec(text.substr(rpos))[0];
				rpos += value.length;
			}

			attrs[attrName] = value;
			attrName = '';
		}

		if (!wellFormed)
		{
			return;
		}

		var usesContent = false;

		if (type === START_TAG
		 && bbcodeConfig.contentAttr
		 && attrs[bbcodeConfig.contentAttr] === undefined)
		{
			/**
			* Capture the content of that tag and use it as attribute value
			*/
			var pos = text.toUpperCase().indexOf('[/' + bbcodeName + suffix + ']', rpos);

			if (pos > -1)
			{
				attrs[bbcodeConfig.contentAttr]
					= text.substr(1 + rpos, pos - (1 + rpos));

				usesContent = true;
			}
		}
	}

	if (type === START_TAG
	 && !usesContent
	 && bbcodeConfig.autoClose)
	{
		var endTag = '[/' + bbcodeName + suffix + ']';

		/**
		* Make sure that the start tag isn't immediately followed by an endtag
		*/
		if (text.substr(1 + rpos, endTag.length).toUpperCase() !== endTag)
		{
			type = SELF_CLOSING_TAG;
		}
	}

	tags.push({
		name   : tagName,
		pos    : lpos,
		len    : rpos + 1 - lpos,
		type   : type,
		suffix : suffix,
		attrs  : attrs
	});
});

return tags;<commit_msg>TextFormatter: fixed suffix to include the leading colon<commit_after>var tags = [],
	textLen = text.length;

foreach(matches, function(m)
{
	var bbcodeName = m[1][0].toUpperCase();

	if (!config.bbcodesConfig[bbcodeName])
	{
		// Not a known BBCode
		return;
	}

	var bbcodeConfig = config.bbcodesConfig[bbcodeName],
	    tagName      = bbcodeConfig.tagName;

	/**
	* Position of the first character of current BBCode, which should be a [
	*/
	var lpos = m[0][1];

	/**
	* Position of the last character of current BBCode, starts as the position of
	* the =, ] or : char, then moves to the right as the BBCode is parsed
	*/
	var rpos = lpos + m[0][0].length;

	/**
	* Attributes parsed from the text
	*/
	var attrs = {};

	/**
	* Check for BBCode suffix
	*
	* Used to skip the parsing of closing BBCodes, e.g.
	*   [code:1][code]type your code here[/code][/code:1]
	*
	*/
	var suffix = '';

	if (text[rpos] === ':')
	{
		/**
		* [code:1] or [/code:1]
		* suffix = ':1'
		*/
		suffix  = /^:[0-9]*/.exec(text.substr(rpos))[0];
		rpos   += suffix.length;
	}

	var type;

	if (m[0][0][1] === '/')
	{
		if (text[rpos] !== ']')
		{
			log('warning', {
				'pos'    : rpos,
				'len'    : 1,
				'msg'    : 'Unexpected character: expected %1$s found %2$s',
				'params' : [']', text[rpos]]
			});
			return;
		}

		type = END_TAG;
	}
	else
	{
		type = START_TAG;

		var wellFormed = false,
		    attrName   = '';

		if (text[rpos] === '=')
		{
			/**
			* [quote=
			*
			* Set the default param. If there's no default param, we issue a warning and
			* reuse the BBCode's name instead
			*/
			if (bbcodeConfig.defaultAttr)
			{
				attrName = bbcodeConfig.defaultAttr;
			}
			else
			{
				attrName = bbcodeName.toLowerCase();

				log('debug', {
					'pos'    : rpos,
					'len'    : 1,
					'msg'    : 'BBCode %1$s does not have a default attribute, using BBCode name as attribute name',
					'params' : [bbcodeName]
				});
			}

			++rpos;
		}

		while (rpos < textLen)
		{
			var c = text[rpos];

			if (c === ']' || c === '/')
			{
				/**
				* We're closing this tag
				*/
				if (attrName)
				{
					/**
					* [quote=]
					* [quote username=]
					*/
					log('warning', {
						'pos'    : rpos,
						'len'    : 1,
						'msg'    : 'Unexpected character %s',
						'params' : [c]
					});
					return;
				}

				if (c === '/')
				{
					/**
					* Self-closing tag, e.g. [foo/]
					*/
					type = SELF_CLOSING_TAG;
					++rpos;

					if (rpos === textLen)
					{
						// text ends with [some tag/
						return;
					}

					c = text[rpos];
					if (c !== ']')
					{
						log('warning', {
							'pos'    : rpos,
							'len'    : 1,
							'msg'    : 'Unexpected character: expected %1$s found %2$s',
							'params' : [']', c]
						});
						return;
					}
				}

				wellFormed = true;
				break;
			}

			if (c === ' ')
			{
				++rpos;
				continue;
			}

			if (!attrName)
			{
				/**
				* Capture the attribute name
				*/
				attrName = /^[a-z_0-9]*/i.exec(text.substr(rpos))[0].toLowerCase();

				if (!attrName)
				{
					log('warning', {
						'pos'    : rpos,
						'len'    : 1,
						'msg'    : 'Unexpected character %s',
						'params' : [c]
					});
					return;
				}

				if (rpos + attrName.length >= textLen)
				{
					log('debug', {
						'pos' : rpos,
						'len' : attrName.length,
						'msg' : 'Attribute name seems to extend till the end of text'
					});
					return;
				}

				rpos += attrName.length;

				if (text[rpos] !== '=')
				{
					log('debug', {
						'pos'    : rpos,
						'len'    : 1,
						'msg'    : 'Unexpected character: expected %1$s found %2$s',
						'params' : ['=', text[rpos]]
					});
					return;
				}

				++rpos;
				continue;
			}

			if (c === '"' || c === "'")
			{
				var valuePos = rpos + 1;

				while (++rpos < textLen)
				{
					rpos = text.indexOf(c, rpos);

					if (rpos === -1)
					{
						/**
						* No matching quote, apparently that string never ends...
						*/
						log('warning', {
							'pos' : valuePos - 1,
							'len' : 1,
							'msg' : 'Could not find matching quote'
						});
						return;
					}

					if (text[rpos - 1] === '\\')
					{
						var n = 1;
						do
						{
							++n;
						}
						while (text[rpos - n] === '\\');

						if (n % 2 === 0)
						{
							continue;
						}
					}

					break;
				}

				value = text.substr(valuePos, rpos - valuePos).replace(/\\(.)/g, '$1');

				// Skip past the closing quote
				++rpos;
			}
			else
			{
				value = /^[^\] \n\r]*/.exec(text.substr(rpos))[0];
				rpos += value.length;
			}

			attrs[attrName] = value;
			attrName = '';
		}

		if (!wellFormed)
		{
			return;
		}

		var usesContent = false;

		if (type === START_TAG
		 && bbcodeConfig.contentAttr
		 && attrs[bbcodeConfig.contentAttr] === undefined)
		{
			/**
			* Capture the content of that tag and use it as attribute value
			*/
			var pos = text.toUpperCase().indexOf('[/' + bbcodeName + suffix + ']', rpos);

			if (pos > -1)
			{
				attrs[bbcodeConfig.contentAttr]
					= text.substr(1 + rpos, pos - (1 + rpos));

				usesContent = true;
			}
		}
	}

	if (type === START_TAG
	 && !usesContent
	 && bbcodeConfig.autoClose)
	{
		var endTag = '[/' + bbcodeName + suffix + ']';

		/**
		* Make sure that the start tag isn't immediately followed by an endtag
		*/
		if (text.substr(1 + rpos, endTag.length).toUpperCase() !== endTag)
		{
			type = SELF_CLOSING_TAG;
		}
	}

	tags.push({
		name   : tagName,
		pos    : lpos,
		len    : rpos + 1 - lpos,
		type   : type,
		suffix : suffix,
		attrs  : attrs
	});
});

return tags;<|endoftext|>


<commit_before>
import sagaHelper from "redux-saga-testing";
import { takeLatest } from "redux-saga";
import { put, select, call, cps, take } from "redux-saga/effects";

import { Meteor } from "meteor/meteor";

import { initial } from "../../reducer";
import actions from "../../actions";
import types from "../../types";

import { chargeTransaction } from "../";

describe("early return", () => {
  const it = sagaHelper(chargeTransaction({ state: "HAPPY" }));
  it("exits on wrong state", result => {
    expect(result).toBeUndefined();
  });
});

describe("successful charge without saved payment", () => {
  const it = sagaHelper(chargeTransaction({ state: "submit" }));
  const initalState = {
    give: {
      ...initial,
    },
  };

  it("reads the state from the store", result => {
    expect(result.SELECT).toBeTruthy();
    return initalState;
  });

  it("sets the loading state", ({ PUT: { action }}) => {
    expect(action).toEqual(actions.loading());
  });

  it("reads from the store again if no saved account and not a schedule", result => {
    expect(result.SELECT).toBeTruthy();
    return initalState;
  });

  it("reads from the store again if not a saved account", result => {
    expect(result.SELECT).toBeTruthy();
    return initalState;
  });

  it("waits for the url to return if not found", result => {
    expect(result).toEqual(take(types.SET_TRANSACTION_DETAILS));
    return { url: "https://example.com/TOKEN" };
  });

  it("tries to submit a transaction with the correct token", result => {
    expect(result.CALL.args[0].variables).toEqual({
      token: "TOKEN",
      name: null,
      id: undefined
    });
    return true;
  });

  it("puts a success state", result => {
    expect(result).toEqual(put(actions.setState("success")));
  });

  it("ends after a normal charge", result => {
    expect(result).toBeUndefined();
  });

});

describe("successful charge saved payment and schedules", () => {
  const it = sagaHelper(chargeTransaction({ state: "submit" }));
  const initalState = {
    give: {
      ...initial,
      savedAccount: { id: 1 },
      schedule: { start: "20200101" },
    },
  };

  it("reads the state from the store", result => {
    expect(result.SELECT).toBeTruthy();
    return initalState;
  });

  it("sets the loading state", ({ PUT: { action }}) => {
    expect(action).toEqual(actions.loading());
  });

  it("tries to call create order mutation", result => {
    const variables = result.CALL.args[0].variables;
    expect(variables).toEqual({
      data: JSON.stringify({
        billing: {
          "first-name": null,
          "last-name": null,
          email: null,
          address1: null,
          address2: "",
          city: null,
          state: null,
          postal: null,
        },
        "merchant-defined-field-2": null,
        plan: { payments: 0, amount: 0 },
        "start-date": "20200101",
        "merchant-defined-field-3": "20200101",
        "merchant-defined-field-1": "",
        "merchant-defined-field-4": "",
        savedAccount: 1,
        savedAccountName: undefined,
      }),
      instant: true,
      id: undefined,
    });

    return true;
  });

  it("puts a success state", result => {
    expect(result).toEqual(put(actions.setState("success")));
  });

  it("ends after a normal charge", result => {
    expect(result).toBeUndefined();
  });

});

window.ga = jest.fn();
describe("successful charge using a saved payment", () => {
  const it = sagaHelper(chargeTransaction({ state: "submit" }));
  const initalState = {
    give: {
      ...initial,
      savedAccount: { id: 1 },
    },
  };

  it("reads the state from the store", result => {
    expect(result.SELECT).toBeTruthy();
    return initalState;
  });

  it("sets the loading state", ({ PUT: { action }}) => {
    expect(action).toEqual(actions.loading());
  });

  it("reads from the store again if no saved account and not a schedule", result => {
    expect(result.SELECT).toBeTruthy();
    return initalState;
  });

  it("tries to submit person details to ensure a url", result => {
    expect(result.CALL.args[0].variables).toEqual({
      data: JSON.stringify({
        amount: 0,
        billing: {
          'first-name': null,
          'last-name': null,
          email: null,
          address1: null,
          address2: '',
          city: null,
          state: null,
          postal: null
        },
        'merchant-defined-field-2': null,
        savedAccount: 1,
        savedAccountName: undefined
      }),
      id: null,
      instant: false,
    });
    return { data: { response: { url: "http://example.com/TOKEN" }}};
  });

  // BELOW IS TESTED IN ./submitPersonDetails
  it("submits a form", result => true);
  it("sets a url", result => {});

  it("reads from the store again after submitting person details", result => {
    expect(result.SELECT).toBeTruthy();
    return { ...{ give: { ...initalState.give, ...{  url: "http://example.com/TOKEN" }} } };
  });

  it("tries to submit a transaction with the correct token", result => {
    expect(result.CALL.args[0].variables).toEqual({
      token: "TOKEN",
      id: undefined,
      name: null
    });
    return true;
  });

  it("puts a success state", result => {
    ga.mockClear();
    expect(result).toEqual(put(actions.setState("success")));
  });

  it("ends after a normal charge", result => {
    expect(window.ga.mock.calls).toMatchSnapshot();
    expect(window.ga).toHaveBeenCalledTimes(2)
    delete window.ga;
    expect(result).toBeUndefined();
  });
});

fdescribe("validating cards on saved payment creation", () => {
  const giveData = {
    personal: {},
    billing: {},
    payment: {
      type: "cc"
    },
  };
  const it = sagaHelper(chargeTransaction({ state: "submit" }));
  const initalState = {
    give: {
      ...initial,
      savedAccount: {},
      data: giveData,
    },
  };

  it("reads the state from the store", result => {
    expect(result.SELECT).toBeTruthy();
    return initalState;
  });

  it("skips over loading state", result => {});
  it("skips over setting store the first time", result => {
    return {};
  });
  it("passes give data", result => ({
    give: {
      url: "URL-Mc-URLface",
      data: giveData,
    }
  }));

  it("calls validation method", result => {
    // validate calls select() first.
    // if validate wasn't being called, the next yield in the file
    // is a graphql call, so this would fail.
    expect(result.SELECT).toBeDefined();
    return { validationError: true };
  });
});
<commit_msg>removed fdescribe<commit_after>
import sagaHelper from "redux-saga-testing";
import { takeLatest } from "redux-saga";
import { put, select, call, cps, take } from "redux-saga/effects";

import { Meteor } from "meteor/meteor";

import { initial } from "../../reducer";
import actions from "../../actions";
import types from "../../types";

import { chargeTransaction } from "../";

describe("early return", () => {
  const it = sagaHelper(chargeTransaction({ state: "HAPPY" }));
  it("exits on wrong state", result => {
    expect(result).toBeUndefined();
  });
});

describe("successful charge without saved payment", () => {
  const it = sagaHelper(chargeTransaction({ state: "submit" }));
  const initalState = {
    give: {
      ...initial,
    },
  };

  it("reads the state from the store", result => {
    expect(result.SELECT).toBeTruthy();
    return initalState;
  });

  it("sets the loading state", ({ PUT: { action }}) => {
    expect(action).toEqual(actions.loading());
  });

  it("reads from the store again if no saved account and not a schedule", result => {
    expect(result.SELECT).toBeTruthy();
    return initalState;
  });

  it("reads from the store again if not a saved account", result => {
    expect(result.SELECT).toBeTruthy();
    return initalState;
  });

  it("waits for the url to return if not found", result => {
    expect(result).toEqual(take(types.SET_TRANSACTION_DETAILS));
    return { url: "https://example.com/TOKEN" };
  });

  it("tries to submit a transaction with the correct token", result => {
    expect(result.CALL.args[0].variables).toEqual({
      token: "TOKEN",
      name: null,
      id: undefined
    });
    return true;
  });

  it("puts a success state", result => {
    expect(result).toEqual(put(actions.setState("success")));
  });

  it("ends after a normal charge", result => {
    expect(result).toBeUndefined();
  });

});

describe("successful charge saved payment and schedules", () => {
  const it = sagaHelper(chargeTransaction({ state: "submit" }));
  const initalState = {
    give: {
      ...initial,
      savedAccount: { id: 1 },
      schedule: { start: "20200101" },
    },
  };

  it("reads the state from the store", result => {
    expect(result.SELECT).toBeTruthy();
    return initalState;
  });

  it("sets the loading state", ({ PUT: { action }}) => {
    expect(action).toEqual(actions.loading());
  });

  it("tries to call create order mutation", result => {
    const variables = result.CALL.args[0].variables;
    expect(variables).toEqual({
      data: JSON.stringify({
        billing: {
          "first-name": null,
          "last-name": null,
          email: null,
          address1: null,
          address2: "",
          city: null,
          state: null,
          postal: null,
        },
        "merchant-defined-field-2": null,
        plan: { payments: 0, amount: 0 },
        "start-date": "20200101",
        "merchant-defined-field-3": "20200101",
        "merchant-defined-field-1": "",
        "merchant-defined-field-4": "",
        savedAccount: 1,
        savedAccountName: undefined,
      }),
      instant: true,
      id: undefined,
    });

    return true;
  });

  it("puts a success state", result => {
    expect(result).toEqual(put(actions.setState("success")));
  });

  it("ends after a normal charge", result => {
    expect(result).toBeUndefined();
  });

});

window.ga = jest.fn();
describe("successful charge using a saved payment", () => {
  const it = sagaHelper(chargeTransaction({ state: "submit" }));
  const initalState = {
    give: {
      ...initial,
      savedAccount: { id: 1 },
    },
  };

  it("reads the state from the store", result => {
    expect(result.SELECT).toBeTruthy();
    return initalState;
  });

  it("sets the loading state", ({ PUT: { action }}) => {
    expect(action).toEqual(actions.loading());
  });

  it("reads from the store again if no saved account and not a schedule", result => {
    expect(result.SELECT).toBeTruthy();
    return initalState;
  });

  it("tries to submit person details to ensure a url", result => {
    expect(result.CALL.args[0].variables).toEqual({
      data: JSON.stringify({
        amount: 0,
        billing: {
          'first-name': null,
          'last-name': null,
          email: null,
          address1: null,
          address2: '',
          city: null,
          state: null,
          postal: null
        },
        'merchant-defined-field-2': null,
        savedAccount: 1,
        savedAccountName: undefined
      }),
      id: null,
      instant: false,
    });
    return { data: { response: { url: "http://example.com/TOKEN" }}};
  });

  // BELOW IS TESTED IN ./submitPersonDetails
  it("submits a form", result => true);
  it("sets a url", result => {});

  it("reads from the store again after submitting person details", result => {
    expect(result.SELECT).toBeTruthy();
    return { ...{ give: { ...initalState.give, ...{  url: "http://example.com/TOKEN" }} } };
  });

  it("tries to submit a transaction with the correct token", result => {
    expect(result.CALL.args[0].variables).toEqual({
      token: "TOKEN",
      id: undefined,
      name: null
    });
    return true;
  });

  it("puts a success state", result => {
    ga.mockClear();
    expect(result).toEqual(put(actions.setState("success")));
  });

  it("ends after a normal charge", result => {
    expect(window.ga.mock.calls).toMatchSnapshot();
    expect(window.ga).toHaveBeenCalledTimes(2)
    delete window.ga;
    expect(result).toBeUndefined();
  });
});

describe("validating cards on saved payment creation", () => {
  const giveData = {
    personal: {},
    billing: {},
    payment: {
      type: "cc"
    },
  };
  const it = sagaHelper(chargeTransaction({ state: "submit" }));
  const initalState = {
    give: {
      ...initial,
      savedAccount: {},
      data: giveData,
    },
  };

  it("reads the state from the store", result => {
    expect(result.SELECT).toBeTruthy();
    return initalState;
  });

  it("skips over loading state", result => {});
  it("skips over setting store the first time", result => {
    return {};
  });
  it("passes give data", result => ({
    give: {
      url: "URL-Mc-URLface",
      data: giveData,
    }
  }));

  it("calls validation method", result => {
    // validate calls select() first.
    // if validate wasn't being called, the next yield in the file
    // is a graphql call, so this would fail.
    expect(result.SELECT).toBeDefined();
    return { validationError: true };
  });
});
<|endoftext|>


<commit_before>import { Template } from 'meteor/templating';
import { TAPi18n } from 'meteor/tap:i18n';

import { wei2eth, removeDecimal, getCoin } from '/imports/api/blockchain/modules/web3Util';
import { timeCompressed } from '/imports/ui/modules/chronos';
import { token } from '/lib/token';
import { Contracts } from '/imports/api/contracts/Contracts';

import '/imports/ui/templates/components/decision/balance/balance.html';

const numeral = require('numeral');

/**
* @summary gets width in percentage according to placed tokens
* @param {number} balance total balance
* @param {number} placed staked tokens
* @returns {number}
*/
const _getWidth = (balance, placed) => {
  if (balance === 0) { return 0; }
  return parseInt((placed * 100) / balance, 10);
};

/**
* @summary shows balance in currency not decimals
* @param {object} value value to be changed
* @param {string} token currency being used
* @returns {number}
*/
const _currencyValue = (value, tokenCode) => {
  switch (tokenCode) {
    case 'WEI':
      return wei2eth(value.toString());
    // case 'VOTE':
    //   return adjustDecimal(value);
    default:
      return value;
  }
};

/**
* @summary format currency display according to crypto rules
* @param {string} value value to be changed
* @param {string} tokenCode currency being used
* @returns {string} formatted number
*/
const _formatCryptoValue = (value, tokenCode) => {
  let tokenFinal;
  if (!tokenCode) { tokenFinal = 'ETH'; } else { tokenFinal = tokenCode; }
  return numeral(_currencyValue(value, tokenFinal)).format(getCoin(tokenFinal).format);
};

/**
* @summary shows percentag of staked Tokens
* @param {object} coin template data
* @returns {number}
*/
const _getPercentage = (coin) => {
  return _getWidth(coin.balance, coin.placed);
};

Template.balance.onCreated(function () {
  Template.instance().coin = getCoin(Template.currentData().token);
  Template.instance().percentage = _getPercentage(Template.currentData());
});

Template.balance.helpers({
  balanceStyle() {
    let style = '';
    const coin = Template.instance().coin;
    if (coin.color) {
      style = `border-color: ${coin.color}; `;
      if (this.isRevoke) {
        style += 'color: #ff2752 ';
      } else {
        style += `color: ${coin.color} `;
      }
    }
    return style;
  },
  tokenStyle() {
    let style = '';
    if (this.isTransaction) {
      style += 'token-ledger';
    }
    if (this.isButton) {
      style += ' token-button';
    }
    return style;
  },
  tickerStyle() {
    const coin = Template.instance().coin;
    if (coin.color) {
      return `background-color: ${coin.color}; border-color: ${coin.color};`;
    }
    return '';
  },
  hasDate() {
    return this.date;
  },
  sinceDate() {
    return `${timeCompressed(this.date)}`;
  },
  barStyle() {
    const coin = Template.instance().coin;
    return `background-color: ${coin.color}; width: ${Template.instance().percentage}%`;
  },
  unanimous() {
    if (Template.instance().percentage === 100) {
      return 'unanimous';
    }
    return '';
  },
  ticker() {
    let label = Template.instance().coin.code;
    if (this.rules && this.rules.quadraticVoting) {
      label = `${TAPi18n.__('ticker-rule-quadratic')} ${label}`;
    }
    if (this.rules && this.rules.balanceVoting) {
      label = `${label} ${TAPi18n.__('ticker-rule-balance')}`;
    }
    return label;
  },
  available() {
    return _formatCryptoValue(this.available, this.token);
  },
  percentage() {
    return `${_getPercentage(this)}%`;
  },
  balance() {
    const instance = Template.instance();
    if (this.blockchain && this.isButton) {
      if (this.contract._id) {
        const contract = Contracts.findOne({ _id: this.contract._id });
        if (contract && contract.blockchain) {
          this.blockchain = contract.blockchain;
        }
      }
      let score;
      if (this.blockchain.score) {
        score = this.blockchain.score.finalConfirmed;
      } else {
        score = 0;
      }
      const confirmed = _currencyValue(score, this.token);
      return `${numeral(confirmed).format(instance.coin.format)}`;
    }
    if (this.isCrypto && this.value) {
      const coinData = getCoin(instance.coin.code);
      return _formatCryptoValue(removeDecimal(this.value, coinData.decimals).toNumber(), instance.coin.code);
    }
    if (this.token === 'WEB VOTE' && !this.blockchain) {
      const balance = _currencyValue(this.available, this.token);
      return numeral(balance).format(Template.instance().coin.format);
    }
    const balance = _currencyValue(this.balance, this.token);
    return numeral(balance).format(Template.instance().coin.format);
  },
  hasPending() {
    if (this.blockchain && this.blockchain.score) {
      if (this.contract._id) {
        const contract = Contracts.findOne({ _id: this.contract._id });
        if (contract && contract.blockchain) {
          this.blockchain = contract.blockchain;
        }
      }
      return (this.blockchain.score.finalPending);
    }
    return false;
  },
  pending() {
    if (this.blockchain && this.blockchain.score) {
      if (this.contract._id) {
        const contract = Contracts.findOne({ _id: this.contract._id });
        if (contract && contract.blockchain) {
          this.blockchain = contract.blockchain;
        }
      }
      const instance = Template.instance();
      const pending = _currencyValue(this.blockchain.score.finalPending, this.token);
      return `${numeral(pending).format(instance.coin.format)} ${TAPi18n.__('pending')}`;
    }
    return '';
  },
});

export const formatCryptoValue = _formatCryptoValue;
<commit_msg>web vote balance on ballot<commit_after>import { Template } from 'meteor/templating';
import { TAPi18n } from 'meteor/tap:i18n';

import { wei2eth, removeDecimal, getCoin } from '/imports/api/blockchain/modules/web3Util';
import { timeCompressed } from '/imports/ui/modules/chronos';
import { token } from '/lib/token';
import { Contracts } from '/imports/api/contracts/Contracts';

import '/imports/ui/templates/components/decision/balance/balance.html';

const numeral = require('numeral');

/**
* @summary gets width in percentage according to placed tokens
* @param {number} balance total balance
* @param {number} placed staked tokens
* @returns {number}
*/
const _getWidth = (balance, placed) => {
  if (balance === 0) { return 0; }
  return parseInt((placed * 100) / balance, 10);
};

/**
* @summary shows balance in currency not decimals
* @param {object} value value to be changed
* @param {string} token currency being used
* @returns {number}
*/
const _currencyValue = (value, tokenCode) => {
  switch (tokenCode) {
    case 'WEI':
      return wei2eth(value.toString());
    // case 'VOTE':
    //   return adjustDecimal(value);
    default:
      return value;
  }
};

/**
* @summary format currency display according to crypto rules
* @param {string} value value to be changed
* @param {string} tokenCode currency being used
* @returns {string} formatted number
*/
const _formatCryptoValue = (value, tokenCode) => {
  let tokenFinal;
  if (!tokenCode) { tokenFinal = 'ETH'; } else { tokenFinal = tokenCode; }
  return numeral(_currencyValue(value, tokenFinal)).format(getCoin(tokenFinal).format);
};

/**
* @summary shows percentag of staked Tokens
* @param {object} coin template data
* @returns {number}
*/
const _getPercentage = (coin) => {
  return _getWidth(coin.balance, coin.placed);
};

Template.balance.onCreated(function () {
  Template.instance().coin = getCoin(Template.currentData().token);
  Template.instance().percentage = _getPercentage(Template.currentData());
});

Template.balance.helpers({
  balanceStyle() {
    let style = '';
    const coin = Template.instance().coin;
    if (coin.color) {
      style = `border-color: ${coin.color}; `;
      if (this.isRevoke) {
        style += 'color: #ff2752 ';
      } else {
        style += `color: ${coin.color} `;
      }
    }
    return style;
  },
  tokenStyle() {
    let style = '';
    if (this.isTransaction) {
      style += 'token-ledger';
    }
    if (this.isButton) {
      style += ' token-button';
    }
    return style;
  },
  tickerStyle() {
    const coin = Template.instance().coin;
    if (coin.color) {
      return `background-color: ${coin.color}; border-color: ${coin.color};`;
    }
    return '';
  },
  hasDate() {
    return this.date;
  },
  sinceDate() {
    return `${timeCompressed(this.date)}`;
  },
  barStyle() {
    const coin = Template.instance().coin;
    return `background-color: ${coin.color}; width: ${Template.instance().percentage}%`;
  },
  unanimous() {
    if (Template.instance().percentage === 100) {
      return 'unanimous';
    }
    return '';
  },
  ticker() {
    let label = Template.instance().coin.code;
    if (this.rules && this.rules.quadraticVoting) {
      label = `${TAPi18n.__('ticker-rule-quadratic')} ${label}`;
    }
    if (this.rules && this.rules.balanceVoting) {
      label = `${label} ${TAPi18n.__('ticker-rule-balance')}`;
    }
    return label;
  },
  available() {
    return _formatCryptoValue(this.available, this.token);
  },
  percentage() {
    return `${_getPercentage(this)}%`;
  },
  balance() {
    const instance = Template.instance();
    if (this.token === 'WEB VOTE' && this.isButton) {
      const balance = _currencyValue(this.contract.wallet.balance, this.token);
      return numeral(balance).format(Template.instance().coin.format);
    }
    if (this.blockchain && this.isButton) {
      if (this.contract._id) {
        const contract = Contracts.findOne({ _id: this.contract._id });
        if (contract && contract.blockchain) {
          this.blockchain = contract.blockchain;
        }
      }
      let score;
      if (this.blockchain.score) {
        score = this.blockchain.score.finalConfirmed;
      } else {
        score = 0;
      }
      const confirmed = _currencyValue(score, this.token);
      return `${numeral(confirmed).format(instance.coin.format)}`;
    }
    if (this.isCrypto && this.value) {
      const coinData = getCoin(instance.coin.code);
      return _formatCryptoValue(removeDecimal(this.value, coinData.decimals).toNumber(), instance.coin.code);
    }
    if (this.token === 'WEB VOTE' && !this.blockchain) {
      const balance = _currencyValue(this.available, this.token);
      return numeral(balance).format(Template.instance().coin.format);
    }
    const balance = _currencyValue(this.balance, this.token);
    return numeral(balance).format(Template.instance().coin.format);
  },
  hasPending() {
    if (this.blockchain && this.blockchain.score) {
      if (this.contract._id) {
        const contract = Contracts.findOne({ _id: this.contract._id });
        if (contract && contract.blockchain) {
          this.blockchain = contract.blockchain;
        }
      }
      return (this.blockchain.score.finalPending);
    }
    return false;
  },
  pending() {
    if (this.blockchain && this.blockchain.score) {
      if (this.contract._id) {
        const contract = Contracts.findOne({ _id: this.contract._id });
        if (contract && contract.blockchain) {
          this.blockchain = contract.blockchain;
        }
      }
      const instance = Template.instance();
      const pending = _currencyValue(this.blockchain.score.finalPending, this.token);
      return `${numeral(pending).format(instance.coin.format)} ${TAPi18n.__('pending')}`;
    }
    return '';
  },
});

export const formatCryptoValue = _formatCryptoValue;
<|endoftext|>


<commit_before>'use strict';

angular.module('core').controller('promoController', ['$scope', 'Authentication', 'promoService',
	function($scope, Authentication, promoService) {
		// This provides Authentication context.
		$scope.authentication = Authentication;

	// Some example string - remove in prod
        $scope.helloText = 'Promo form Test';
        $scope.testuser = $scope.authentication.user.displayName;

    	$scope.promos = promoService.query();
		$scope.newPromo = '';

	$scope.post = function() {
	  promoService.save({
	  	  created_by: $scope.authentication.user._id
	  	, created_by_name: $scope.authentication.user.displayName
	  	, newPromo.Account: $scope.Account
	  	, newPromo.Deal_Type: $scope.Deal_Type
	  	, newPromo.Deal_ID: $scope.Deal_ID

	  	}, function(){
	    $scope.promos = promoService.query();
	    $scope.newPromo = '';
	  });
	};

	$scope.delete = function(promo)	{
		promoService.delete({id: promo._id});
		$scope.promo = promoService.query();
	};

	}
]);
<commit_msg>Update promo.client.controller.js<commit_after>'use strict';

angular.module('core').controller('promoController', ['$scope', 'Authentication', 'promoService',
	function($scope, Authentication, promoService) {
		// This provides Authentication context.
		$scope.authentication = Authentication;

	// Some example string - remove in prod
        $scope.helloText = 'Promo form Test';
        $scope.testuser = $scope.authentication.user.displayName;

    	$scope.promos = promoService.query();
		$scope.newPromo = {};

	$scope.post = function() {
	  promoService.save({
	  	  created_by: $scope.authentication.user._id
	  	, created_by_name: $scope.authentication.user.displayName
	  	, Account: $scope.Account
	  	, Deal_Type: $scope.Deal_Type
	  	, Deal_ID: $scope.Deal_ID

	  	}, function(){
	    $scope.promos = promoService.query();
	    $scope.newPromo = {};
	  });
	};

	$scope.delete = function(promo)	{
		promoService.delete({id: promo._id});
		$scope.promo = promoService.query();
	};

	}
]);
<|endoftext|>


<commit_before>// @flow

const {cyan, green} = require('chalk')
const path = require('path')
const trimDollar = require('../../helpers/trim-dollar')

module.exports = function (args: {configuration: Configuration, formatter: Formatter, searcher: Searcher}, done: DoneFunction) {
  args.formatter.start('verifying NPM installation instructions')

  const installText = trimDollar(args.searcher.nodeContent({types: ['fence', 'code']}, ({nodes}) => {
    if (nodes.length === 0) return 'missing code block'
    if (nodes.length > 1) return 'found multiple code blocks'
  }))

  const pkg = require(path.join(process.cwd(), 'package.json'))
  args.formatter.start(`verifying NPM installs ${cyan(pkg.name)}`)

  if (missesPackageName(installText, pkg.name)) {
    args.formatter.error(`could not find ${cyan(pkg.name)} in installation instructions`)
    return done(new Error('1'))
  }
  args.formatter.success(`installs ${green(pkg.name)}`)
  done()
}

function missesPackageName (installText: string, packageName: string): boolean {
  // Note: cannot use minimist here
  //       because it is too stupid to understand
  //       that NPM uses '-g' by itself, and not as a switch for the argument after it
  return installText.split(' ')
                    .map((word) => word.trim())
                    .filter((word) => word === packageName)
                    .length === 0
}
<commit_msg>Make verify-npm-install action synchronous (#149)<commit_after>// @flow

const {cyan, green} = require('chalk')
const path = require('path')
const trimDollar = require('../../helpers/trim-dollar')

module.exports = function (args: {configuration: Configuration, formatter: Formatter, searcher: Searcher}) {
  args.formatter.start('verifying NPM installation instructions')

  const installText = trimDollar(args.searcher.nodeContent({types: ['fence', 'code']}, ({nodes}) => {
    if (nodes.length === 0) return 'missing code block'
    if (nodes.length > 1) return 'found multiple code blocks'
  }))

  const pkg = require(path.join(process.cwd(), 'package.json'))
  args.formatter.start(`verifying NPM installs ${cyan(pkg.name)}`)

  if (missesPackageName(installText, pkg.name)) {
    args.formatter.error(`could not find ${cyan(pkg.name)} in installation instructions`)
    throw new Error('1')
  }
  args.formatter.success(`installs ${green(pkg.name)}`)
}

function missesPackageName (installText: string, packageName: string): boolean {
  // Note: cannot use minimist here
  //       because it is too stupid to understand
  //       that NPM uses '-g' by itself, and not as a switch for the argument after it
  return installText.split(' ')
                    .map((word) => word.trim())
                    .filter((word) => word === packageName)
                    .length === 0
}
<|endoftext|>


<commit_before>/*jslint indent: 2, nomen: true, maxlen: 100, vars: true, white: true, plusplus: true*/
/*global $, window, _*/
(function() {
  "use strict";

  var disableVersionCheck = function() {
    $.ajax({
      type: "POST",
      url: "/_admin/aardvark/disableVersionCheck"
    });
  };
  var isVersionCheckEnabled = function(cb) {
    $.ajax({
      type: "GET",
      url: "/_admin/aardvark/shouldCheckVersion",
      success: function(data) {
        if (data === true) {
          cb();
        }
      }
    });
  };

  var showInterface = function(currentVersion, json) {
    var buttons = [];
    buttons.push(window.modalView.createNotificationButton("Don't ask again", function() {
      disableVersionCheck();
      window.modalView.hide();
    }));
    buttons.push(window.modalView.createSuccessButton("Download Page", function() {
      window.open('https://www.arangodb.org/download','_blank');
      window.modalView.hide();
    }));
    var infos = [];
    var cEntry = window.modalView.createReadOnlyEntry.bind(window.modalView);
    infos.push(cEntry("current", "Current", currentVersion.toString()));
    if (json.major) {
      infos.push(cEntry("major", "Major", json.major.version));
    }
    if (json.minor) {
      infos.push(cEntry("minor", "Minor", json.minor.version));
    }
    if (json.bugfix) {
      infos.push(cEntry("bugfix", "Bugfix", json.bugfix.version));
    }
    window.modalView.show(
      "modalTable.ejs", "New Version Available", buttons, infos
    );
  };

  window.checkVersion = function() {
    // this checks for version updates
    $.ajax({
      type: "GET",
      cache: false,
      url: "/_api/version",
      contentType: "application/json",
      processData: false,
      async: true,
      success: function(data) {
        var currentVersion =
          window.versionHelper.fromString(data.version);
        currentVersion.major = 1;
        currentVersion.minor = 4;
        currentVersion.bugfix = 1;
        window.parseVersions = function (json) {
          if (_.isEmpty(json)) {
            //No new version.
            return;
          }
          isVersionCheckEnabled(showInterface.bind(window, currentVersion, json));
        };
        $.ajax({
          type: "GET",
          async: true,
          crossDomain: true,
          dataType: "jsonp",
          url: "https://www.arangodb.org/repositories/versions.php" +
          "?jsonp=parseVersions&version=" + encodeURIComponent(currentVersion.toString())
        });
      }
    });
  };
}());
<commit_msg>Fixed #824. Removed debug version of arango in WebUI<commit_after>/*jslint indent: 2, nomen: true, maxlen: 100, vars: true, white: true, plusplus: true*/
/*global $, window, _*/
(function() {
  "use strict";

  var disableVersionCheck = function() {
    $.ajax({
      type: "POST",
      url: "/_admin/aardvark/disableVersionCheck"
    });
  };
  var isVersionCheckEnabled = function(cb) {
    $.ajax({
      type: "GET",
      url: "/_admin/aardvark/shouldCheckVersion",
      success: function(data) {
        if (data === true) {
          cb();
        }
      }
    });
  };

  var showInterface = function(currentVersion, json) {
    var buttons = [];
    buttons.push(window.modalView.createNotificationButton("Don't ask again", function() {
      disableVersionCheck();
      window.modalView.hide();
    }));
    buttons.push(window.modalView.createSuccessButton("Download Page", function() {
      window.open('https://www.arangodb.org/download','_blank');
      window.modalView.hide();
    }));
    var infos = [];
    var cEntry = window.modalView.createReadOnlyEntry.bind(window.modalView);
    infos.push(cEntry("current", "Current", currentVersion.toString()));
    if (json.major) {
      infos.push(cEntry("major", "Major", json.major.version));
    }
    if (json.minor) {
      infos.push(cEntry("minor", "Minor", json.minor.version));
    }
    if (json.bugfix) {
      infos.push(cEntry("bugfix", "Bugfix", json.bugfix.version));
    }
    window.modalView.show(
      "modalTable.ejs", "New Version Available", buttons, infos
    );
  };

  window.checkVersion = function() {
    // this checks for version updates
    $.ajax({
      type: "GET",
      cache: false,
      url: "/_api/version",
      contentType: "application/json",
      processData: false,
      async: true,
      success: function(data) {
        var currentVersion =
          window.versionHelper.fromString(data.version);
        window.parseVersions = function (json) {
          if (_.isEmpty(json)) {
            //No new version.
            return;
          }
          isVersionCheckEnabled(showInterface.bind(window, currentVersion, json));
        };
        $.ajax({
          type: "GET",
          async: true,
          crossDomain: true,
          dataType: "jsonp",
          url: "https://www.arangodb.org/repositories/versions.php" +
          "?jsonp=parseVersions&version=" + encodeURIComponent(currentVersion.toString())
        });
      }
    });
  };
}());
<|endoftext|>


<commit_before>'use strict'

var React = require('react')
var { PersonalFields, AddressFields, MembershipFields, DeletionFields } =
    require('./member_fields/specific.js')
var request = require('xhr')
var nullply = require('app/nullply')
var curry = require('curry')

var Field = require('./field.js')
var Dropdown = require('./common/dropdown.js')

function entry_maker (value, desc) {
  desc = desc || presentable_values(value)
  return { desc: desc, value: value }}

function presentable_values(value) {
  var capital_position = value.search(/[A-Z]/)
  return value[0].toUpperCase() + value.slice(1, capital_position) +
      (capital_position === -1 ? '' : ' ') + value.slice(capital_position)}

var deletion_reasons = [
  entry_maker('deletionReason'),
  [
    ['deceased'],
    ['notResponding', 'Did not respond to reminders'],
    ['duplicate'],
    ['dissatisfied', 'Expressed dissatisfaction'],
    ['mailReturn', 'Mail returned to us'],
    ['moved', 'Moved away'],
    ['notifiedTermination'],
    ['other']
  ].map(nullply(entry_maker))
]

var EditOptions = React.createClass({
  delete_or_undelete: function () {
    return this.props.status === 'deactivated' ?

          <button className='button-two button-c m-l-15 red right'
              onClick={this.props.reactivate} >Reactivate</button>

 :

          <button id='edit-member-mode'
              className='button-two m-l-15 right w-100 red'
              onClick={this.props.deleteMem}>Delete</button>
          <Dropdown
              id='deletion-reason'
              className='right'
              default={ deletion_reasons[0] } options={ deletion_reasons[1] } />

   },

  render: function () { return (

          <button id='save-member' className='button-two m-l-15 right w-100'
              onClick={this.props.save}>Save</button>
          <button id='cancel' className='button-two m-l-15 right w-100'
              onClick={this.props.cancel}>Cancel</button>
          { this.delete_or_undelete() }

  ) } })

var EditToggle = React.createClass({
  render: function () { return (
          <button id='edit-member-mode'
              className='member-info-edit-button'
              onClick={this.props.changeMode}>Edit</button> )}})

var MemberInformation = React.createClass({
  displayName: 'Member Information',
  getInitialState: function () { return {} },
  correct_buttons: function () {
    return this.props.mode === 'edit' ?
        <EditOptions save={this.props.save}
            changeMode={this.props.changeMode}
            deleteMem={this.props.deleteMember}
            status={this.props.member.activation_status}
            reactivate={this.props.reactivate}
            cancel={this.props.cancel} /> :
        <EditToggle changeMode={this.props.changeMode}/>
  },
  render: function () {
    var fields_with_props = render_with_props(this.props)
    return (

        { this.correct_buttons() }

        { [PersonalFields, AddressFields, MembershipFields]
            .map(fields_with_props) }
        { this.props.member.activation_status === 'deactivated'
            ? render_with_props(DeletionFields)
            :

 }

 )}})

var render_with_props = curry((props, Fields, i) =>
    <Fields
      key={i}
      mode={props.mode}
      member={props.member}
      errors={props.errors}
      on_composition_end={props.on_composition_end}
      onChange={props.onChange} /> )

module.exports = MemberInformation
<commit_msg>oops, a refactor too far<commit_after>'use strict'

var React = require('react')
var { PersonalFields, AddressFields, MembershipFields, DeletionFields } =
    require('./member_fields/specific.js')
var request = require('xhr')
var nullply = require('app/nullply')
var curry = require('curry')

var Field = require('./field.js')
var Dropdown = require('./common/dropdown.js')

function entry_maker (value, desc) {
  desc = desc || presentable_values(value)
  return { desc: desc, value: value }}

function presentable_values(value) {
  var capital_position = value.search(/[A-Z]/)
  return value[0].toUpperCase() + value.slice(1, capital_position) +
      (capital_position === -1 ? '' : ' ') + value.slice(capital_position)}

var deletion_reasons = [
  entry_maker('deletionReason'),
  [
    ['deceased'],
    ['notResponding', 'Did not respond to reminders'],
    ['duplicate'],
    ['dissatisfied', 'Expressed dissatisfaction'],
    ['mailReturn', 'Mail returned to us'],
    ['moved', 'Moved away'],
    ['notifiedTermination'],
    ['other']
  ].map(nullply(entry_maker))
]

var EditOptions = React.createClass({
  delete_or_undelete: function () {
    return this.props.status === 'deactivated' ?

          <button className='button-two button-c m-l-15 red right'
              onClick={this.props.reactivate} >Reactivate</button>

 :

          <button id='edit-member-mode'
              className='button-two m-l-15 right w-100 red'
              onClick={this.props.deleteMem}>Delete</button>
          <Dropdown
              id='deletion-reason'
              className='right'
              default={ deletion_reasons[0] } options={ deletion_reasons[1] } />

   },

  render: function () { return (

          <button id='save-member' className='button-two m-l-15 right w-100'
              onClick={this.props.save}>Save</button>
          <button id='cancel' className='button-two m-l-15 right w-100'
              onClick={this.props.cancel}>Cancel</button>
          { this.delete_or_undelete() }

  ) } })

var EditToggle = React.createClass({
  render: function () { return (
          <button id='edit-member-mode'
              className='member-info-edit-button'
              onClick={this.props.changeMode}>Edit</button> )}})

var MemberInformation = React.createClass({
  displayName: 'Member Information',
  getInitialState: function () { return {} },
  correct_buttons: function () {
    return this.props.mode === 'edit' ?
        <EditOptions save={this.props.save}
            changeMode={this.props.changeMode}
            deleteMem={this.props.deleteMember}
            status={this.props.member.activation_status}
            reactivate={this.props.reactivate}
            cancel={this.props.cancel} /> :
        <EditToggle changeMode={this.props.changeMode}/>
  },
  render: function () {
    var fields_with_props = render_with_props(this.props)
    return (

        { this.correct_buttons() }

        { [PersonalFields, AddressFields, MembershipFields]
            .map(fields_with_props) }
        { this.props.member.activation_status === 'deactivated'
            ? render_with_props(DeletionFields)
            :

 }

 )}})

var render_with_props = curry((props, Fields, i) =>
    <Fields
        {...props}
        key={i} /> )

module.exports = MemberInformation
<|endoftext|>


<commit_before>import VueRouter from 'vue-router';
import { mount, createLocalVue } from '@vue/test-utils';
import LearnIndex from '../../src/views/LearnIndex';
import makeStore from '../makeStore';

jest.mock('kolibri.urls');

const localVue = createLocalVue();
localVue.use(VueRouter);

const router = new VueRouter({
  routes: [
    { path: '/recommended', name: 'RECOMMENDED' },
    { path: '/topics', name: 'TOPICS_ROOT' },
    { path: '/classes', name: 'ALL_CLASSES' },
  ],
});

function makeWrapper(options) {
  return mount(LearnIndex, {
    ...options,
    stubs: {
      breadcrumbs: true,
      contentUnavailablePage: true,
      CoreBase: `

          <slot></slot>
          <slot name="sub-nav"></slot>

      `,
      topicsPage: true,
      TotalPoints: true,
    },
    localVue,
    router,
  });
}

function getElements(wrapper) {
  return {
    // hrefs need to match the routes in the mock router above
    classesLink: () => wrapper.find('[href="#/classes"]'),
    recommendedLink: () => wrapper.find('[href="#/recommended"]'),
    topicsLink: () => wrapper.find('[href="#/topics"]'),
    tabLinks: () => wrapper.findAll({ name: 'NavbarLink' }),
    CoreBase: () => wrapper.find({ name: 'CoreBase' }),
  };
}

describe('learn plugin index page', () => {
  let store;

  const setSessionUserKind = kind => {
    store.state.core.session.kind = [kind];
    store.state.core.session.user_id = 'test';
  };
  const setMemberships = memberships => {
    store.state.memberships = memberships;
  };
  const setPageName = pageName => {
    store.state.pageName = pageName;
  };
  const setCanAccessUnassignedContent = canAccess => {
    store.state.core.session.can_access_unassigned_content = canAccess;
  };

  beforeEach(() => {
    store = makeStore();
  });

  it('there are no tabs if showing content unavailable page', () => {
    setPageName('CONTENT_UNAVAILABLE');
    const wrapper = makeWrapper({ store });
    const { CoreBase } = getElements(wrapper);
    expect(CoreBase().props().showSubNav).toEqual(false);
  });

  describe('when allowed to access unassigned content', () => {
    beforeEach(() => {
      setCanAccessUnassignedContent(true);
    });

    it('the recommended and channel links are always available to everybody', () => {
      setSessionUserKind('anonymous');
      setMemberships([]);
      const wrapper = makeWrapper({ store });
      const { tabLinks, recommendedLink, topicsLink } = getElements(wrapper);
      expect(tabLinks().length).toEqual(2);
      expect(recommendedLink().is('a')).toEqual(true);
      expect(topicsLink().is('a')).toEqual(true);
    });

    it('the classes tab is available if user is logged in and has memberships', () => {
      // should work for any user 'kind' except for 'anonymous'
      setSessionUserKind('learner');
      setMemberships([{ id: 'membership_1' }]);
      const wrapper = makeWrapper({ store });
      const { classesLink, tabLinks } = getElements(wrapper);
      expect(tabLinks().length).toEqual(3);
      expect(classesLink().is('a')).toEqual(true);
    });

    it('the classes tab is not available if user is not logged in', () => {
      // in current implementation, anonymous user implies empty memberships
      setSessionUserKind('anonymous');
      setMemberships([]);
      const wrapper = makeWrapper({ store });
      const { classesLink, tabLinks } = getElements(wrapper);
      expect(tabLinks().length).toEqual(2);
      expect(!classesLink().exists()).toEqual(true);
    });

    it('the classes tab is not available if user has no memberships/classes', () => {
      setSessionUserKind('learner');
      setMemberships([]);
      const wrapper = makeWrapper({ store });
      const { classesLink, tabLinks } = getElements(wrapper);
      expect(tabLinks().length).toEqual(2);
      expect(!classesLink().exists()).toEqual(true);
    });
  });

  describe('when not allowed to access unassigned content', () => {
    beforeEach(() => {
      setCanAccessUnassignedContent(false);
    });

    it('no tabs are available', () => {
      setSessionUserKind('anonymous');
      setMemberships([]);
      const wrapper = makeWrapper({ store });
      const { tabLinks } = getElements(wrapper);
      expect(tabLinks().length).toEqual(0);
    });

    it('only classes tab is available if signed in', () => {
      // should work for any user 'kind' except for 'anonymous'
      setSessionUserKind('learner');
      setMemberships([{ id: 'membership_1' }]);
      const wrapper = makeWrapper({ store });
      const { classesLink, tabLinks } = getElements(wrapper);
      expect(tabLinks().length).toEqual(1);
      expect(classesLink().is('a')).toEqual(true);
    });
  });
});
<commit_msg>fix test<commit_after>import VueRouter from 'vue-router';
import { mount, createLocalVue } from '@vue/test-utils';
import LearnIndex from '../../src/views/LearnIndex';
import makeStore from '../makeStore';

jest.mock('kolibri.urls');

const localVue = createLocalVue();
localVue.use(VueRouter);

const router = new VueRouter({
  routes: [
    { path: '/recommended', name: 'RECOMMENDED' },
    { path: '/topics', name: 'TOPICS_ROOT' },
    { path: '/classes', name: 'ALL_CLASSES' },
  ],
});

function makeWrapper(options) {
  return mount(LearnIndex, {
    ...options,
    stubs: {
      breadcrumbs: true,
      contentUnavailablePage: true,
      CoreBase: `

          <slot></slot>
          <slot name="sub-nav"></slot>

      `,
      topicsPage: true,
      TotalPoints: true,
    },
    localVue,
    router,
  });
}

function getElements(wrapper) {
  return {
    // hrefs need to match the routes in the mock router above
    classesLink: () => wrapper.find('[href="#/classes"]'),
    recommendedLink: () => wrapper.find('[href="#/recommended"]'),
    topicsLink: () => wrapper.find('[href="#/topics"]'),
    tabLinks: () => wrapper.findAll({ name: 'NavbarLink' }),
    CoreBase: () => wrapper.find({ name: 'CoreBase' }),
  };
}

describe('learn plugin index page', () => {
  let store;

  const setSessionUserKind = kind => {
    store.state.core.session.kind = [kind];
    store.state.core.session.user_id = 'test';
  };
  const setMemberships = memberships => {
    store.state.memberships = memberships;
  };
  const setPageName = pageName => {
    store.state.pageName = pageName;
  };
  const setCanAccessUnassignedContent = canAccess => {
    store.state.core.session.can_access_unassigned_content = canAccess;
    store.state.core.session.allowRemoteAccess = canAccess;
  };

  beforeEach(() => {
    store = makeStore();
  });

  it('there are no tabs if showing content unavailable page', () => {
    setPageName('CONTENT_UNAVAILABLE');
    const wrapper = makeWrapper({ store });
    const { CoreBase } = getElements(wrapper);
    expect(CoreBase().props().showSubNav).toEqual(false);
  });

  describe('when allowed to access unassigned content', () => {
    beforeEach(() => {
      setCanAccessUnassignedContent(true);
    });

    it('the recommended and channel links are always available to everybody', () => {
      setSessionUserKind('anonymous');
      setMemberships([]);
      const wrapper = makeWrapper({ store });
      const { tabLinks, recommendedLink, topicsLink } = getElements(wrapper);
      expect(tabLinks().length).toEqual(2);
      expect(recommendedLink().is('a')).toEqual(true);
      expect(topicsLink().is('a')).toEqual(true);
    });

    it('the classes tab is available if user is logged in and has memberships', () => {
      // should work for any user 'kind' except for 'anonymous'
      setSessionUserKind('learner');
      setMemberships([{ id: 'membership_1' }]);
      const wrapper = makeWrapper({ store });
      const { classesLink, tabLinks } = getElements(wrapper);
      expect(tabLinks().length).toEqual(3);
      expect(classesLink().is('a')).toEqual(true);
    });

    it('the classes tab is not available if user is not logged in', () => {
      // in current implementation, anonymous user implies empty memberships
      setSessionUserKind('anonymous');
      setMemberships([]);
      const wrapper = makeWrapper({ store });
      const { classesLink, tabLinks } = getElements(wrapper);
      expect(tabLinks().length).toEqual(2);
      expect(!classesLink().exists()).toEqual(true);
    });

    it('the classes tab is not available if user has no memberships/classes', () => {
      setSessionUserKind('learner');
      setMemberships([]);
      const wrapper = makeWrapper({ store });
      const { classesLink, tabLinks } = getElements(wrapper);
      expect(tabLinks().length).toEqual(2);
      expect(!classesLink().exists()).toEqual(true);
    });
  });

  describe('when not allowed to access unassigned content', () => {
    beforeEach(() => {
      setCanAccessUnassignedContent(false);
    });

    it('no tabs are available', () => {
      setSessionUserKind('anonymous');
      setMemberships([]);
      const wrapper = makeWrapper({ store });
      const { tabLinks } = getElements(wrapper);
      expect(tabLinks().length).toEqual(0);
    });

    it('only classes tab is available if signed in', () => {
      // should work for any user 'kind' except for 'anonymous'
      setSessionUserKind('learner');
      setMemberships([{ id: 'membership_1' }]);
      const wrapper = makeWrapper({ store });
      const { classesLink, tabLinks } = getElements(wrapper);
      expect(tabLinks().length).toEqual(1);
      expect(classesLink().is('a')).toEqual(true);
    });
  });
});
<|endoftext|>