<commit_before>// Copyright (c) 2009-2014 Kris Maglione <maglione.k@gmail.com>
//
// This work is licensed for reuse under an MIT license. Details are
// given in the LICENSE.txt file included with this file.
"use strict";

try {

defineModule("main", {
    exports: ["ModuleBase"],
    require: ["config", "overlay", "services", "util"]
});

var BASE = "resource://dactyl-content/";

var global = this;

/**
 * @class ModuleBase
 * The base class for all modules.
 */
var ModuleBase = Class("ModuleBase", {
    /**
     * @property {[string]} A list of module prerequisites which
     * must be initialized before this module is loaded.
     */
    requires: [],

    toString: function () "[module " + this.constructor.className + "]"
});

var _id = 0;

var Modules = function Modules(window) {
    /**
     * @constructor Module
     *
     * Constructs a new ModuleBase class and makes arrangements for its
     * initialization. Arguments marked as optional must be either
     * entirely elided, or they must have the exact type specified.
     * Loading semantics are as follows:
     *
     *  - A module is guaranteed not to be initialized before any of its
     *    prerequisites as listed in its {@see ModuleBase#requires} member.
     *  - A module is considered initialized once it's been instantiated,
     *    its {@see Class#init} method has been called, and its
     *    instance has been installed into the top-level {@see modules}
     *    object.
     *  - Once the module has been initialized, its module-dependent
     *    initialization functions will be called as described hereafter.
     * @param {string} name The module's name as it will appear in the
     *     top-level {@see modules} object.
     * @param {ModuleBase} base The base class for this module.
     *     @optional
     * @param {Object} prototype The prototype for instances of this
     *     object. The object itself is copied and not used as a prototype
     *     directly.
     * @param {Object} classProperties The class properties for the new
     *     module constructor.
     *     @optional
     * @param {Object} moduleInit The module initialization functions
     *     for the new module. Each function is called as soon as the
     *     named module has been initialized. The constructors are
     *     guaranteed to be called in the same order that the dependent
     *     modules were initialized.
     *     @optional
     *
     * @returns {function} The constructor for the resulting module.
     */
    function Module(name, ...args) {

        var base = ModuleBase;
        if (callable(args[0]))
            base = args.shift();

        let [prototype, classProperties, moduleInit] = args;
        prototype._metaInit_ = function () {
            delete module.prototype._metaInit_;
            Class.replaceProperty(modules, module.className, this);
        };
        const module = Class(name, base, prototype, classProperties);

        module.INIT = moduleInit || {};
        module.modules = modules;
        module.prototype.INIT = module.INIT;
        module.requires = prototype.requires || [];
        Module.list.push(module);
        Module.constructors[name] = module;
        return module;
    }
    Module.list = [];
    Module.constructors = {};

    function newContext(proto, normal, name) {
        if (normal)
            return create(proto);

        sandbox = Components.utils.Sandbox(window, { sandboxPrototype: proto || modules,
                                                     sandboxName: name || ("Dactyl Sandbox " + ++_id),
                                                     wantXrays: true });

        // Hack:
        // sandbox.Object = jsmodules.Object;
        sandbox.File = global.File;
        sandbox.Math = global.Math;
        sandbox.Set  = global.Set;
        return sandbox;
    };

    const BASES = [BASE, "resource://dactyl-local-content/"];

    var jsmodules = newContext(window, false, "Dactyl `jsmodules`");
    jsmodules.NAME = "jsmodules";

    const create = bind("create", jsmodules.Object);

    const modules = update(create(jsmodules), {
        yes_i_know_i_should_not_report_errors_in_these_branches_thanks: [],

        jsmodules: jsmodules,

        get content() this.config.browser.contentWindow || window.content,

        get document() window.document,

        window: window,

        Module: Module,

        load: function load(script) {
            for (let [i, base] in Iterator(BASES)) {
                try {
                    JSMLoader.loadSubScript(base + script + ".js", modules, "UTF-8");
                    return;
                }
                catch (e) {
                    if (typeof e !== "string") {
                        util.dump("Trying: " + (base + script + ".js") + ":");
                        util.reportError(e);
                    }
                }
            }
            try {
                require(script, jsmodules);
            }
            catch (e) {
                util.dump("Loading script " + script + ":");
                util.reportError(e);
            }
        },

        newContext: newContext,

        get ownPropertyValues() array.compact(
                Object.getOwnPropertyNames(this)
                      .map(name => Object.getOwnPropertyDescriptor(this, name).value)),

        get moduleList() this.ownPropertyValues.filter(mod => (mod instanceof this.ModuleBase || mod.isLocalModule))
    });

    modules.plugins = create(modules);
    modules.modules = modules;
    return modules;
}

config.loadStyles();

overlay.overlayWindow(Object.keys(config.overlays),
                      function _overlay(window) ({
    ready: function onInit(document) {
        const modules = Modules(window);
        modules.moduleManager = this;
        this.modules = modules;
        this.jsmodules = modules.jsmodules;

        window.dactyl = { modules: modules };

        defineModule.time("load", null, function _load() {
            config.modules.global
                  .forEach(function (name) {
                      if (!isArray(name))
                          defineModule.time("load", name, require, null, name, modules.jsmodules);
                      else
                          lazyRequire(name[0], name.slice(1), modules.jsmodules);
                  });

            config.modules.window
                  .forEach(name => { defineModule.time("load", name, modules.load, modules, name); });
        }, this);
    },

    load: function onLoad(document) {
        let self = this;

        var { modules, Module } = this.modules;
        delete window.dactyl;

        this.startTime = Date.now();
        this.deferredInit = { load: {} };
        this.seen = RealSet();
        this.loaded = RealSet();
        modules.loaded = this.loaded;

        this.modules = modules;

        this.scanModules();
        this.initDependencies("init");

        modules.config.scripts.forEach(modules.load);

        this.scanModules();

        defineModule.modules.forEach(function defModule({ lazyInit, constructor: { className } }) {
            if (!lazyInit) {
                Class.replaceProperty(modules, className, modules[className]);
                this.initDependencies(className);
            }
            else
                modules.__defineGetter__(className, function () {
                    let module = modules.jsmodules[className];
                    Class.replaceProperty(modules, className, module);
                    if (module.reallyInit)
                        module.reallyInit(); // :(

                    if (!module.lazyDepends)
                        self.initDependencies(className);
                    return module;
                });
        }, this);
    },

    cleanup: function cleanup(window) {
        overlay.windows.remove(window);

        Cu.nukeSandbox(this.jsmodules);
    },

    unload: function unload(window) {
        for each (let mod in this.modules.moduleList.reverse()) {
            mod.stale = true;

            if ("destroy" in mod)
                util.trapErrors("destroy", mod);
        }
    },

    visible: function visible(window) {
        // Module.list.forEach(load);
        this.initDependencies("load");
        this.modules.times = update({}, defineModule.times);

        defineModule.loadLog.push("Loaded in " + (Date.now() - this.startTime) + "ms");

        overlay.windows.add(window);
    },

    loadModule: function loadModule(module, prereq, frame) {
        let { loaded, seen } = this;
        let { Module, modules } = this.modules;

        if (isString(module)) {
            if (!Module.constructors.hasOwnProperty(module))
                modules.load(module);
            module = Module.constructors[module];
        }

        try {
            if (loaded.has(module.className))
                return;

            if (seen.add(module.className))
                throw Error("Module dependency loop.");

            for (let dep in values(module.requires))
                this.loadModule(Module.constructors[dep], module.className);

            defineModule.loadLog.push(
                "Load" + (isString(prereq) ? " " + prereq + " dependency: " : ": ")
                    + module.className);

            if (frame && frame.filename)
                defineModule.loadLog.push("  from: " + util.fixURI(frame.filename) + ":" + frame.lineNumber);

            let obj = defineModule.time(module.className, "init", module);
            Class.replaceProperty(modules, module.className, obj);

            loaded.add(module.className);

            if (loaded.has("dactyl") && obj.signals)
                modules.dactyl.registerObservers(obj);

            if (!module.lazyDepends)
                this.initDependencies(module.className);
        }
        catch (e) {
            util.dump("Loading " + (module && module.className) + ":");
            util.reportError(e);
        }
        return modules[module.className];
    },

    deferInit: function deferInit(name, INIT, mod) {
        let { modules } = this.modules;

        let init = this.deferredInit[name] || {};
        this.deferredInit[name] = init;

        let className = mod.className || mod.constructor.className;

        if (!hasOwnProperty(init, className)) {
            init[className] = function callee() {
                function finish() {
                    this.currentDependency = className;
                    defineModule.time(className, name, INIT[name], mod,
                                      modules.dactyl, modules, window);
                }
                if (!callee.frobbed) {
                    callee.frobbed = true;
                    if (modules[name] instanceof Class)
                        modules[name].withSavedValues(["currentDependency"], finish);
                    else
                        finish.call({});
                }
            };

            INIT[name].require = function (name) { init[name](); };
        }
    },

    scanModules: function scanModules() {
        let { Module, modules } = this.modules;

        defineModule.modules.forEach((mod) => {
            let names = RealSet(Object.keys(mod.INIT));
            if ("init" in mod.INIT)
                names.add("init");

            for (let name of names)
                this.deferInit(name, mod.INIT, mod);
        });

        Module.list.forEach((mod) => {
            if (!mod.frobbed) {
                modules.__defineGetter__(mod.className, () => {
                    delete modules[mod.className];
                    return this.loadModule(mod.className, null, Components.stack.caller);
                });
                Object.keys(mod.prototype.INIT)
                      .forEach((name) => { this.deferInit(name, mod.prototype.INIT, mod); });
            }
            mod.frobbed = true;
        });
    },

    initDependencies: function initDependencies(name, parents) {
        for (let [k, v] in Iterator(this.deferredInit[name] || {}))
            if (!parents || ~parents.indexOf(k))
                util.trapErrors(v);
    }
}));

endModule();

} catch(e){ if (!e.stack) e = Error(e); dump(e.fileName+":"+e.lineNumber+": "+e+"\n" + e.stack); }

// vim: set fdm=marker sw=4 sts=4 ts=8 et ft=javascript:
<commit_msg>Err...<commit_after>// Copyright (c) 2009-2014 Kris Maglione <maglione.k@gmail.com>
//
// This work is licensed for reuse under an MIT license. Details are
// given in the LICENSE.txt file included with this file.
"use strict";

try {

defineModule("main", {
    exports: ["ModuleBase"],
    require: ["config", "overlay", "services", "util"]
});

var BASE = "resource://dactyl-content/";

var global = this;

/**
 * @class ModuleBase
 * The base class for all modules.
 */
var ModuleBase = Class("ModuleBase", {
    /**
     * @property {[string]} A list of module prerequisites which
     * must be initialized before this module is loaded.
     */
    requires: [],

    toString: function () "[module " + this.constructor.className + "]"
});

var _id = 0;

var Modules = function Modules(window) {
    /**
     * @constructor Module
     *
     * Constructs a new ModuleBase class and makes arrangements for its
     * initialization. Arguments marked as optional must be either
     * entirely elided, or they must have the exact type specified.
     * Loading semantics are as follows:
     *
     *  - A module is guaranteed not to be initialized before any of its
     *    prerequisites as listed in its {@see ModuleBase#requires} member.
     *  - A module is considered initialized once it's been instantiated,
     *    its {@see Class#init} method has been called, and its
     *    instance has been installed into the top-level {@see modules}
     *    object.
     *  - Once the module has been initialized, its module-dependent
     *    initialization functions will be called as described hereafter.
     * @param {string} name The module's name as it will appear in the
     *     top-level {@see modules} object.
     * @param {ModuleBase} base The base class for this module.
     *     @optional
     * @param {Object} prototype The prototype for instances of this
     *     object. The object itself is copied and not used as a prototype
     *     directly.
     * @param {Object} classProperties The class properties for the new
     *     module constructor.
     *     @optional
     * @param {Object} moduleInit The module initialization functions
     *     for the new module. Each function is called as soon as the
     *     named module has been initialized. The constructors are
     *     guaranteed to be called in the same order that the dependent
     *     modules were initialized.
     *     @optional
     *
     * @returns {function} The constructor for the resulting module.
     */
    function Module(name, ...args) {

        var base = ModuleBase;
        if (callable(args[0]))
            base = args.shift();

        let [prototype, classProperties, moduleInit] = args;
        prototype._metaInit_ = function () {
            delete module.prototype._metaInit_;
            Class.replaceProperty(modules, module.className, this);
        };
        const module = Class(name, base, prototype, classProperties);

        module.INIT = moduleInit || {};
        module.modules = modules;
        module.prototype.INIT = module.INIT;
        module.requires = prototype.requires || [];
        Module.list.push(module);
        Module.constructors[name] = module;
        return module;
    }
    Module.list = [];
    Module.constructors = {};

    function newContext(proto, normal, name) {
        if (normal)
            return create(proto);

        sandbox = Components.utils.Sandbox(window, { sandboxPrototype: proto || modules,
                                                     sandboxName: name || ("Dactyl Sandbox " + ++_id),
                                                     wantXrays: true });

        // Hack:
        // sandbox.Object = jsmodules.Object;
        sandbox.File = global.File;
        sandbox.Math = global.Math;
        sandbox.Set  = global.Set;
        return sandbox;
    };

    const BASES = [BASE, "resource://dactyl-local-content/"];

    var jsmodules = newContext(window, false, "Dactyl `jsmodules`");
    jsmodules.NAME = "jsmodules";

    const create = bind("create", jsmodules.Object);

    const modules = update(create(jsmodules), {
        yes_i_know_i_should_not_report_errors_in_these_branches_thanks: [],

        jsmodules: jsmodules,

        get content() this.config.browser.contentWindow || window.content,

        get document() window.document,

        window: window,

        Module: Module,

        load: function load(script) {
            for (let [i, base] in Iterator(BASES)) {
                try {
                    JSMLoader.loadSubScript(base + script + ".js", modules, "UTF-8");
                    return;
                }
                catch (e) {
                    if (typeof e !== "string") {
                        util.dump("Trying: " + (base + script + ".js") + ":");
                        util.reportError(e);
                    }
                }
            }
            try {
                require(script, jsmodules);
            }
            catch (e) {
                util.dump("Loading script " + script + ":");
                util.reportError(e);
            }
        },

        newContext: newContext,

        get ownPropertyValues() array.compact(
                Object.getOwnPropertyNames(this)
                      .map(name => Object.getOwnPropertyDescriptor(this, name).value)),

        get moduleList() this.ownPropertyValues.filter(mod => (mod instanceof this.ModuleBase || mod.isLocalModule))
    });

    modules.plugins = create(modules);
    modules.modules = modules;
    return modules;
}

config.loadStyles();

overlay.overlayWindow(Object.keys(config.overlays),
                      function _overlay(window) ({
    ready: function onInit(document) {
        const modules = Modules(window);
        modules.moduleManager = this;
        this.modules = modules;
        this.jsmodules = modules.jsmodules;

        window.dactyl = { modules: modules };

        defineModule.time("load", null, function _load() {
            config.modules.global
                  .forEach(function (name) {
                      if (!isArray(name))
                          defineModule.time("load", name, require, null, name, modules.jsmodules);
                      else
                          lazyRequire(name[0], name.slice(1), modules.jsmodules);
                  });

            config.modules.window
                  .forEach(name => { defineModule.time("load", name, modules.load, modules, name); });
        }, this);
    },

    load: function onLoad(document) {
        let self = this;

        var { modules, Module } = this.modules;
        delete window.dactyl;

        this.startTime = Date.now();
        this.deferredInit = { load: {} };
        this.seen = RealSet();
        this.loaded = RealSet();
        modules.loaded = this.loaded;

        this.modules = modules;

        this.scanModules();
        this.initDependencies("init");

        modules.config.scripts.forEach(modules.load);

        this.scanModules();

        defineModule.modules.forEach(function defModule({ lazyInit, constructor: { className } }) {
            if (!lazyInit) {
                Class.replaceProperty(modules, className, modules[className]);
                this.initDependencies(className);
            }
            else
                modules.__defineGetter__(className, function () {
                    let module = modules.jsmodules[className];
                    Class.replaceProperty(modules, className, module);
                    if (module.reallyInit)
                        module.reallyInit(); // :(

                    if (!module.lazyDepends)
                        self.initDependencies(className);
                    return module;
                });
        }, this);
    },

    cleanup: function cleanup(window) {
        overlay.windows.delete(window);

        Cu.nukeSandbox(this.jsmodules);
    },

    unload: function unload(window) {
        for each (let mod in this.modules.moduleList.reverse()) {
            mod.stale = true;

            if ("destroy" in mod)
                util.trapErrors("destroy", mod);
        }
    },

    visible: function visible(window) {
        // Module.list.forEach(load);
        this.initDependencies("load");
        this.modules.times = update({}, defineModule.times);

        defineModule.loadLog.push("Loaded in " + (Date.now() - this.startTime) + "ms");

        overlay.windows.add(window);
    },

    loadModule: function loadModule(module, prereq, frame) {
        let { loaded, seen } = this;
        let { Module, modules } = this.modules;

        if (isString(module)) {
            if (!Module.constructors.hasOwnProperty(module))
                modules.load(module);
            module = Module.constructors[module];
        }

        try {
            if (loaded.has(module.className))
                return;

            if (seen.add(module.className))
                throw Error("Module dependency loop.");

            for (let dep in values(module.requires))
                this.loadModule(Module.constructors[dep], module.className);

            defineModule.loadLog.push(
                "Load" + (isString(prereq) ? " " + prereq + " dependency: " : ": ")
                    + module.className);

            if (frame && frame.filename)
                defineModule.loadLog.push("  from: " + util.fixURI(frame.filename) + ":" + frame.lineNumber);

            let obj = defineModule.time(module.className, "init", module);
            Class.replaceProperty(modules, module.className, obj);

            loaded.add(module.className);

            if (loaded.has("dactyl") && obj.signals)
                modules.dactyl.registerObservers(obj);

            if (!module.lazyDepends)
                this.initDependencies(module.className);
        }
        catch (e) {
            util.dump("Loading " + (module && module.className) + ":");
            util.reportError(e);
        }
        return modules[module.className];
    },

    deferInit: function deferInit(name, INIT, mod) {
        let { modules } = this.modules;

        let init = this.deferredInit[name] || {};
        this.deferredInit[name] = init;

        let className = mod.className || mod.constructor.className;

        if (!hasOwnProperty(init, className)) {
            init[className] = function callee() {
                function finish() {
                    this.currentDependency = className;
                    defineModule.time(className, name, INIT[name], mod,
                                      modules.dactyl, modules, window);
                }
                if (!callee.frobbed) {
                    callee.frobbed = true;
                    if (modules[name] instanceof Class)
                        modules[name].withSavedValues(["currentDependency"], finish);
                    else
                        finish.call({});
                }
            };

            INIT[name].require = function (name) { init[name](); };
        }
    },

    scanModules: function scanModules() {
        let { Module, modules } = this.modules;

        defineModule.modules.forEach((mod) => {
            let names = RealSet(Object.keys(mod.INIT));
            if ("init" in mod.INIT)
                names.add("init");

            for (let name of names)
                this.deferInit(name, mod.INIT, mod);
        });

        Module.list.forEach((mod) => {
            if (!mod.frobbed) {
                modules.__defineGetter__(mod.className, () => {
                    delete modules[mod.className];
                    return this.loadModule(mod.className, null, Components.stack.caller);
                });
                Object.keys(mod.prototype.INIT)
                      .forEach((name) => { this.deferInit(name, mod.prototype.INIT, mod); });
            }
            mod.frobbed = true;
        });
    },

    initDependencies: function initDependencies(name, parents) {
        for (let [k, v] in Iterator(this.deferredInit[name] || {}))
            if (!parents || ~parents.indexOf(k))
                util.trapErrors(v);
    }
}));

endModule();

} catch(e){ if (!e.stack) e = Error(e); dump(e.fileName+":"+e.lineNumber+": "+e+"\n" + e.stack); }

// vim: set fdm=marker sw=4 sts=4 ts=8 et ft=javascript:
<|endoftext|>


<commit_before>/// <reference types="cypress" />

context('Reports', () => {
    beforeEach(() => {
        cy.loginStandard();
    });

    it('Gen Newsletter Labels ', () => {

        cy.visit('LettersAndLabels.php');
        cy.contains("Letters and Mailing Labels");
        cy.contains("Newsletter labels")
        //  TODO    cy.get('.btn-default:nth-child(1)').click();

    });

    it('Gen data labels"', () => {

        cy.visit('LettersAndLabels.php');
        cy.contains("Letters and Mailing Labels");
        cy.contains("Confirm data labels")
        //   TODO     cy.get('.btn-default:nth-child(2)').click();

    });

});
<commit_msg>skipping dashboard page<commit_after>/// <reference types="cypress" />

context('Standard Reports', () => {

    it('Gen Newsletter Labels ', () => {

        cy.loginStandard('LettersAndLabels.php');
        cy.contains("Letters and Mailing Labels");
        cy.contains("Newsletter labels")
        //  TODO    cy.get('.btn-default:nth-child(1)').click();

    });

    it('Gen data labels', () => {

        cy.loginStandard('LettersAndLabels.php');
        cy.contains("Letters and Mailing Labels");
        cy.contains("Confirm data labels")
        //   TODO     cy.get('.btn-default:nth-child(2)').click();

    });

});
<|endoftext|>


<commit_before>import {ElementResizeDetector} from 'widget/elementResizeDetector'
import {ViewportResizeDetector} from 'widget/viewportResizeDetector'
import {Widget} from 'widget/widget'
import {animationFrameScheduler, combineLatest, distinctUntilChanged, filter, fromEvent, interval, map, mapTo, merge, of, scan, switchMap, withLatestFrom} from 'rxjs'
import {compose} from 'compose'
import Hammer from 'hammerjs'
import Portal from 'widget/portal'
import PropTypes from 'prop-types'
import React from 'react'
import _ from 'lodash'
import styles from './slider.module.css'
import withSubscriptions from 'subscription'

const clamp = (value, {min, max}) => Math.max(min, Math.min(max, value))

const lerp = (rate, speed = 1) => (value, target) => value + (target - value) * (rate * speed)

const normalizeLinear = (value, min, max) => {
    const offset = min
    return (value - offset) / (max - offset)
}

const denormalizeLinear = (value, min, max) => {
    const offset = min
    return value * (max - offset) + offset
}

const normalizeLog = (value, min, max) => {
    const offset = min - 1
    return Math.log(value - offset) / Math.log(max - offset)
}

const denormalizeLog = (value, min, max) => {
    const offset = min - 1
    return Math.exp(value * Math.log(max - offset)) + offset
}

const invertNormalized = (value, invert) =>
    invert ? 1 - value : value

const normalize = (value, min, max, scale, invert) =>
    invertNormalized(scale === 'log' ? normalizeLog(value, min, max) : normalizeLinear(value, min, max), invert)

const denormalize = (value, min, max, scale, invert) =>
    scale === 'log'
        ? denormalizeLog(invertNormalized(value, invert), min, max)
        : denormalizeLinear(invertNormalized(value, invert), min, max)

class SliderContainer extends React.Component {
    clickTarget = React.createRef()

    renderTick({position, value, label}) {
        const left = `${Math.trunc(position)}px`
        return (
            <React.Fragment key={value}>

{label}

            </React.Fragment>
        )
    }

    renderAxis() {
        const {ticks} = this.props
        return (

                {ticks.map(tick => this.renderTick(tick))}

        )
    }

    renderClickTarget() {
        return (

        )
    }

    renderDynamics() {
        const {value, width, range, decimals, ticks, snap, minValue, maxValue, invert, onChange} = this.props
        return (
            <SliderDynamics
                value={value}
                minValue={minValue}
                maxValue={maxValue}
                width={width}
                decimals={decimals}
                ticks={ticks}
                snap={snap}
                range={range}
                invert={invert}
                clickTarget={this.clickTarget}
                normalize={value => {
                    const {scale, minValue, maxValue} = this.props
                    return normalize(value, minValue, maxValue, scale, invert)
                }}
                denormalize={value => {
                    const {scale, minValue, maxValue} = this.props
                    return denormalize(value, minValue, maxValue, scale, invert)
                }}
                onChange={onChange}
            />
        )
    }

    render() {
        return (

                {this.renderAxis()}
                {this.renderClickTarget()}
                {this.renderDynamics()}

        )
    }
}

SliderContainer.propTypes = {
    decimals: PropTypes.number,
    denormalize: PropTypes.func,
    info: PropTypes.oneOfType([
        PropTypes.string,
        PropTypes.func
    ]),
    maxValue: PropTypes.number,
    minValue: PropTypes.number,
    normalize: PropTypes.func,
    snap: PropTypes.bool,
    ticks: PropTypes.oneOfType([
        PropTypes.number,
        PropTypes.array
    ]),
    value: PropTypes.any,
    width: PropTypes.number,
    onChange: PropTypes.func
}

class _SliderDynamics extends React.Component {
    state = {
        position: null,
        previewPosition: null,
        clickTargetOffset: null,
        dragging: null,
        inhibitInput: null
    }
    handle = React.createRef()

    renderLeftRange() {
        const {position} = this.state
        const {width} = this.props
        return <div className={styles.range} style={{right: `${width - position}px`}}/>
    }

    renderRightRange() {
        const {position} = this.state
        return <div className={styles.range} style={{left: `${position}px`}}/>
    }

    renderRanges() {
        const {range, invert} = this.props
        return (
            <React.Fragment>
                {((range === 'low' && !invert) || (range === 'high' && invert)) ? this.renderLeftRange() : null}
                {((range === 'high' && !invert) || (range === 'low' && invert)) ? this.renderRightRange() : null}
            </React.Fragment>
        )
    }

    renderPreview() {
        const {previewPosition} = this.state
        return previewPosition !== null ? (
            <div className={[styles.cursor, styles.preview].join(' ')} ref={this.preview}
                style={{left: `${previewPosition}px`}}/>
        ) : null
    }

    renderHandle() {
        const {position, dragging} = this.state
        return (
            <div className={[styles.cursor, styles.handle, dragging ? styles.dragging : null].join(' ')}
                ref={this.handle}
                style={{left: `${position}px`}}/>
        )
    }

    renderOverlay() {
        const {dragging} = this.state
        return dragging
            ? (
                <Portal type='global'>

                </Portal>
            ) : null
    }

    renderViewportResizer() {
        return (
            <ViewportResizeDetector onChange={() => this.setClickTargetOffset()}/>
        )
    }

    render() {
        return (
            <React.Fragment>
                {this.renderRanges()}
                {this.renderPreview()}
                {this.renderHandle()}
                {this.renderOverlay()}
                {this.renderViewportResizer()}
            </React.Fragment>
        )
    }

    componentDidMount() {
        this.initialize({
            handleElement: this.handle.current,
            clickTargetElement: this.props.clickTarget.current
        })
    }

    getRelativeEventPosition(e) {
        const {clickTargetOffset, handleWidth} = this.state
        return this.clampPosition(e.clientX - clickTargetOffset - handleWidth / 2)
    }

    initialize({handleElement, clickTargetElement}) {
        const {addSubscription} = this.props

        this.setState({
            handleWidth: handleElement.getBoundingClientRect().width
        })

        this.setHandlePositionByValue()

        const handle = new Hammer(handleElement)
        // limit handle movement to horizontal axis
        handle.get('pan').set({
            direction: Hammer.DIRECTION_HORIZONTAL,
            threshold: 1
        })

        const mouseMove$ = fromEvent(clickTargetElement, 'mousemove')
        const mouseLeave$ = fromEvent(clickTargetElement, 'mouseleave')
        const pan$ = fromEvent(handle, 'panstart panmove panend')
        const panStart$ = pan$.pipe(filter(e => e.type === 'panstart'))
        const panMove$ = pan$.pipe(filter(e => e.type === 'panmove'))
        const panEnd$ = pan$.pipe(filter(e => e.type === 'panend'))
        const animationFrame$ = interval(0, animationFrameScheduler)

        const hoverPosition$ = merge(
            mouseMove$.pipe(
                map(e => this.getRelativeEventPosition(e))
            ),
            mouseLeave$.pipe(
                mapTo(null)
            )
        )

        // target position by clicking
        const clickPosition$ = fromEvent(clickTargetElement, 'click').pipe(
            map(e => this.snapPosition(this.getRelativeEventPosition(e)))
        )

        // target position by dragging
        const dragPosition$ = panStart$.pipe(
            switchMap(() => {
                const {position} = this.state
                return merge(
                    panMove$.pipe(
                        map(event => this.clampPosition(position + event.deltaX)),
                        distinctUntilChanged()
                    ),
                    panEnd$.pipe(
                        map(() => this.snapPosition(this.state.previewPosition))
                    )
                )
            })
        )

        const handleDragging$ = merge(
            of(false),
            panStart$.pipe(mapTo(true)),
            panEnd$.pipe(mapTo(false)),
        )

        const targetPosition$ = merge(clickPosition$, dragPosition$)

        const handlePosition$ = targetPosition$.pipe(
            withLatestFrom(handleDragging$),
            switchMap(([targetPosition, dragging]) => {
                const {position} = this.state
                return animationFrame$.pipe(
                    map(() => targetPosition),
                    scan(lerp(dragging ? .30 : .15), position),
                    map(position => Math.round(position)),
                    distinctUntilChanged()
                )
            })
        )

        const handleMoving$ = combineLatest(handlePosition$, targetPosition$).pipe(
            map(([currentPosition, targetPosition]) => currentPosition !== targetPosition),
            distinctUntilChanged()
        )

        const previewPosition$ = merge(targetPosition$, hoverPosition$).pipe(
            map(position => position === null ? null : this.snapPosition(position)),
            distinctUntilChanged()
        )

        const inhibitInput$ = handleMoving$.pipe(
            withLatestFrom(handleDragging$),
            map(([dragging, moving]) => dragging || moving)
        )

        const updateInput$ = merge(clickPosition$, panEnd$)

        addSubscription(
            handlePosition$.subscribe(position =>
                this.setHandlePosition(position)
            ),
            previewPosition$.subscribe(previewPosition =>
                this.setPreviewPosition(previewPosition)
            ),
            handleDragging$.subscribe(dragging =>
                this.setDragging(dragging)
            ),
            inhibitInput$.subscribe(inhibit =>
                this.setInhibitInput(inhibit)
            ),
            updateInput$.subscribe(() =>
                this.updateInputValue()
            )
        )
    }

    componentDidUpdate(prevProps) {
        const {inhibitInput} = this.state
        // prevent input from self-interfering during animation
        if (!inhibitInput && !_.isEqual(prevProps, this.props)) {
            this.setHandlePositionByValue()
        }
    }

    toPosition(value) {
        const {normalize, width} = this.props
        return normalize(value) * width
    }

    toValue(position) {
        const {denormalize, width} = this.props
        return denormalize(position / width)
    }

    clampPosition(position) {
        const {width} = this.props
        return Math.round(
            clamp(position, {
                min: 0,
                max: width
            })
        )
    }

    snapPosition(value) {
        const {ticks, snap} = this.props
        if (snap) {
            const closest = _(ticks)
                .map(({position}) => ({position, distance: Math.abs(position - value)}))
                .sortBy('distance')
                .head()
            return closest.position
        } else {
            return value
        }
    }

    setHandlePositionByValue() {
        const {value} = this.props
        this.setHandlePosition(this.toPosition(value))
    }

    setHandlePosition(position) {
        const {position: currentPosition} = this.state
        if (position >= 0 && position !== currentPosition) {
            this.setState({position})
        }
    }

    updateInputValue() {
        const {decimals, onChange} = this.props
        const {previewPosition} = this.state
        const value = this.toValue(this.snapPosition(previewPosition))
        const factor = Math.pow(10, decimals)
        const roundedValue = Math.round(value * factor) / factor
        onChange && onChange(roundedValue)
    }

    setPreviewPosition(previewPosition) {
        this.setState({previewPosition})
    }

    setInhibitInput(inhibitInput) {
        this.setState({inhibitInput})
    }

    setDragging(dragging) {
        this.setState({dragging})
    }

    setClickTargetOffset() {
        const {clickTarget} = this.props
        const {clickTargetOffset: currentClickTargetOffset} = this.state
        const clickTargetOffset = Math.trunc(clickTarget.current.getBoundingClientRect().left)
        if (currentClickTargetOffset !== clickTargetOffset) {
            this.setState({clickTargetOffset})
        }
    }
}

const SliderDynamics = compose(
    _SliderDynamics,
    withSubscriptions()
)

SliderDynamics.propTypes = {
    denormalize: PropTypes.func.isRequired,
    maxValue: PropTypes.number.isRequired,
    minValue: PropTypes.number.isRequired,
    normalize: PropTypes.func.isRequired,
    value: PropTypes.any.isRequired,
    decimals: PropTypes.number,
    invert: PropTypes.bool,
    snap: PropTypes.bool,
    ticks: PropTypes.array,
    width: PropTypes.number,
    onChange: PropTypes.func
}

export class Slider extends React.Component {
    state = {
        width: null,
        ticks: [],
        minValue: null,
        maxValue: null
    }

    static getDerivedStateFromProps(props, state) {
        const mapTicks = ticks =>
            ticks.map((tick, index) => {
                if (_.isObject(tick)) {
                    const value = tick.value || index
                    const label = tick.label || ''
                    return {value, label}
                }
                if (_.isString(tick)) {
                    return {value: index, externalValue: tick, label: tick}
                }
                return {value: tick, externalValue: tick, label: tick}
            })

        const ticks = mapTicks(props.ticks ? props.ticks : [props.minValue, props.maxValue])
        const minValue = props.minValue || ticks.reduce((min, {value}) => Math.min(min, value), null)
        const maxValue = props.maxValue || ticks.reduce((max, {value}) => Math.max(max, value), null)
        return {
            ticks: ticks
                .filter(({value}) => value >= minValue && value <= maxValue)
                .map(tick => ({
                    ...tick,
                    position: state.width * normalize(tick.value, minValue, maxValue, props.scale, props.invert)
                })),
            minValue,
            maxValue
        }
    }

    renderInfo() {
        const {value, info, alignment} = this.props
        const {ticks} = this.state
        const tick = ticks && ticks.find(tick => tick.value === value)
        const label = (tick && tick.label) || value
        return info ? (

                {_.isFunction(info) ? info(label, value) : info}

        ) : null
    }

    renderSlider() {
        const {width} = this.state
        return (

                    <ElementResizeDetector onResize={({width}) => this.setState({width})}/>
                    {width ? this.renderContainer() : null}

        )
    }

    renderContainer() {
        const {value, scale = 'linear', decimals = 0, snap, range = 'left', invert = false, info, onChange} = this.props
        const {ticks, minValue, maxValue, width} = this.state
        return (
            <SliderContainer
                value={value}
                minValue={minValue}
                maxValue={maxValue}
                decimals={decimals}
                ticks={ticks}
                snap={snap}
                range={range}
                scale={scale}
                invert={invert}
                info={info}
                width={width}
                onChange={onChange}
            />
        )

    }

    render() {
        const {label, tooltip, tooltipPlacement, alignment, disabled} = this.props
        return (
            <Widget
                className={styles.wrapper}
                label={label}
                alignment={alignment}
                disabled={disabled}
                tooltip={tooltip}
                tooltipPlacement={tooltipPlacement}>
                {this.renderInfo()}
                {this.renderSlider()}
            </Widget>
        )
    }
}

Slider.propTypes = {
    alignment: PropTypes.oneOf(['left', 'center', 'right']),
    decimals: PropTypes.number,
    disabled: PropTypes.any,
    info: PropTypes.oneOfType([
        PropTypes.string,
        PropTypes.func
    ]),
    invert: PropTypes.any,
    label: PropTypes.string,
    maxValue: PropTypes.number,
    minValue: PropTypes.number,
    range: PropTypes.oneOf(['none', 'low', 'high']),
    scale: PropTypes.oneOf(['linear', 'log']),
    snap: PropTypes.any,
    ticks: PropTypes.oneOfType([
        // PropTypes.number,
        PropTypes.array
    ]),
    tooltip: PropTypes.string,
    tooltipPlacement: PropTypes.string,
    value: PropTypes.any,
    onChange: PropTypes.func
}
<commit_msg>Fixed Slider input inhibit behaviour.<commit_after>import {ElementResizeDetector} from 'widget/elementResizeDetector'
import {ViewportResizeDetector} from 'widget/viewportResizeDetector'
import {Widget} from 'widget/widget'
import {animationFrameScheduler, combineLatest, distinctUntilChanged, fromEvent, interval, map, mapTo, merge, of, scan, switchMap, withLatestFrom} from 'rxjs'
import {compose} from 'compose'
import Hammer from 'hammerjs'
import Portal from 'widget/portal'
import PropTypes from 'prop-types'
import React from 'react'
import _ from 'lodash'
import styles from './slider.module.css'
import withSubscriptions from 'subscription'

const clamp = (value, {min, max}) => Math.max(min, Math.min(max, value))

const lerp = (rate, speed = 1) => (value, target) => value + (target - value) * (rate * speed)

const normalizeLinear = (value, min, max) => {
    const offset = min
    return (value - offset) / (max - offset)
}

const denormalizeLinear = (value, min, max) => {
    const offset = min
    return value * (max - offset) + offset
}

const normalizeLog = (value, min, max) => {
    const offset = min - 1
    return Math.log(value - offset) / Math.log(max - offset)
}

const denormalizeLog = (value, min, max) => {
    const offset = min - 1
    return Math.exp(value * Math.log(max - offset)) + offset
}

const invertNormalized = (value, invert) =>
    invert ? 1 - value : value

const normalize = (value, min, max, scale, invert) =>
    invertNormalized(scale === 'log' ? normalizeLog(value, min, max) : normalizeLinear(value, min, max), invert)

const denormalize = (value, min, max, scale, invert) =>
    scale === 'log'
        ? denormalizeLog(invertNormalized(value, invert), min, max)
        : denormalizeLinear(invertNormalized(value, invert), min, max)

class SliderContainer extends React.Component {
    clickTarget = React.createRef()

    renderTick({position, value, label}) {
        const left = `${Math.trunc(position)}px`
        return (
            <React.Fragment key={value}>

{label}

            </React.Fragment>
        )
    }

    renderAxis() {
        const {ticks} = this.props
        return (

                {ticks.map(tick => this.renderTick(tick))}

        )
    }

    renderClickTarget() {
        return (

        )
    }

    renderDynamics() {
        const {value, width, range, decimals, ticks, snap, minValue, maxValue, invert, onChange} = this.props
        return (
            <SliderDynamics
                value={value}
                minValue={minValue}
                maxValue={maxValue}
                width={width}
                decimals={decimals}
                ticks={ticks}
                snap={snap}
                range={range}
                invert={invert}
                clickTarget={this.clickTarget}
                normalize={value => {
                    const {scale, minValue, maxValue} = this.props
                    return normalize(value, minValue, maxValue, scale, invert)
                }}
                denormalize={value => {
                    const {scale, minValue, maxValue} = this.props
                    return denormalize(value, minValue, maxValue, scale, invert)
                }}
                onChange={onChange}
            />
        )
    }

    render() {
        return (

                {this.renderAxis()}
                {this.renderClickTarget()}
                {this.renderDynamics()}

        )
    }
}

SliderContainer.propTypes = {
    decimals: PropTypes.number,
    denormalize: PropTypes.func,
    info: PropTypes.oneOfType([
        PropTypes.string,
        PropTypes.func
    ]),
    maxValue: PropTypes.number,
    minValue: PropTypes.number,
    normalize: PropTypes.func,
    snap: PropTypes.bool,
    ticks: PropTypes.oneOfType([
        PropTypes.number,
        PropTypes.array
    ]),
    value: PropTypes.any,
    width: PropTypes.number,
    onChange: PropTypes.func
}

class _SliderDynamics extends React.Component {
    state = {
        position: null,
        previewPosition: null,
        clickTargetOffset: null,
        dragging: null,
        inhibitInput: null
    }
    handle = React.createRef()

    renderLeftRange() {
        const {position} = this.state
        const {width} = this.props
        return <div className={styles.range} style={{right: `${width - position}px`}}/>
    }

    renderRightRange() {
        const {position} = this.state
        return <div className={styles.range} style={{left: `${position}px`}}/>
    }

    renderRanges() {
        const {range, invert} = this.props
        return (
            <React.Fragment>
                {((range === 'low' && !invert) || (range === 'high' && invert)) ? this.renderLeftRange() : null}
                {((range === 'high' && !invert) || (range === 'low' && invert)) ? this.renderRightRange() : null}
            </React.Fragment>
        )
    }

    renderPreview() {
        const {previewPosition} = this.state
        return previewPosition !== null ? (
            <div className={[styles.cursor, styles.preview].join(' ')} ref={this.preview}
                style={{left: `${previewPosition}px`}}/>
        ) : null
    }

    renderHandle() {
        const {position, dragging} = this.state
        return (
            <div className={[styles.cursor, styles.handle, dragging ? styles.dragging : null].join(' ')}
                ref={this.handle}
                style={{left: `${position}px`}}/>
        )
    }

    renderOverlay() {
        const {dragging} = this.state
        return dragging
            ? (
                <Portal type='global'>

                </Portal>
            ) : null
    }

    renderViewportResizer() {
        return (
            <ViewportResizeDetector onChange={() => this.setClickTargetOffset()}/>
        )
    }

    render() {
        return (
            <React.Fragment>
                {this.renderRanges()}
                {this.renderPreview()}
                {this.renderHandle()}
                {this.renderOverlay()}
                {this.renderViewportResizer()}
            </React.Fragment>
        )
    }

    componentDidMount() {
        this.initialize({
            handleElement: this.handle.current,
            clickTargetElement: this.props.clickTarget.current
        })
    }

    getRelativeEventPosition(e) {
        const {clickTargetOffset, handleWidth} = this.state
        return this.clampPosition(e.clientX - clickTargetOffset - handleWidth / 2)
    }

    initialize({handleElement, clickTargetElement}) {
        const {addSubscription} = this.props

        this.setState({
            handleWidth: handleElement.getBoundingClientRect().width
        })

        this.setHandlePositionByValue()

        const handle = new Hammer(handleElement)
        // limit handle movement to horizontal axis
        handle.get('pan').set({
            direction: Hammer.DIRECTION_HORIZONTAL,
            threshold: 1
        })

        const mouseMove$ = fromEvent(clickTargetElement, 'mousemove')
        const mouseLeave$ = fromEvent(clickTargetElement, 'mouseleave')
        const panStart$ = fromEvent(handle, 'panstart')
        const panMove$ = fromEvent(handle, 'panmove')
        const panEnd$ = fromEvent(handle, 'panend')
        const animationFrame$ = interval(0, animationFrameScheduler)

        const hoverPosition$ = merge(
            mouseMove$.pipe(
                map(e => this.getRelativeEventPosition(e))
            ),
            mouseLeave$.pipe(
                mapTo(null)
            )
        )

        // target position by clicking
        const clickPosition$ = fromEvent(clickTargetElement, 'click').pipe(
            map(e => this.snapPosition(this.getRelativeEventPosition(e)))
        )

        // target position by dragging
        const dragPosition$ = panStart$.pipe(
            switchMap(() => {
                const {position} = this.state
                return merge(
                    panMove$.pipe(
                        map(event => this.clampPosition(position + event.deltaX)),
                        distinctUntilChanged()
                    ),
                    panEnd$.pipe(
                        map(() => this.snapPosition(this.state.previewPosition))
                    )
                )
            })
        )

        const handleDragging$ = merge(
            of(false),
            panStart$.pipe(mapTo(true)),
            panEnd$.pipe(mapTo(false)),
        )

        const targetPosition$ = merge(clickPosition$, dragPosition$)

        const handlePosition$ = targetPosition$.pipe(
            withLatestFrom(handleDragging$),
            switchMap(([targetPosition, dragging]) => {
                const {position} = this.state
                return animationFrame$.pipe(
                    map(() => targetPosition),
                    scan(lerp(dragging ? .30 : .15), position),
                    map(position => Math.round(position))
                )
            }),
            distinctUntilChanged()
        )

        const handleMoving$ = handlePosition$.pipe(
            withLatestFrom(targetPosition$),
            map(([currentPosition, targetPosition]) => currentPosition !== targetPosition),
            distinctUntilChanged()
        )

        const previewPosition$ = merge(targetPosition$, hoverPosition$).pipe(
            map(position => position === null ? null : this.snapPosition(position)),
            distinctUntilChanged()
        )

        const inhibitInput$ = combineLatest([handleMoving$, handleDragging$]).pipe(
            map(([moving, dragging]) => moving || dragging),
            distinctUntilChanged()
        )

        const updateInput$ = merge(clickPosition$, panEnd$)

        addSubscription(
            handlePosition$.subscribe(position =>
                this.setHandlePosition(position)
            ),
            previewPosition$.subscribe(previewPosition =>
                this.setPreviewPosition(previewPosition)
            ),
            handleDragging$.subscribe(dragging =>
                this.setDragging(dragging)
            ),
            inhibitInput$.subscribe(inhibit =>
                this.setInhibitInput(inhibit)
            ),
            updateInput$.subscribe(() =>
                this.updateInputValue()
            )
        )
    }

    componentDidUpdate(prevProps) {
        const {inhibitInput} = this.state
        // prevent input from self-interfering during animation
        if (!inhibitInput && !_.isEqual(prevProps, this.props)) {
            this.setHandlePositionByValue()
        }
    }

    toPosition(value) {
        const {normalize, width} = this.props
        return normalize(value) * width
    }

    toValue(position) {
        const {denormalize, width} = this.props
        return denormalize(position / width)
    }

    clampPosition(position) {
        const {width} = this.props
        return Math.round(
            clamp(position, {
                min: 0,
                max: width
            })
        )
    }

    snapPosition(value) {
        const {ticks, snap} = this.props
        if (snap) {
            const closest = _(ticks)
                .map(({position}) => ({position, distance: Math.abs(position - value)}))
                .sortBy('distance')
                .head()
            return Math.round(closest.position)
        } else {
            return Math.round(value)
        }
    }

    setHandlePositionByValue() {
        const {value} = this.props
        this.setHandlePosition(this.toPosition(value))
    }

    setHandlePosition(position) {
        const {position: currentPosition} = this.state
        if (position >= 0 && position !== currentPosition) {
            this.setState({position})
        }
    }

    updateInputValue() {
        const {decimals, onChange} = this.props
        const {previewPosition} = this.state
        const value = this.toValue(this.snapPosition(previewPosition))
        const factor = Math.pow(10, decimals)
        const roundedValue = Math.round(value * factor) / factor
        onChange && onChange(roundedValue)
    }

    setPreviewPosition(previewPosition) {
        this.setState({previewPosition})
    }

    setInhibitInput(inhibitInput) {
        this.setState({inhibitInput})
    }

    setDragging(dragging) {
        this.setState({dragging})
    }

    setClickTargetOffset() {
        const {clickTarget} = this.props
        const {clickTargetOffset: currentClickTargetOffset} = this.state
        const clickTargetOffset = Math.trunc(clickTarget.current.getBoundingClientRect().left)
        if (currentClickTargetOffset !== clickTargetOffset) {
            this.setState({clickTargetOffset})
        }
    }
}

const SliderDynamics = compose(
    _SliderDynamics,
    withSubscriptions()
)

SliderDynamics.propTypes = {
    denormalize: PropTypes.func.isRequired,
    maxValue: PropTypes.number.isRequired,
    minValue: PropTypes.number.isRequired,
    normalize: PropTypes.func.isRequired,
    value: PropTypes.any.isRequired,
    decimals: PropTypes.number,
    invert: PropTypes.bool,
    snap: PropTypes.bool,
    ticks: PropTypes.array,
    width: PropTypes.number,
    onChange: PropTypes.func
}

export class Slider extends React.Component {
    state = {
        width: null,
        ticks: [],
        minValue: null,
        maxValue: null
    }

    static getDerivedStateFromProps(props, state) {
        const mapTicks = ticks =>
            ticks.map((tick, index) => {
                if (_.isObject(tick)) {
                    const value = tick.value || index
                    const label = tick.label || ''
                    return {value, label}
                }
                if (_.isString(tick)) {
                    return {value: index, externalValue: tick, label: tick}
                }
                return {value: tick, externalValue: tick, label: tick}
            })

        const ticks = mapTicks(props.ticks ? props.ticks : [props.minValue, props.maxValue])
        const minValue = props.minValue || ticks.reduce((min, {value}) => Math.min(min, value), null)
        const maxValue = props.maxValue || ticks.reduce((max, {value}) => Math.max(max, value), null)
        return {
            ticks: ticks
                .filter(({value}) => value >= minValue && value <= maxValue)
                .map(tick => ({
                    ...tick,
                    position: state.width * normalize(tick.value, minValue, maxValue, props.scale, props.invert)
                })),
            minValue,
            maxValue
        }
    }

    renderInfo() {
        const {value, info, alignment} = this.props
        const {ticks} = this.state
        const tick = ticks && ticks.find(tick => tick.value === value)
        const label = (tick && tick.label) || value
        return info ? (

                {_.isFunction(info) ? info(label, value) : info}

        ) : null
    }

    renderSlider() {
        const {width} = this.state
        return (

                    <ElementResizeDetector onResize={({width}) => this.setState({width})}/>
                    {width ? this.renderContainer() : null}

        )
    }

    renderContainer() {
        const {value, scale = 'linear', decimals = 0, snap, range = 'left', invert = false, info, onChange} = this.props
        const {ticks, minValue, maxValue, width} = this.state
        return (
            <SliderContainer
                value={value}
                minValue={minValue}
                maxValue={maxValue}
                decimals={decimals}
                ticks={ticks}
                snap={snap}
                range={range}
                scale={scale}
                invert={invert}
                info={info}
                width={width}
                onChange={onChange}
            />
        )

    }

    render() {
        const {label, tooltip, tooltipPlacement, alignment, disabled} = this.props
        return (
            <Widget
                className={styles.wrapper}
                label={label}
                alignment={alignment}
                disabled={disabled}
                tooltip={tooltip}
                tooltipPlacement={tooltipPlacement}>
                {this.renderInfo()}
                {this.renderSlider()}
            </Widget>
        )
    }
}

Slider.propTypes = {
    alignment: PropTypes.oneOf(['left', 'center', 'right']),
    decimals: PropTypes.number,
    disabled: PropTypes.any,
    info: PropTypes.oneOfType([
        PropTypes.string,
        PropTypes.func
    ]),
    invert: PropTypes.any,
    label: PropTypes.string,
    maxValue: PropTypes.number,
    minValue: PropTypes.number,
    range: PropTypes.oneOf(['none', 'low', 'high']),
    scale: PropTypes.oneOf(['linear', 'log']),
    snap: PropTypes.any,
    ticks: PropTypes.oneOfType([
        // PropTypes.number,
        PropTypes.array
    ]),
    tooltip: PropTypes.string,
    tooltipPlacement: PropTypes.string,
    value: PropTypes.any,
    onChange: PropTypes.func
}
<|endoftext|>


<commit_before>'use strict';
var _ = require('underscore');
var template = require('../../src/template/template.js');
function compileTemplates(rawTemplates) {
  var compiledTemplates = {}, partialsList = {}, rawTemplates = rawTemplates || {};
  var templateNames = Object.keys(rawTemplates);

  function parseTemplates(rawTemplates, templateNames, compiledTemplates) {
    for (var i = 0; i < templateNames.length; i++) {
      var parsed = Ractive.parse(rawTemplates[templateNames[i]], {
        stripComments: false,
        preserveWhitespace: true
      });
      compiledTemplates[templateNames[i]] = new template(parsed.t, partialsList);
    }
  }

  // Compile templates as partials
  parseTemplates(rawTemplates, templateNames, compiledTemplates);
  _.keys(rawTemplates).forEach(function(item) {
    partialsList[item] = compiledTemplates[item];
  });
  // Reparse templates with partials
  parseTemplates(rawTemplates, templateNames, compiledTemplates);
  return compiledTemplates;
}
module.exports = {compileTemplates: compileTemplates};
<commit_msg>Minor changes<commit_after>'use strict';
/*global Ractive */
var _ = require('underscore');
var template = require('../../src/template/template.js');
function compileTemplates(rawTemplates) {
  var compiledTemplates = {}, partialsList = {};
  rawTemplates = rawTemplates || {};
  var templateNames = Object.keys(rawTemplates);

  function parseTemplates(rawTemplates, templateNames, compiledTemplates) {
    for (var i = 0; i < templateNames.length; i++) {
      var parsed = Ractive.parse(rawTemplates[templateNames[i]], {
        stripComments: false,
        preserveWhitespace: true
      });
      compiledTemplates[templateNames[i]] = new template(parsed.t, partialsList);
    }
  }

  // Compile templates as partials
  parseTemplates(rawTemplates, templateNames, compiledTemplates);
  _.keys(rawTemplates).forEach(function(item) {
    partialsList[item] = compiledTemplates[item];
  });
  // Reparse templates with partials
  parseTemplates(rawTemplates, templateNames, compiledTemplates);
  return compiledTemplates;
}
module.exports = {compileTemplates: compileTemplates};
<|endoftext|>


<commit_before>/**
 * Copyright 2019 Google LLC
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

'use strict';

// sample-metadata:
//   title: Cloud Tasks Create App Engine Target
//   description: Create Cloud Tasks with a Google App Engine Target
//   usage: node createTask.js <projectId> <queueName> <location> <payload> <delayInSeconds>

/**
 * Create a task for a given queue with an arbitrary payload.
 */
async function createTask(
  project = 'my-project-id', // Your GCP Project id
  queue = 'my-appengine-queue', // Name of your Queue
  location = 'us-central1', // The GCP region of your queue
  payload = 'Hello, World!', // The task HTTP request body
  inSeconds = 0 // Delay in task execution
) {
  // [START cloud_tasks_appengine_create_task]
  // [START tasks_quickstart]
  // Imports the Google Cloud Tasks library.
  const {CloudTasksClient} = require('@google-cloud/tasks');

  // Instantiates a client.
  const client = new CloudTasksClient();

  // TODO(developer): Uncomment these lines and replace with your values.
  // const project = 'my-project-id';
  // const queue = 'my-appengine-queue';
  // const location = 'us-central1';
  // const payload = 'Hello, World!';

  // Construct the fully qualified queue name.
  const parent = client.queuePath(project, location, queue);

  const task = {
    appEngineHttpRequest: {
      httpMethod: 'POST',
      relativeUri: '/log_payload',
    },
  };

  if (payload) {
    task.appEngineHttpRequest.body = Buffer.from(payload).toString('base64');
  }

  if (inSeconds) {
    // The time when the task is scheduled to be attempted.
    task.scheduleTime = {
      seconds: inSeconds + Date.now() / 1000,
    };
  }

  const request = {
    parent: parent,
    task: task,
  };

  console.log('Sending task:');
  console.log(task);
  // Send create task request.
  const [response] = await client.createTask(request);
  const name = response.name;
  console.log(`Created task ${name}`);

  // [END cloud_tasks_appengine_create_task]
  // [END tasks_quickstart]
}

createTask(...process.argv.slice(2)).catch(console.error);
<commit_msg>refactor: style fixes for tasks_quickstart (#281)<commit_after>/**
 * Copyright 2019 Google LLC
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

'use strict';

// sample-metadata:
//   title: Cloud Tasks Create App Engine Target
//   description: Create Cloud Tasks with a Google App Engine Target
//   usage: node createTask.js <projectId> <queueName> <location> <payload> <delayInSeconds>

/**
 * Create a task for a given queue with an arbitrary payload.
 */
async function createTask(
  project = 'my-project-id', // Your GCP Project id
  queue = 'my-appengine-queue', // Name of your Queue
  location = 'us-central1', // The GCP region of your queue
  payload = 'Hello, World!', // The task HTTP request body
  inSeconds = 0 // Delay in task execution
) {
  // [START cloud_tasks_appengine_create_task]
  // [START tasks_quickstart]
  // Imports the Google Cloud Tasks library.
  const {CloudTasksClient} = require('@google-cloud/tasks');

  // Instantiates a client.
  const client = new CloudTasksClient();

  // TODO(developer): Uncomment these lines and replace with your values.
  // const project = 'my-project-id';
  // const queue = 'my-appengine-queue';
  // const location = 'us-central1';
  // const payload = 'Hello, World!';

  // Construct the fully qualified queue name.
  const parent = client.queuePath(project, location, queue);

  const task = {
    appEngineHttpRequest: {
      httpMethod: 'POST',
      relativeUri: '/log_payload',
    },
  };

  if (payload) {
    task.appEngineHttpRequest.body = Buffer.from(payload).toString('base64');
  }

  if (inSeconds) {
    // The time when the task is scheduled to be attempted.
    task.scheduleTime = {
      seconds: inSeconds + Date.now() / 1000,
    };
  }

  console.log('Sending task:');
  console.log(task);
  // Send create task request.
  const request = {parent, task};
  const [response] = await client.createTask(request);
  const name = response.name;
  console.log(`Created task ${name}`);

  // [END cloud_tasks_appengine_create_task]
  // [END tasks_quickstart]
}

createTask(...process.argv.slice(2)).catch(console.error);
<|endoftext|>


<commit_before>
// initialize a package.json file

module.exports = init

var prompt = require("./utils/prompt")
  , path = require("path")
  , readJson = require("./utils/read-json")
  , fs = require("./utils/graceful-fs")
  , promiseChain = require("./utils/promise-chain")
  , exec = require("./utils/exec")
  , semver = require("./utils/semver")
  , log = require("./utils/log")
  , npm = require("../npm")
  , output = require("./utils/output")

init.usage = "npm init [folder]"

function init (args, cb) {
  var folder = args[0] || "."
    , ll = npm.config.get("loglevel")
  npm.config.set("loglevel", "paused")
  if (folder.charAt(0) !== "/") folder = path.join(process.cwd(), folder)

  readJson(path.join(folder, "package.json"), function (er, data) {
    if (er) data = {}
    init_(data, folder, function (er) {
      npm.config.set("loglevel", ll)
      if (!er) log(path.join(folder, "package.json"), "written")
      cb(er)
    })
  })
}
function init_ (data, folder, cb) {
  var dl
    , outfd = npm.config.get("outfd")
  output.write(outfd,
    ["This utility will walk you through creating a package.json file."
    ,"It only covers the most common items, and tries to guess sane defaults."
    ,"See `npm help json` for definitive documentation on these fields"
    ,"and exactly what they do."
    ,"Press ^C at any time to quit."
    ,""
    ].join("\n"))
  promiseChain(cb)
    ( prompt
    , ["Package name: ", defaultName(folder, data)]
    , function (n) { data.name = n }
    )
    ( prompt
    , ["Description: ", data.description]
    , function (d) { data.description = d }
    )
    ( defaultVersion, [folder, data], function (v) { data.version = v } )
    (function (cb) {
      prompt("Package version: ", data.version, function (er, v) {
        if (er) return cb(er)
        data.version = v
        cb()
      })
    }, [])
    ( prompt
    , ["Project homepage: ", data.homepage || data.url || "(none)"]
    , function (u) {
        if (u === "(none)") return
        data.homepage = u
        delete data.url
      }
    )
    ( prompt
    , ["Author name: ", data.author && data.author.name]
    , function (n) {
        if (!n) return
        (data.author = data.author || {}).name = n
      }
    )
    ( prompt
    , ["Author email: ", data.author && data.author.email || "(none)"]
    , function (n) {
        if (n === "(none)") return
        (data.author = data.author || {}).email = n
      }
    )
    ( prompt
    , ["Author url: ", data.author && data.author.url || "(none)"]
    , function (n) {
        if (n === "(none)") return
        (data.author = data.author || {}).url = n
      }
    )
    ( prompt
    , ["Main module/entry point: ", data.main || "(none)"]
    , function (m) {
        if (m === "(none)") {
          delete data.main
          return
        }
        data.main = m
      }
    )
    ( defaultLib, [data, folder], function (d) { dl = d } )
    ( function (cb) {
        prompt("Which folder do your modules live in: ", dl, cb)
      }
    , []
    , function (l) {
        if (l === "(none)") {
          if (data.directories && data.directories.lib) {
            delete data.directories.lib
          }
          return
        }
        (data.directories = data.directories || {}).lib = l
      }
    )
    ( prompt
    , ["Test command: ", data.scripts && data.scripts.test || "(none)"]
    , function (t) {
        if (t === "(none)") return
        (data.scripts = data.scripts || {}).test = t
      }
    )
    ( prompt
    , [ "What versions of node does it run on? "
      , data.engines && data.engines.node || "*"
      ]
    , function (nodever) {
        (data.engines = data.engines || {}).node = nodever
      }
    )
    // todo: friendly dependency resolution stuffs.
    (cleanupPaths, [data, folder])
    (function (cb) {
      try { data = readJson.processJson(data) }
      catch (er) { return cb(er) }
      Object.keys(data)
        .filter(function (k) { return k.match(/^_/) })
        .forEach(function (k) { delete data[k] })
      readJson.unParsePeople(data)
      var str = JSON.stringify(data, null, 2)
        , msg = "About to write to "
              + path.join(folder, "package.json")
              + "\n\n"
              + str
              + "\n\n"
      output.write(outfd, msg, cb)
    })
    (function (cb) {
      prompt("\nIs this ok? ", "yes", function (er, ok) {
        if (er) return cb(er)
        if (ok.toLowerCase().charAt(0) !== "y") {
          return cb(new Error("cancelled"))
        }
        return cb()
      })
    })
    (function (cb) {
      fs.writeFile( path.join(folder, "package.json")
                  , JSON.stringify(data, null, 2)
                  , cb
                  )
    })
    ()
}

function defaultLib (data, folder, cb) {
  // existing lib setting?
  if (data.directories && data.directories.lib) {
    return cb(null, data.directories.lib)
  }
  // two options at this point.
  // if main is ./lib/name.js, look first for ./lib/name/
  // failing that, use ./lib
  // if main is ./foo.js, then look for ./lib
  var l
  if (data.main) {
    l = path.join(folder, path.dirname(data.main))
  } else {
    l = folder
  }
  // now try to walk down any ./lib or ./name folders we can find.
  // it just has to be a reasonable guess
  defaultLibWalker(l, data.name, cb)
}
function defaultLibWalker (folder, name, cb) {
  fs.readdir(folder, function (er, files) {
    // oops?
    return (er) ? cb(null, path.dirname(folder)) // oops?
          : (files.indexOf(name) !== -1) ?
              defaultLibWalker(path.join(folder, name), name, cb)
          : (files.indexOf("lib") !== -1) ?
              defaultLibWalker(path.join(folder, "lib"), name, cb)
          : cb(null, folder)
  })
}
// sync - no io
function defaultName (folder, data) {
  if (data.name) return data.name
  return path.basename(folder).replace(/^node[_-]?|[-\.]?js$/g, '')
}

function defaultVersion (folder, data, cb) {
  if (data.version) return cb(null, data.version)
  exec("git", ["describe", "--tags"], process.env, false, folder,
       function (er, code, out) {
    out = (out || "").trim()
    if (semver.valid(out)) return cb(null, out)
    return cb(null, "0.0.0")
  })
}

function cleanupPaths (data, folder, cb) {
  if (data.main) {
    data.main = cleanupPath(data.main, folder)
  }
  var dirs = data.directories
  if (dirs) {
    Object.keys(dirs).forEach(function (dir) {
      dirs[dir] = cleanupPath(dirs[dir], folder)
    })
  }
  cb()
}
function cleanupPath (m, folder) {
  if (m.indexOf(folder) === 0) m = path.join(".", m.substr(folder.length))
  return m
}
<commit_msg>Add git repo step to `npm init`.<commit_after>
// initialize a package.json file

module.exports = init

var prompt = require("./utils/prompt")
  , path = require("path")
  , readJson = require("./utils/read-json")
  , fs = require("./utils/graceful-fs")
  , promiseChain = require("./utils/promise-chain")
  , exec = require("./utils/exec")
  , semver = require("./utils/semver")
  , log = require("./utils/log")
  , npm = require("../npm")
  , output = require("./utils/output")

init.usage = "npm init [folder]"

function init (args, cb) {
  var folder = args[0] || "."
    , ll = npm.config.get("loglevel")
  npm.config.set("loglevel", "paused")
  if (folder.charAt(0) !== "/") folder = path.join(process.cwd(), folder)

  readJson(path.join(folder, "package.json"), function (er, data) {
    if (er) data = {}
    init_(data, folder, function (er) {
      npm.config.set("loglevel", ll)
      if (!er) log(path.join(folder, "package.json"), "written")
      cb(er)
    })
  })
}
function init_ (data, folder, cb) {
  var dl
    , outfd = npm.config.get("outfd")
  output.write(outfd,
    ["This utility will walk you through creating a package.json file."
    ,"It only covers the most common items, and tries to guess sane defaults."
    ,"See `npm help json` for definitive documentation on these fields"
    ,"and exactly what they do."
    ,"Press ^C at any time to quit."
    ,""
    ].join("\n"))
  promiseChain(cb)
    ( prompt
    , ["Package name: ", defaultName(folder, data)]
    , function (n) { data.name = n }
    )
    ( prompt
    , ["Description: ", data.description]
    , function (d) { data.description = d }
    )
    ( defaultVersion, [folder, data], function (v) { data.version = v } )
    (function (cb) {
      prompt("Package version: ", data.version, function (er, v) {
        if (er) return cb(er)
        data.version = v
        cb()
      })
    }, [])
    ( prompt
    , ["Project homepage: ", data.homepage || data.url || "(none)"]
    , function (u) {
        if (u === "(none)") return
        data.homepage = u
        delete data.url
      }
    )
    ( defaultRepo, [folder, data], function (r) { data.repository = r } )
    (function (cb) {
      prompt("Project git repository: "
             , data.repository && data.repository.url || "none"
             , function (er, r) {
               if (er) return cb(er)
               if (r !== "none") {
                 data.repository = (data.repository || {}).url = r
               }
               cb()
             })
    }, [])
    ( prompt
    , ["Author name: ", data.author && data.author.name]
    , function (n) {
        if (!n) return
        (data.author = data.author || {}).name = n
      }
    )
    ( prompt
    , ["Author email: ", data.author && data.author.email || "(none)"]
    , function (n) {
        if (n === "(none)") return
        (data.author = data.author || {}).email = n
      }
    )
    ( prompt
    , ["Author url: ", data.author && data.author.url || "(none)"]
    , function (n) {
        if (n === "(none)") return
        (data.author = data.author || {}).url = n
      }
    )
    ( prompt
    , ["Main module/entry point: ", data.main || "(none)"]
    , function (m) {
        if (m === "(none)") {
          delete data.main
          return
        }
        data.main = m
      }
    )
    ( defaultLib, [data, folder], function (d) { dl = d } )
    ( function (cb) {
        prompt("Which folder do your modules live in: ", dl, cb)
      }
    , []
    , function (l) {
        if (l === "(none)") {
          if (data.directories && data.directories.lib) {
            delete data.directories.lib
          }
          return
        }
        (data.directories = data.directories || {}).lib = l
      }
    )
    ( prompt
    , ["Test command: ", data.scripts && data.scripts.test || "(none)"]
    , function (t) {
        if (t === "(none)") return
        (data.scripts = data.scripts || {}).test = t
      }
    )
    ( prompt
    , [ "What versions of node does it run on? "
      , data.engines && data.engines.node || "*"
      ]
    , function (nodever) {
        (data.engines = data.engines || {}).node = nodever
      }
    )
    // todo: friendly dependency resolution stuffs.
    (cleanupPaths, [data, folder])
    (function (cb) {
      try { data = readJson.processJson(data) }
      catch (er) { return cb(er) }
      Object.keys(data)
        .filter(function (k) { return k.match(/^_/) })
        .forEach(function (k) { delete data[k] })
      readJson.unParsePeople(data)
      var str = JSON.stringify(data, null, 2)
        , msg = "About to write to "
              + path.join(folder, "package.json")
              + "\n\n"
              + str
              + "\n\n"
      output.write(outfd, msg, cb)
    })
    (function (cb) {
      prompt("\nIs this ok? ", "yes", function (er, ok) {
        if (er) return cb(er)
        if (ok.toLowerCase().charAt(0) !== "y") {
          return cb(new Error("cancelled"))
        }
        return cb()
      })
    })
    (function (cb) {
      fs.writeFile( path.join(folder, "package.json")
                  , JSON.stringify(data, null, 2)
                  , cb
                  )
    })
    ()
}

function defaultLib (data, folder, cb) {
  // existing lib setting?
  if (data.directories && data.directories.lib) {
    return cb(null, data.directories.lib)
  }
  // two options at this point.
  // if main is ./lib/name.js, look first for ./lib/name/
  // failing that, use ./lib
  // if main is ./foo.js, then look for ./lib
  var l
  if (data.main) {
    l = path.join(folder, path.dirname(data.main))
  } else {
    l = folder
  }
  // now try to walk down any ./lib or ./name folders we can find.
  // it just has to be a reasonable guess
  defaultLibWalker(l, data.name, cb)
}
function defaultLibWalker (folder, name, cb) {
  fs.readdir(folder, function (er, files) {
    // oops?
    return (er) ? cb(null, path.dirname(folder)) // oops?
          : (files.indexOf(name) !== -1) ?
              defaultLibWalker(path.join(folder, name), name, cb)
          : (files.indexOf("lib") !== -1) ?
              defaultLibWalker(path.join(folder, "lib"), name, cb)
          : cb(null, folder)
  })
}
// sync - no io
function defaultName (folder, data) {
  if (data.name) return data.name
  return path.basename(folder).replace(/^node[_-]?|[-\.]?js$/g, '')
}

function defaultVersion (folder, data, cb) {
  if (data.version) return cb(null, data.version)
  exec("git", ["describe", "--tags"], process.env, false, folder,
       function (er, code, out) {
    out = (out || "").trim()
    if (semver.valid(out)) return cb(null, out)
    return cb(null, "0.0.0")
  })
}

function defaultRepo (folder, data, cb) {
  if (data.repository) return cb(null, data.repository)
  process.chdir(folder)
  exec("git", ["remote", "-v"], process.env, false, function (er, code, out) {
    out = (out || "")
      .trim()
      .split("\n").filter(function (line) {
        return line.search(/^origin/) !== -1
      })[0]
    if (!out) return cb(null, {})
    repo = {
      type: "git"
      , url: out.split(/\s/)[1].replace("git@github.com:", "git://github.com/")
    }
    return cb(null, repo)
  })
}

function cleanupPaths (data, folder, cb) {
  if (data.main) {
    data.main = cleanupPath(data.main, folder)
  }
  var dirs = data.directories
  if (dirs) {
    Object.keys(dirs).forEach(function (dir) {
      dirs[dir] = cleanupPath(dirs[dir], folder)
    })
  }
  cb()
}
function cleanupPath (m, folder) {
  if (m.indexOf(folder) === 0) m = path.join(".", m.substr(folder.length))
  return m
}
<|endoftext|>


<commit_before>/*
 Copyright 2018 Carmilla Mina Jankovic

 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at

 http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
 */

const List = require('./List');
const MessageDialog = require('../views/dialogs/MessageDialog');

const dataHandler = require('../../data/DataHandler');
const storageManager = require('../../StorageManager');
const eventCentral = require('../../EventCentral');
const textTools = require('../../TextTools');
const userComposer = require('../../data/composers/UserComposer');
const accessCentral = require('../../AccessCentral');
const messageComposer = require('../../data/composers/MessageComposer');
const teamComposer = require('../../data/composers/TeamComposer');

class MessageList extends List {
  /**
   * MessageList constructor.
   * @param {Object} params Parameters.
   * @param {boolean} [params.multiRoom] Should messages from all rooms be retrieved and shown in the list?
   * @param {boolean} [params.shouldSwitchRoom] Should the messages only be retrieved from the user's current room?
   * @param {string} [params.roomId] Id of the room to retrieve messages from.
   * @param {string[]} [params.classes] CSS classes.
   * @param {string} [params.elementId] Id of the list element.
   */
  constructor({
    roomId,
    effect,
    hideDate = false,
    showTeam = true,
    fullDate = true,
    multiRoom = false,
    shouldSwitchRoom = false,
    whisperText = ' - ',
    roomLists = [],
    classes = [],
    elementId = `mList-${Date.now()}`,
  }) {
    const superParams = {
      elementId,
      effect,
      sorting: {
        paramName: 'customTimeCreated',
        fallbackParamName: 'timeCreated',
      },
      listItemClickFuncs: {
        onlyListItemFields: true,
        leftFunc: (objectId) => {
          const message = messageComposer.getMessage({ messageId: objectId });
          const {
            hasFullAccess,
          } = accessCentral.hasAccessTo({
            objectToAccess: message,
            toAuth: userComposer.getCurrentUser(),
          });

          if (hasFullAccess) {
            const messageDialog = new MessageDialog({
              messageId: message.objectId,
              text: message.text,
            });

            messageDialog.addToView({
              element: this.getParentElement(),
            });
          }
        },
      },
      shouldScrollToBottom: true,
      classes: classes.concat(['msgList']),
      dependencies: [
        dataHandler.users,
        dataHandler.rooms,
        dataHandler.aliases,
        dataHandler.teams,
      ],
      shouldFocusOnClick: false,
      collector: dataHandler.messages,
      fieldToAppend: 'text',
      shouldAppendImage: true,
      appendClasses: ['msgLine'],
      listItemFieldsClasses: ['msgInfo'],
      listItemFields: [
        {
          paramName: 'ownerAliasId',
          fallbackTo: 'ownerId',
          convertFunc: (objectId) => {
            const identity = userComposer.getIdentity({ objectId });
            const teamIds = identity.partOfTeams || [];
            const shortNames = teamIds.map(teamId => teamComposer.getTeam({ teamId }).shortName);

            if (identity) {
              let name = identity.username || identity.aliasName;

              if (showTeam) {
                name += `[${shortNames.join('/')}]`;
              }

              return name;
            }

            return objectId;
          },
        }, {
          paramName: 'customTimeCreated',
          fallbackTo: 'timeCreated',
          convertFunc: (date) => {
            const timestamp = textTools.generateTimestamp({ date });

            if (hideDate) {
              return timestamp.fullTime;
            }

            return fullDate
              ? `${timestamp.fullTime} ${timestamp.fullDate}`
              : `${timestamp.fullTime} ${timestamp.halfDate}`;
          },
        }, {
          classes: ['msgRoomName'],
          paramName: 'roomId',
          convertFunc: (objectId) => {
            const room = dataHandler.rooms.getObject({ objectId });

            if (!multiRoom) {
              return '';
            }

            if (room) {
              const { isWhisper, participantIds } = room;

              if (isWhisper) {
                const identities = userComposer.getWhisperIdentities({ participantIds });

                return identities.length > 0
                  ? `${identities[0].username || identities[0].aliasName}${whisperText}${identities[1].username || identities[1].aliasName}`
                  : '';
              }

              return room.roomName.slice(0, 24);
            }

            return objectId;
          },
        },
      ],
    };

    if (!multiRoom) {
      superParams.filter = {
        rules: [
          { paramName: 'roomId', paramValue: roomId || storageManager.getCurrentRoom() },
        ],
      };
    }

    super(superParams);

    this.onCreateFunc = ({ object }) => {
      this.roomLists.every((roomList) => {
        const rooms = roomList.getCollectorObjects();
        const foundRoom = rooms.find(room => object.roomId === room.objectId);

        if (foundRoom) {
          roomList.animateElement({ elementId: foundRoom.objectId });

          return false;
        }

        return true;
      });
    };
    this.roomLists = roomLists;
    this.roomId = roomId || this.getRoomId();

    if (shouldSwitchRoom) {
      eventCentral.addWatcher({
        event: eventCentral.Events.SWITCH_ROOM,
        func: ({ origin, room }) => {
          if (!origin || this.roomLists.map(roomList => roomList.elementId).some(roomListId => roomListId === origin)) {
            this.getParentElement().classList.remove('flash');
            this.getParentElement().classList.add('flash');

            setTimeout(() => {
              this.getParentElement().classList.remove('flash');
            }, 400);

            this.showMessagesByRoom({ roomId: room.objectId });
          }
        },
      });
    }
  }

  showMessagesByRoom({ roomId }) {
    this.roomId = roomId;
    this.filter = { rules: [{ paramName: 'roomId', paramValue: roomId }] };

    this.appendList();
  }

  setRoomListId(id) {
    this.roomListId = id;
  }

  setRoomId(roomId) {
    this.roomId = roomId;
  }

  getRoomId() {
    return this.roomId || storageManager.getCurrentRoom();
  }
}

module.exports = MessageList;
<commit_msg>Collapse list items sent from the same id<commit_after>/*
 Copyright 2018 Carmilla Mina Jankovic

 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at

 http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
 */

const List = require('./List');
const MessageDialog = require('../views/dialogs/MessageDialog');

const dataHandler = require('../../data/DataHandler');
const storageManager = require('../../StorageManager');
const eventCentral = require('../../EventCentral');
const textTools = require('../../TextTools');
const userComposer = require('../../data/composers/UserComposer');
const accessCentral = require('../../AccessCentral');
const messageComposer = require('../../data/composers/MessageComposer');
const teamComposer = require('../../data/composers/TeamComposer');

class MessageList extends List {
  /**
   * MessageList constructor.
   * @param {Object} params Parameters.
   * @param {boolean} [params.multiRoom] Should messages from all rooms be retrieved and shown in the list?
   * @param {boolean} [params.shouldSwitchRoom] Should the messages only be retrieved from the user's current room?
   * @param {string} [params.roomId] Id of the room to retrieve messages from.
   * @param {string[]} [params.classes] CSS classes.
   * @param {string} [params.elementId] Id of the list element.
   */
  constructor({
    roomId,
    effect,
    hideDate = false,
    showTeam = true,
    fullDate = true,
    multiRoom = false,
    shouldSwitchRoom = false,
    whisperText = ' - ',
    roomLists = [],
    classes = [],
    elementId = `mList-${Date.now()}`,
  }) {
    const superParams = {
      elementId,
      effect,
      collapseEqual: {
        paramName: 'ownerAliasId',
        fallbackTo: 'ownerId',
      },
      sorting: {
        paramName: 'customTimeCreated',
        fallbackParamName: 'timeCreated',
      },
      listItemClickFuncs: {
        onlyListItemFields: true,
        leftFunc: (objectId) => {
          const message = messageComposer.getMessage({ messageId: objectId });
          const {
            hasFullAccess,
          } = accessCentral.hasAccessTo({
            objectToAccess: message,
            toAuth: userComposer.getCurrentUser(),
          });

          if (hasFullAccess) {
            const messageDialog = new MessageDialog({
              messageId: message.objectId,
              text: message.text,
            });

            messageDialog.addToView({
              element: this.getParentElement(),
            });
          }
        },
      },
      shouldScrollToBottom: true,
      classes: classes.concat(['msgList']),
      dependencies: [
        dataHandler.users,
        dataHandler.rooms,
        dataHandler.aliases,
        dataHandler.teams,
      ],
      shouldFocusOnClick: false,
      collector: dataHandler.messages,
      fieldToAppend: 'text',
      shouldAppendImage: true,
      appendClasses: ['msgLine'],
      listItemFieldsClasses: ['msgInfo'],
      listItemFields: [
        {
          paramName: 'ownerAliasId',
          fallbackTo: 'ownerId',
          convertFunc: (objectId) => {
            const identity = userComposer.getIdentity({ objectId });
            const teamIds = identity.partOfTeams || [];
            const shortNames = teamIds.map(teamId => teamComposer.getTeam({ teamId }).shortName);

            if (identity) {
              let name = identity.username || identity.aliasName;

              if (showTeam) {
                name += `[${shortNames.join('/')}]`;
              }

              return name;
            }

            return objectId;
          },
        }, {
          paramName: 'customTimeCreated',
          fallbackTo: 'timeCreated',
          convertFunc: (date) => {
            const timestamp = textTools.generateTimestamp({ date });

            if (hideDate) {
              return timestamp.fullTime;
            }

            return fullDate
              ? `${timestamp.fullTime} ${timestamp.fullDate}`
              : `${timestamp.fullTime} ${timestamp.halfDate}`;
          },
        }, {
          classes: ['msgRoomName'],
          paramName: 'roomId',
          convertFunc: (objectId) => {
            const room = dataHandler.rooms.getObject({ objectId });

            if (!multiRoom) {
              return '';
            }

            if (room) {
              const { isWhisper, participantIds } = room;

              if (isWhisper) {
                const identities = userComposer.getWhisperIdentities({ participantIds });

                return identities.length > 0
                  ? `${identities[0].username || identities[0].aliasName}${whisperText}${identities[1].username || identities[1].aliasName}`
                  : '';
              }

              return room.roomName.slice(0, 24);
            }

            return objectId;
          },
        },
      ],
    };

    if (!multiRoom) {
      superParams.filter = {
        rules: [
          { paramName: 'roomId', paramValue: roomId || storageManager.getCurrentRoom() },
        ],
      };
    }

    super(superParams);

    this.onCreateFunc = ({ object }) => {
      this.roomLists.every((roomList) => {
        const rooms = roomList.getCollectorObjects();
        const foundRoom = rooms.find(room => object.roomId === room.objectId);

        if (foundRoom) {
          roomList.animateElement({ elementId: foundRoom.objectId });

          return false;
        }

        return true;
      });
    };
    this.roomLists = roomLists;
    this.roomId = roomId || this.getRoomId();

    if (shouldSwitchRoom) {
      eventCentral.addWatcher({
        event: eventCentral.Events.SWITCH_ROOM,
        func: ({ origin, room }) => {
          if (!origin || this.roomLists.map(roomList => roomList.elementId).some(roomListId => roomListId === origin)) {
            this.getParentElement().classList.remove('flash');
            this.getParentElement().classList.add('flash');

            setTimeout(() => {
              this.getParentElement().classList.remove('flash');
            }, 400);

            this.showMessagesByRoom({ roomId: room.objectId });
          }
        },
      });
    }
  }

  showMessagesByRoom({ roomId }) {
    this.roomId = roomId;
    this.filter = { rules: [{ paramName: 'roomId', paramValue: roomId }] };

    this.appendList();
  }

  setRoomListId(id) {
    this.roomListId = id;
  }

  setRoomId(roomId) {
    this.roomId = roomId;
  }

  getRoomId() {
    return this.roomId || storageManager.getCurrentRoom();
  }
}

module.exports = MessageList;
<|endoftext|>