<commit_before>const [
    /*-1 */COMMENT,
    /* 0 */SPACE,
    /* 1 */STRAP,
    /* 2 */STAMP,
    /* 3 */VALUE,
    /* 4 */QUOTED,
    /* 5 */PIECE,
    /* 6 */EXPRESS,
    /* 7 */SCOPED,
    /* 8 */LABEL,
    /* 9 */PROPERTY,
] = new Array(20).fill(0).map((_, a) => a - 1);
var number_reg = /^[\+\-]?(0x[0-9a-f]+|0b\d+|0o\d+|(\d*\.\d+|\d+\.?)(e[\+\-]?\d+|[mn])?)$/i;
var skipAssignment = function (o) {
    var needpunc = false;
    var o0 = o;
    var qcount = 0;
    loop: while (o) switch (o.type) {
        case STAMP:
            switch (o.text) {
                case ",":
                case ";":
                    break loop;
                case "++":
                case "--":
                    o = o.next;
                    break;
                case "!":
                case "~":
                case "+":
                case "-":
                    o = o.next;
                    needpunc = false;
                    break;
                case "?":
                    qcount++;
                    needpunc = false;
                    o = o.next;
                    break;
                case ":":
                    qcount--;
                    if (qcount < 0) break loop;
                    needpunc = false;
                    o = o.next;
                    break;
                default:
                    if (/^[!~\+\-]+$/.test(o.text)) {
                        needpunc = false;
                        o = o.next;
                        break;
                    }
                    if (!needpunc) break loop;
                    needpunc = false;
                    o = o.next;
            }
            break;
        case SCOPED:
            if (needpunc && o.entry === "{") break loop;
            o = o.next;
            needpunc = true;
            break;
        case EXPRESS:
            if (/^\.|\.$/.test(o.text)) {
                o = o.next;
                break;
            }
            else if (/^\[/.test(o.text)) {
                needpunc = true;
                o = o.next;
                break;
            }
        case VALUE:
        case QUOTED:
            if (needpunc) break loop;
            needpunc = true;
            o = o.next;
            break;
        case STRAP:
            if (needpunc) {
                if (!/^(in|instanceof)$/.test(o.text)) break loop;
                o = o.next;
                needpunc = false;
            }
            else if (o.text === "class") {
                o = o.next;
                while (o && !o.isClass) o = o.next;
                while (o && o.isClass) o = o.next;
                needpunc = true;
                break;
            }
            else if (o.text === "function") {
                o = o.next;
                if (o && o.type === EXPRESS) o = o.next;
                if (o) o = o.next;
                if (o) o = o.next;
                needpunc = true;
                break;
            }
            else {
                o = o.next;
                needpunc = false;
            }
            break;
        default:
            console.log(o);
            throw new Error('代码结构异常！');
            o = o.next;
    }
    return o;
};
var createScoped = function (parsed) {
    var used = Object.create(null); var vars = Object.create(null), lets = vars;
    var scoped = [];
    var run = function (o, id) {
        loop: while (o) {
            var isCatch = false;
            var isFunction = false;
            var isScope = false;
            var isArrow = false;
            switch (o.type) {
                case QUOTED:
                    if (o.length) {
                        run(o.first);
                    }
                    break;
                case STAMP:
                    break;
                case PROPERTY:
                    if (o.next) {
                        if (o.next.type !== STAMP || o.next.text !== ",") break;
                    }
                case VALUE:
                    if (number_reg.test(o.text)) break;
                case EXPRESS:
                    if (o.prev && o.prev.type === EXPRESS) {
                        if (/\.$/.test(o.prev.text)) break;
                    }
                    var u = o.text.replace(/^([^\.\[]*)[\s\S]*$/, '$1');
                    if (!u) break;
                    if (o.next && o.next.type === STAMP && o.next.text === "=>") {
                        isScope = true;
                        isArrow = true;
                    }
                    else {
                        saveTo(used, u, o);
                    }
                    break;
                case LABEL:
                    var name = o.text;
                    name = name.slice(0, name.length - 1);
                    vars[name] = true;
                    o.kind = "label";
                    saveTo(used, name, o);
                    break;

                case STRAP:
                    var s = o.text;
                    switch (s) {
                        case "var":
                        case "import":
                            var m = vars;
                        case "let":
                        case "const":
                            m = m || lets;
                            var [declared, used0, o0, skiped] = getDeclared(o.next, s);
                            while (skiped.length) {
                                var o1 = run(skiped[0], 0);
                                let sindex = skiped.indexOf(o1);
                                if (sindex < 0) break;
                                skiped.splice(0, sindex + 1);
                            }
                            o = o0;
                            mergeTo(used, used0);
                            Object.assign(m, declared);
                            continue loop;
                        case "function":
                            isFunction = true;
                        case "catch":
                            isCatch = true;
                        case "class":
                            if (!o.isExpress) {
                                o = o.next;

                                if (o.type === EXPRESS) {
                                    vars[o.text] = true;
                                    o.kind = isFunction ? 'function' : 'class';
                                    saveTo(used, o.text, o);

                                    o = o.next;
                                }
                            }
                            isScope = true;
                            break;

                    }
                    break;
                case SCOPED:
                    if (o.entry === "(") {
                        if (o.next && o.next.type === STAMP && o.next.text === "=>"
                            || o.prev && (o.prev.type === PROPERTY || o.prev.isprop)) {
                            isArrow = true;
                            isScope = true;
                        }
                        else {
                            run(o.first);
                        }
                    }
                    else if (o.entry === "{") {
                        isScope = true;
                    }
                    else {
                        run(o.first);
                    }
                    break;
            }
            if (isScope) {
                var _used = used;
                var _lets = lets;
                var _vars = vars;
                var _scoped = scoped;
                used = Object.create(null);
                lets = Object.create(null);
                vars = Object.create(null);
                scoped = [];
                var isExpress = o.isExpress;

                if (isFunction || isArrow) {
                    scoped.used = used;
                    scoped.vars = vars;
                    lets = vars;
                    if (isFunction) vars.this = true, vars.arguments = true;
                    isFunction = true;
                } else {
                    vars = _vars;
                    scoped.lets = lets;
                    scoped.used = used;
                }
                if (isArrow);
                else if (o.isExpress && o.type !== SCOPED) {
                    o = o.next;
                    if (o.type === EXPRESS) {
                        vars[o.text] = true;
                        o.kind = isFunction ? 'function' : 'class';
                        saveTo(used, o.text, o);
                        o = o.next;
                    }
                }
                if (!isFunction) while (o.type !== SCOPED) {
                    // if (o.next && o.next.type === STAMP && o.next.text === "=>") break;
                    o = run(o, 0);
                    o = o.next;
                    if (!o) break loop;
                }

                if (o.entry === "(") {
                    o.isExpress = isExpress;
                    if (isFunction || isCatch) {
                        var [declared, used0, o0, skiped] = getDeclared(o.first, 'argument');
                        mergeTo(used, used0);
                        while (skiped.length) {
                            var o1 = run(skiped[0], 0);
                            var sindex = skiped.indexOf(o1);
                            if (sindex < 0) break;
                            skiped.splice(0, sindex + 1);
                        }
                        Object.assign(isCatch ? lets : vars, declared);
                    }
                    else {
                        run(o.first);
                    }
                    o = o.next;
                    if (!o) break;
                    if (o.type === STAMP && o.text === "=>") o = o.next;
                }
                else if (isArrow) {
                    vars[o.text] = true;
                    o.kind = 'argument';
                    saveTo(used, o.text, o);
                    o = o.next.next;
                }
                if (!o) break;
                if (o.type === SCOPED && o.entry === "{") {
                    o.isExpress = isExpress;
                    run(o.first);
                }
                else {
                    do {
                        if (o.type === STAMP && o.text === ";") break;
                        o = run(o, 0);
                        var next = o.next;
                        if (!next) break;
                        var e = o;
                        if (o.type === STAMP && /^(\+\+|\-\-)$/.test(o.text) || ~[VALUE, QUOTED, SCOPED].indexOf(o.type) || EXPRESS === o.type && !/\.$/.test(o.text)) {
                            if (~[VALUE, QUOTED, PROPERTY, LABEL].indexOf(next.type)) break;
                            if (EXPRESS === next.type && !/^\./.test(next.text)) break;
                            if (next.type === SCOPED && next.entry === "{") break;
                        }
                        o = next;
                    } while (o);
                }
                var map = isFunction ? vars : lets;
                var keepscope = false;
                for (var k in map) {
                    keepscope = true;
                    break;
                }
                if (keepscope) {
                    for (var k in used) {
                        if (!(k in map)) {
                            for (var u of used[k]) {
                                saveTo(_used, k, u);
                            }
                        }
                    }
                    _scoped.push(scoped);
                }
                else {
                    mergeTo(_used, used);
                    if (scoped.length) _scoped.push(scoped);
                }
                if (vars.this) {
                    delete vars.this;
                    delete vars.arguments;
                }
                used = _used;
                lets = _lets;
                vars = _vars;
                scoped = _scoped;
            }
            if (id >= 0) break;
            if (o) o = o.next;
        }
        return o;
    };
    run(parsed.first);
    scoped.used = used;
    scoped.vars = vars;
    var envs = Object.create(null);
    for (var u in used) {
        if (!(u in vars)) {
            if (!/^(true|false|null|this|arguments)$/.test(u)) envs[u] = true;
        }
    }
    scoped.envs = envs;
    return scoped;
};
var getDeclared = function (o, kind) {
    var declared = Object.create(null), used = Object.create(null); var skiped = [];
    loop: while (o) {
        while (o && o.type === STAMP && o.text === ',') o = o.next;
        if (!o) break;
        if (o.isprop) {
            skiped.push(o);
            if (o.next && o.next.type === STAMP && o.next.text === ":") {
                o = o.next;
                o = o.next;
            }
        }
        switch (o.type) {
            case PROPERTY:
                if (o.next && o.next.type === STAMP && o.next.text === ":") {
                    o = o.next.next;
                    continue;
                }
            case STRAP:
            case VALUE:
            case EXPRESS:
                var n = o.text.replace(/^\.\.\.|\.\.\.$/g, '');
                declared[n] = true;
                o.kind = kind;
                saveTo(used, n, o);
                o = o.next;
                break;
            case SCOPED:
                var [d, u, _, s] = getDeclared(o.first, kind);
                while (s.length) skiped.push.apply(skiped, s.splice(0, 1024));
                mergeTo(used, u);
                Object.assign(declared, d);
                o = o.next;
                break;

            default:
                console.log(o);
                throw new Error("代码结构异常");
        }
        if (!o) break;
        switch (o.type) {
            case STRAP:
                if (/^(in|of)$/.test(o.text)) {
                    o = o.next;
                    var o0 = skipAssignment(o);
                    do {
                        skiped.push(o);
                        o = o.next;
                    } while (o !== o0);
                    o = o0;
                    break;
                }
                break loop;
            case STAMP:
                if (o.text === "=") {
                    o = o.next;
                    var o0 = skipAssignment(o);
                    do {
                        skiped.push(o);
                        o = o.next;
                    } while (o !== o0);
                    o = o0;
                    break;
                }
                break;
        }
        if (!o) break;
        if (o.type !== STAMP) break;
        if (o.text !== ',') break;
    }
    return [declared, used, o, skiped];
};
var saveTo = function (used, k, o) {
    if (!(used[k] instanceof Array)) used[k] = [];
    used[k].push(o);
};

var mergeTo = function (used, used0) {
    for (var k in used0) {
        var v = used0[k];
        for (var s of v) saveTo(used, k, s);
    }
};

module.exports = {
    /*-1 */COMMENT,
    /* 0 */SPACE,
    /* 1 */STRAP,
    /* 2 */STAMP,
    /* 3 */VALUE,
    /* 4 */QUOTED,
    /* 5 */PIECE,
    /* 6 */EXPRESS,
    /* 7 */SCOPED,
    /* 8 */LABEL,
    /* 9 */PROPERTY,
    number_reg,
    skipAssignment,
    getDeclared,
    createScoped,
    saveTo,
    mergeTo
};<commit_msg>修复一处错误，支持识别class a extends b中的b<commit_after>const [
    /*-1 */COMMENT,
    /* 0 */SPACE,
    /* 1 */STRAP,
    /* 2 */STAMP,
    /* 3 */VALUE,
    /* 4 */QUOTED,
    /* 5 */PIECE,
    /* 6 */EXPRESS,
    /* 7 */SCOPED,
    /* 8 */LABEL,
    /* 9 */PROPERTY,
] = new Array(20).fill(0).map((_, a) => a - 1);
var number_reg = /^[\+\-]?(0x[0-9a-f]+|0b\d+|0o\d+|(\d*\.\d+|\d+\.?)(e[\+\-]?\d+|[mn])?)$/i;
var skipAssignment = function (o) {
    var needpunc = false;
    var o0 = o;
    var qcount = 0;
    loop: while (o) switch (o.type) {
        case STAMP:
            switch (o.text) {
                case ",":
                case ";":
                    break loop;
                case "++":
                case "--":
                    o = o.next;
                    break;
                case "!":
                case "~":
                case "+":
                case "-":
                    o = o.next;
                    needpunc = false;
                    break;
                case "?":
                    qcount++;
                    needpunc = false;
                    o = o.next;
                    break;
                case ":":
                    qcount--;
                    if (qcount < 0) break loop;
                    needpunc = false;
                    o = o.next;
                    break;
                default:
                    if (/^[!~\+\-]+$/.test(o.text)) {
                        needpunc = false;
                        o = o.next;
                        break;
                    }
                    if (!needpunc) break loop;
                    needpunc = false;
                    o = o.next;
            }
            break;
        case SCOPED:
            if (needpunc && o.entry === "{") break loop;
            o = o.next;
            needpunc = true;
            break;
        case EXPRESS:
            if (/^\.|\.$/.test(o.text)) {
                o = o.next;
                break;
            }
            else if (/^\[/.test(o.text)) {
                needpunc = true;
                o = o.next;
                break;
            }
        case VALUE:
        case QUOTED:
            if (needpunc) break loop;
            needpunc = true;
            o = o.next;
            break;
        case STRAP:
            if (needpunc) {
                if (!/^(in|instanceof)$/.test(o.text)) break loop;
                o = o.next;
                needpunc = false;
            }
            else if (o.text === "class") {
                o = o.next;
                while (o && !o.isClass) o = o.next;
                while (o && o.isClass) o = o.next;
                needpunc = true;
                break;
            }
            else if (o.text === "function") {
                o = o.next;
                if (o && o.type === EXPRESS) o = o.next;
                if (o) o = o.next;
                if (o) o = o.next;
                needpunc = true;
                break;
            }
            else {
                o = o.next;
                needpunc = false;
            }
            break;
        default:
            console.log(o);
            throw new Error('代码结构异常！');
            o = o.next;
    }
    return o;
};
var createScoped = function (parsed) {
    var used = Object.create(null); var vars = Object.create(null), lets = vars;
    var scoped = [];
    var run = function (o, id) {
        loop: while (o) {
            var isCatch = false;
            var isFunction = false;
            var isScope = false;
            var isArrow = false;
            var isDeclare = false;
            switch (o.type) {
                case QUOTED:
                    if (o.length) {
                        run(o.first);
                    }
                    break;
                case STAMP:
                    break;
                case PROPERTY:
                    if (o.next) {
                        if (o.next.type !== STAMP || o.next.text !== ",") break;
                    }
                case VALUE:
                    if (number_reg.test(o.text)) break;
                case EXPRESS:
                    if (o.prev && o.prev.type === EXPRESS) {
                        if (/\.$/.test(o.prev.text)) break;
                    }
                    var u = o.text.replace(/^([^\.\[]*)[\s\S]*$/, '$1');
                    if (!u) break;
                    if (o.next && o.next.type === STAMP && o.next.text === "=>") {
                        isScope = true;
                        isArrow = true;
                    }
                    else {
                        saveTo(used, u, o);
                    }
                    break;
                case LABEL:
                    var name = o.text;
                    name = name.slice(0, name.length - 1);
                    vars[name] = true;
                    o.kind = "label";
                    saveTo(used, name, o);
                    break;

                case STRAP:
                    var s = o.text;
                    switch (s) {
                        case "var":
                        case "import":
                            var m = vars;
                        case "let":
                        case "const":
                            m = m || lets;
                            var [declared, used0, o0, skiped] = getDeclared(o.next, s);
                            while (skiped.length) {
                                var o1 = run(skiped[0], 0);
                                let sindex = skiped.indexOf(o1);
                                if (sindex < 0) break;
                                skiped.splice(0, sindex + 1);
                            }
                            o = o0;
                            mergeTo(used, used0);
                            Object.assign(m, declared);
                            continue loop;
                        case "function":
                            isFunction = true;
                        case "catch":
                            isCatch = true;
                        case "class":
                            if (!o.isExpress) {
                                o = o.next;

                                if (o.type === EXPRESS) {
                                    vars[o.text] = true;
                                    isDeclare = true;
                                    o.kind = isFunction ? 'function' : 'class';
                                    saveTo(used, o.text, o);

                                    o = o.next;
                                }
                            }
                            isScope = true;
                            break;

                    }
                    break;
                case SCOPED:
                    if (o.entry === "(") {
                        if (o.next && o.next.type === STAMP && o.next.text === "=>"
                            || o.prev && (o.prev.type === PROPERTY || o.prev.isprop)) {
                            isArrow = true;
                            isScope = true;
                        }
                        else {
                            run(o.first);
                        }
                    }
                    else if (o.entry === "{") {
                        isScope = true;
                    }
                    else {
                        run(o.first);
                    }
                    break;
            }
            if (isScope) {
                var _used = used;
                var _lets = lets;
                var _vars = vars;
                var _scoped = scoped;
                used = Object.create(null);
                lets = Object.create(null);
                vars = Object.create(null);
                scoped = [];
                var isExpress = o.isExpress;

                if (isFunction || isArrow) {
                    scoped.used = used;
                    scoped.vars = vars;
                    lets = vars;
                    if (isFunction) vars.this = true, vars.arguments = true;
                    isFunction = true;
                } else {
                    vars = _vars;
                    scoped.lets = lets;
                    scoped.used = used;
                }
                if (isArrow);
                else if (o.isExpress && o.type !== SCOPED && !isDeclare) {
                    o = o.next;
                    if (o.type === EXPRESS) {
                        vars[o.text] = true;
                        o.kind = isFunction ? 'function' : 'class';
                        saveTo(used, o.text, o);
                        o = o.next;
                    }
                }
                if (!isFunction) while (o.type !== SCOPED) {
                    // if (o.next && o.next.type === STAMP && o.next.text === "=>") break;
                    o = run(o, 0);
                    o = o.next;
                    if (!o) break loop;
                }

                if (o.entry === "(") {
                    o.isExpress = isExpress;
                    if (isFunction || isCatch) {
                        var [declared, used0, o0, skiped] = getDeclared(o.first, 'argument');
                        mergeTo(used, used0);
                        while (skiped.length) {
                            var o1 = run(skiped[0], 0);
                            var sindex = skiped.indexOf(o1);
                            if (sindex < 0) break;
                            skiped.splice(0, sindex + 1);
                        }
                        Object.assign(isCatch ? lets : vars, declared);
                    }
                    else {
                        run(o.first);
                    }
                    o = o.next;
                    if (!o) break;
                    if (o.type === STAMP && o.text === "=>") o = o.next;
                }
                else if (isArrow) {
                    vars[o.text] = true;
                    o.kind = 'argument';
                    saveTo(used, o.text, o);
                    o = o.next.next;
                }
                if (!o) break;
                if (o.type === SCOPED && o.entry === "{") {
                    o.isExpress = isExpress;
                    run(o.first);
                }
                else {
                    do {
                        if (o.type === STAMP && o.text === ";") break;
                        o = run(o, 0);
                        var next = o.next;
                        if (!next) break;
                        var e = o;
                        if (o.type === STAMP && /^(\+\+|\-\-)$/.test(o.text) || ~[VALUE, QUOTED, SCOPED].indexOf(o.type) || EXPRESS === o.type && !/\.$/.test(o.text)) {
                            if (~[VALUE, QUOTED, PROPERTY, LABEL].indexOf(next.type)) break;
                            if (EXPRESS === next.type && !/^\./.test(next.text)) break;
                            if (next.type === SCOPED && next.entry === "{") break;
                        }
                        o = next;
                    } while (o);
                }
                var map = isFunction ? vars : lets;
                var keepscope = false;
                for (var k in map) {
                    keepscope = true;
                    break;
                }
                if (keepscope) {
                    for (var k in used) {
                        if (!(k in map)) {
                            for (var u of used[k]) {
                                saveTo(_used, k, u);
                            }
                        }
                    }
                    _scoped.push(scoped);
                }
                else {
                    mergeTo(_used, used);
                    if (scoped.length) _scoped.push(scoped);
                }
                if (vars.this) {
                    delete vars.this;
                    delete vars.arguments;
                }
                used = _used;
                lets = _lets;
                vars = _vars;
                scoped = _scoped;
            }
            if (id >= 0) break;
            if (o) o = o.next;
        }
        return o;
    };
    run(parsed.first);
    scoped.used = used;
    scoped.vars = vars;
    var envs = Object.create(null);
    for (var u in used) {
        if (!(u in vars)) {
            if (!/^(true|false|null|this|arguments)$/.test(u)) envs[u] = true;
        }
    }
    scoped.envs = envs;
    return scoped;
};
var getDeclared = function (o, kind) {
    var declared = Object.create(null), used = Object.create(null); var skiped = [];
    loop: while (o) {
        while (o && o.type === STAMP && o.text === ',') o = o.next;
        if (!o) break;
        if (o.isprop) {
            skiped.push(o);
            if (o.next && o.next.type === STAMP && o.next.text === ":") {
                o = o.next;
                o = o.next;
            }
        }
        switch (o.type) {
            case PROPERTY:
                if (o.next && o.next.type === STAMP && o.next.text === ":") {
                    o = o.next.next;
                    continue;
                }
            case STRAP:
            case VALUE:
            case EXPRESS:
                var n = o.text.replace(/^\.\.\.|\.\.\.$/g, '');
                declared[n] = true;
                o.kind = kind;
                saveTo(used, n, o);
                o = o.next;
                break;
            case SCOPED:
                var [d, u, _, s] = getDeclared(o.first, kind);
                while (s.length) skiped.push.apply(skiped, s.splice(0, 1024));
                mergeTo(used, u);
                Object.assign(declared, d);
                o = o.next;
                break;

            default:
                console.log(o);
                throw new Error("代码结构异常");
        }
        if (!o) break;
        switch (o.type) {
            case STRAP:
                if (/^(in|of)$/.test(o.text)) {
                    o = o.next;
                    var o0 = skipAssignment(o);
                    do {
                        skiped.push(o);
                        o = o.next;
                    } while (o !== o0);
                    o = o0;
                    break;
                }
                break loop;
            case STAMP:
                if (o.text === "=") {
                    o = o.next;
                    var o0 = skipAssignment(o);
                    do {
                        skiped.push(o);
                        o = o.next;
                    } while (o !== o0);
                    o = o0;
                    break;
                }
                break;
        }
        if (!o) break;
        if (o.type !== STAMP) break;
        if (o.text !== ',') break;
    }
    return [declared, used, o, skiped];
};
var saveTo = function (used, k, o) {
    if (!(used[k] instanceof Array)) used[k] = [];
    used[k].push(o);
};

var mergeTo = function (used, used0) {
    for (var k in used0) {
        var v = used0[k];
        for (var s of v) saveTo(used, k, s);
    }
};

module.exports = {
    /*-1 */COMMENT,
    /* 0 */SPACE,
    /* 1 */STRAP,
    /* 2 */STAMP,
    /* 3 */VALUE,
    /* 4 */QUOTED,
    /* 5 */PIECE,
    /* 6 */EXPRESS,
    /* 7 */SCOPED,
    /* 8 */LABEL,
    /* 9 */PROPERTY,
    number_reg,
    skipAssignment,
    getDeclared,
    createScoped,
    saveTo,
    mergeTo
};<|endoftext|>


<commit_before>/*jshint asi: true */
var UNDEFINED = {}
var FALSE = {}

function lz(list) {
  this.fn = []
  this.i = 0
  this.length = list.length

  this.list = list

  if (!(this instanceof lz)) {
    return new lz(list)
  }
}

Object.defineProperty(Array.prototype, 'lz', {
  value: function () {
    return new lz(this)
  },
  enumerable: false
})

lz.prototype.$ = lz.prototype.toArray = function () {
  if (this._value) {
    return this._value
  }

  var results = []
  var item
  var n = this.length

  while (n > 0) {
    item = this.next()
    if (item === UNDEFINED) break
    results.push(item)
    n -= 1
  }

  this._value = results

  return results
}

lz.prototype.cycle = function () {
  return lz.cycle(this.list)
}

lz.prototype.drop = function (n) {
  this._value = null
  var item

  while (n > 0) {
    item = this.next()
    if (item === UNDEFINED) {
      this._value = []
      return this
    }
    n -= 1
  }

  this.list = this.list.slice(this.i)

  // partial reset
  this.i = 0
  this.length = this.list.length

  return this
}

lz.prototype.dropWhile = function (fn) {
  this._value = null
  var item

  while (true) {
    item = this.next()
    if (item === UNDEFINED) {
      this._value = []
      return this
    }
    if (fn(item) === false) break
  }

  this.list = this.list.slice(this.i - 1)

  // partial reset
  this.i = 0
  this.length = this.list.length

  return this
}

lz.prototype.filter = function (f) {
  this._value = null
  this.fn.push(function (x) {
    if (f(x) === true) return x
    else return FALSE
  })
  return this
}

lz.prototype.init = function () {
  var results = []
  var item
  var n = this.length

  while (n > 0) {
    item = this.next()
    if (item === UNDEFINED) break
    results.push(item)
    n -= 1
  }

  results.pop()

  this.list = this._value = results

  // reset
  this.fn = []
  this.i = 0
  this.length = this.list.length

  return this
}

lz.prototype.map = function (f) {
  this._value = null
  this.fn.push(function (x) { return f(x) })
  return this
}

lz.prototype.next = function () {
  var item = this.list[this.i++]
  if (this.i > this.length) return UNDEFINED
  for (var j = 0; j < this.fn.length; j += 1) {
    item = this.fn[j](item)
    if (item === FALSE) return this.next()
  }
  return item
}

lz.prototype.prev = function () {
  var item = this.list[--this.i]
  if (this.i === -1) return UNDEFINED
  for (var j = 0; j < this.fn.length; j += 1) {
    item = this.fn[j](item)
    if (item === FALSE) return this.prev()
  }
  return item
}

lz.prototype.tail = function () {
  var results = []
  var item
  var n = this.length

  while (n > 0) {
    item = this.next()
    if (item === UNDEFINED) break
    results.push(item)
    n -= 1
  }

  results.shift()

  this.list = this._value = results

  // reset
  this.fn = []
  this.i = 0
  this.length = this.list.length

  return this
}

lz.prototype.take = function (n) {
  var results = []
  var item

  while (n > 0) {
    item = this.next()
    if (item === UNDEFINED) break
    results.push(item)
    n -= 1
  }

  this.list = this._value = results

  // reset
  this.fn = []
  this.i = 0
  this.length = this.list.length

  return this
}

lz.prototype.takeWhile = function (fn) {
  var results = []
  var result
  var item

  while (true) {
    item = this.next()
    if (item === UNDEFINED) break
    result = fn(item)
    if (result === true) results.push(item)
    else break
  }

  this.list = this._value = results

  // reset
  this.fn = []
  this.i = 0
  this.length = this.list.length

  return this
}

lz.prototype.zipWith = function (fn, list) {
  return lz.zipWith(fn, list, this.list)
}

// @value
lz.prototype.and = function () {
  var item

  while (true) {
    item = this.next()
    if (item === false) return false
    if (item === UNDEFINED) break
  }

  return true
}

// @value
lz.prototype.all = function (fn) {
  var item

  while (true) {
    item = this.next()
    if (fn(item) === false) return false
    if (item === UNDEFINED) break
  }

  return true
}

// @value
lz.prototype.any = function (fn) {
  var item

  while (true) {
    item = this.next()
    if (fn(item) === true) return true
    if (item === UNDEFINED) break
  }

  return false
}

// @value
lz.prototype.foldl = function (fn) {
  var result, next
  result = this.next()
  if (result === UNDEFINED) return null
  while (true) {
    next = this.next()
    if (next === UNDEFINED) break
    result = fn(result, next)
  }
  return result
}

// @value
lz.prototype.elem = function (n) {
  var item
  while (true) {
    item = this.next()
    if (item === UNDEFINED) break
    if (item === n) return true
  }
  return false
}

// @value
lz.prototype.head = function () {
  var item
  return (item = this.next()) === UNDEFINED ? null : item
}

// @value
lz.prototype.last = function () {
  var item
  this.i = this.length
  return (item = this.prev()) === UNDEFINED ? null : item
}

// @value
lz.prototype.nil = function () {
  if (this.length === 0) return true

  while (true) {
    item = this.next()
    if (item != null) return false
    if (item === UNDEFINED) break
  }

  return true
}

// @value
lz.prototype.or = function () {
  var item

  while (true) {
    item = this.next()
    if (item === true) return true
    if (item === UNDEFINED) break
  }

  return false
}

lz.cycle = function (list) {
  var z = new lz(list)
  var length = list.length
  z.length = Infinity
  z._next = z.next
  z.next = function () {
    if (this.i === length) {
      this.i = 0
    }
    return this._next()
  }
  return z
}

lz.range = function (start, end) {
  var i = new lz([])
  i.length = end
  i._next = i.next
  i.next = function () {
    this.list.push(this.i + start)
    return i._next()
  }
  return i
}

lz.repeat = function (n) {
  var z = new lz([])
  z.length = Infinity
  z._next = z.next
  z.next = function () {
    this.list.push(n)
    return this._next()
  }
  return z
}

lz.replicate = function (times, n) {
  var z = new lz([])
  z.length = times
  z._next = z.next
  z.next = function () {
    this.list.push(n)
    return this._next()
  }
  return z
}

lz.zipWith = function (fn, list1, list2) {
  var z = new lz([])
  z.length = list1.length < list2.length ? list1.length : list2.length

  if (!(list1 instanceof lz) && !(list2 instanceof lz)) {
    z.next = function () {
      if (this.i >= this.length) return UNDEFINED
      return fn(list1[this.i], list2[this.i++])
    }
    return z
  } else {
    if (!(list1 instanceof lz)) list1 = lz(list1)
    if (!(list2 instanceof lz)) list2 = lz(list2)
    z._next = z.next
    z.next = function () {
      this.list.push(fn(list1.next(), list2.next()))
      return this._next()
    }
    return z
  }
}

module.exports = lz
<commit_msg>Adds a scanl prototype method<commit_after>/*jshint asi: true */
var UNDEFINED = {}
var FALSE = {}

function lz(list) {
  this.fn = []
  this.i = 0
  this.length = list.length

  this.list = list

  if (!(this instanceof lz)) {
    return new lz(list)
  }
}

Object.defineProperty(Array.prototype, 'lz', {
  value: function () {
    return new lz(this)
  },
  enumerable: false
})

lz.prototype.$ = lz.prototype.toArray = function () {
  if (this._value) {
    return this._value
  }

  var results = []
  var item
  var n = this.length

  while (n > 0) {
    item = this.next()
    if (item === UNDEFINED) break
    results.push(item)
    n -= 1
  }

  this._value = results

  return results
}

lz.prototype.cycle = function () {
  return lz.cycle(this.list)
}

lz.prototype.drop = function (n) {
  this._value = null
  var item

  while (n > 0) {
    item = this.next()
    if (item === UNDEFINED) {
      this._value = []
      return this
    }
    n -= 1
  }

  this.list = this.list.slice(this.i)

  // partial reset
  this.i = 0
  this.length = this.list.length

  return this
}

lz.prototype.dropWhile = function (fn) {
  this._value = null
  var item

  while (true) {
    item = this.next()
    if (item === UNDEFINED) {
      this._value = []
      return this
    }
    if (fn(item) === false) break
  }

  this.list = this.list.slice(this.i - 1)

  // partial reset
  this.i = 0
  this.length = this.list.length

  return this
}

lz.prototype.filter = function (f) {
  this._value = null
  this.fn.push(function (x) {
    if (f(x) === true) return x
    else return FALSE
  })
  return this
}

lz.prototype.init = function () {
  var results = []
  var item
  var n = this.length

  while (n > 0) {
    item = this.next()
    if (item === UNDEFINED) break
    results.push(item)
    n -= 1
  }

  results.pop()

  this.list = this._value = results

  // reset
  this.fn = []
  this.i = 0
  this.length = this.list.length

  return this
}

lz.prototype.map = function (f) {
  this._value = null
  this.fn.push(function (x) { return f(x) })
  return this
}

lz.prototype.next = function () {
  var item = this.list[this.i++]
  if (this.i > this.length) return UNDEFINED
  for (var j = 0; j < this.fn.length; j += 1) {
    item = this.fn[j](item)
    if (item === FALSE) return this.next()
  }
  return item
}

lz.prototype.prev = function () {
  var item = this.list[--this.i]
  if (this.i === -1) return UNDEFINED
  for (var j = 0; j < this.fn.length; j += 1) {
    item = this.fn[j](item)
    if (item === FALSE) return this.prev()
  }
  return item
}

lz.prototype.scanl = function (fn) {
  this._value = null
  var prev
  this.fn.push(function (x) { return (prev = fn(prev, x) || x) })
  return this
}

lz.prototype.tail = function () {
  var results = []
  var item
  var n = this.length

  while (n > 0) {
    item = this.next()
    if (item === UNDEFINED) break
    results.push(item)
    n -= 1
  }

  results.shift()

  this.list = this._value = results

  // reset
  this.fn = []
  this.i = 0
  this.length = this.list.length

  return this
}

lz.prototype.take = function (n) {
  var results = []
  var item

  while (n > 0) {
    item = this.next()
    if (item === UNDEFINED) break
    results.push(item)
    n -= 1
  }

  this.list = this._value = results

  // reset
  this.fn = []
  this.i = 0
  this.length = this.list.length

  return this
}

lz.prototype.takeWhile = function (fn) {
  var results = []
  var result
  var item

  while (true) {
    item = this.next()
    if (item === UNDEFINED) break
    result = fn(item)
    if (result === true) results.push(item)
    else break
  }

  this.list = this._value = results

  // reset
  this.fn = []
  this.i = 0
  this.length = this.list.length

  return this
}

lz.prototype.zipWith = function (fn, list) {
  return lz.zipWith(fn, list, this.list)
}

// @value
lz.prototype.and = function () {
  var item

  while (true) {
    item = this.next()
    if (item === false) return false
    if (item === UNDEFINED) break
  }

  return true
}

// @value
lz.prototype.all = function (fn) {
  var item

  while (true) {
    item = this.next()
    if (fn(item) === false) return false
    if (item === UNDEFINED) break
  }

  return true
}

// @value
lz.prototype.any = function (fn) {
  var item

  while (true) {
    item = this.next()
    if (fn(item) === true) return true
    if (item === UNDEFINED) break
  }

  return false
}

// @value
lz.prototype.foldl = function (fn) {
  var result, next
  result = this.next()
  if (result === UNDEFINED) return null
  while (true) {
    next = this.next()
    if (next === UNDEFINED) break
    result = fn(result, next)
  }
  return result
}

// @value
lz.prototype.elem = function (n) {
  var item
  while (true) {
    item = this.next()
    if (item === UNDEFINED) break
    if (item === n) return true
  }
  return false
}

// @value
lz.prototype.head = function () {
  var item
  return (item = this.next()) === UNDEFINED ? null : item
}

// @value
lz.prototype.last = function () {
  var item
  this.i = this.length
  return (item = this.prev()) === UNDEFINED ? null : item
}

// @value
lz.prototype.nil = function () {
  if (this.length === 0) return true

  while (true) {
    item = this.next()
    if (item != null) return false
    if (item === UNDEFINED) break
  }

  return true
}

// @value
lz.prototype.or = function () {
  var item

  while (true) {
    item = this.next()
    if (item === true) return true
    if (item === UNDEFINED) break
  }

  return false
}

lz.cycle = function (list) {
  var z = new lz(list)
  var length = list.length
  z.length = Infinity
  z._next = z.next
  z.next = function () {
    if (this.i === length) {
      this.i = 0
    }
    return this._next()
  }
  return z
}

lz.range = function (start, end) {
  var i = new lz([])
  i.length = end
  i._next = i.next
  i.next = function () {
    this.list.push(this.i + start)
    return i._next()
  }
  return i
}

lz.repeat = function (n) {
  var z = new lz([])
  z.length = Infinity
  z._next = z.next
  z.next = function () {
    this.list.push(n)
    return this._next()
  }
  return z
}

lz.replicate = function (times, n) {
  var z = new lz([])
  z.length = times
  z._next = z.next
  z.next = function () {
    this.list.push(n)
    return this._next()
  }
  return z
}

lz.zipWith = function (fn, list1, list2) {
  var z = new lz([])
  z.length = list1.length < list2.length ? list1.length : list2.length

  if (!(list1 instanceof lz) && !(list2 instanceof lz)) {
    z.next = function () {
      if (this.i >= this.length) return UNDEFINED
      return fn(list1[this.i], list2[this.i++])
    }
    return z
  } else {
    if (!(list1 instanceof lz)) list1 = lz(list1)
    if (!(list2 instanceof lz)) list2 = lz(list2)
    z._next = z.next
    z.next = function () {
      this.list.push(fn(list1.next(), list2.next()))
      return this._next()
    }
    return z
  }
}

module.exports = lz
<|endoftext|>


<commit_before>/**
 * Created by daniel on 2015-08-11.
 */
(function () {
    'use strict';

    angular
        .module('app.itemEditor')
        .controller('ItemEditorController', ItemEditorController);

    ItemEditorController.$inject = ['$timeout', 'itemService', '$scope', 'dialogs', 'dashboardService', 'spServicesService'];
    /* @ngInject */
    function ItemEditorController($timeout, itemService, $scope, dialogs, dashboardService, spServicesService) {
        var vm = this;
        vm.widget = $scope.$parent.widget;
        vm.editor = null;
        vm.editorLoaded = editorLoaded;
        vm.setMode = setMode;
        vm.modes = ['tree', 'code'];
        vm.search = function() {vm.editor.search(vm.editor.searchBox.dom.search.value);};
        vm.options = {
            mode: 'tree'
        };
        vm.numberOfErrors = 0;
        vm.itemService = itemService;
        vm.save = save;
        vm.change = change;
        vm.inSync = true;
        vm.unSync = unSync;
        vm.showDetail = false;
        vm.transformService = "";

        activate();

        function activate() {
            if(vm.widget.storage === undefined) {
                resetWidgetStorage();
            }
            $scope.$on('closeRequest', function() {
                if (vm.widget.storage.atLeastOneItemChanged) {
                    var dialog = dialogs.confirm('Confirm close','You have unsaved changes. Do you still want to close?');
                    dialog.result.then(function(){
                        dashboardService.closeWidget(vm.widget.id);
                    });
                } else {
                    dashboardService.closeWidget(vm.widget.id);
                }
            });
            listenToChanges();

            vm.widget.storage.data = {};
        }

        function resetWidgetStorage() {
            vm.widget.storage = {
                data: {},
                itemChanged: {},
                atLeastOneItemChanged: false
            };
        }

        function editorLoaded(editorInstance) {
            vm.editor = editorInstance;
            editorInstance.setName('Selected items');
            actOnSelectionChanges();
            $scope.$on('itemUpdate', function() {change();});
        }

        function actOnSelectionChanges() {
            $scope.$watchCollection(
                function() {
                    return itemService.selected;
                },
                function(nowSelected, previouslySelected) {
                    if (vm.inSync && !vm.widget.storage.atLeastOneItemChanged) {
                        var isSame = (nowSelected.length == previouslySelected.length) && nowSelected.every(function (element, index) {
                              return element === previouslySelected[index];
                          });
                        if (!isSame) {
                            var selected = {};
                            for (var i = 0; i < nowSelected.length; i++) {
                                var item = nowSelected[i];
                                selected[item.name] = item;
                            }
                            vm.widget.storage.data = selected;
                        }
                    }
                }
            );
        }

        function change() {
            if (vm.inSync) {
                var keys = Object.keys(vm.widget.storage.data);
                var atLeastOneItemChanged = false;
                for (var i = 0; i < keys.length; i++) {
                    var key = keys[i];
                    if (vm.widget.storage.data.hasOwnProperty(key)) {
                        var editorItem = vm.widget.storage.data[key];
                        var centralItem = itemService.getItem(editorItem.id);
                        var equal = _.isEqual(editorItem, centralItem);
                        vm.widget.storage.itemChanged[editorItem.id] = !equal;
                        if (!equal) {
                            atLeastOneItemChanged = true;
                        }
                    }
                }
                vm.widget.storage.atLeastOneItemChanged = atLeastOneItemChanged;
            } else {

            }
        }
        function save() {
            if (vm.inSync) {
                var keys = Object.keys(vm.widget.storage.data);
                for (var i = 0; i < keys.length; i++) {
                    var key = keys[i];
                    if (vm.widget.storage.data.hasOwnProperty(key)) {
                        var editorItem = vm.widget.storage.data[key];
                        var centralItem = itemService.getItem(editorItem.id);
                        if (!_.isEqual(editorItem, centralItem)) {
                            //angular.extend(centralItem, editorItem);
                            itemService.saveItem(editorItem);
                        }
                    }
                }
                vm.widget.storage.atLeastOneItemChanged = false;
            } else {
                console.log("call service")
                spServicesService.callService(spServicesService.getService(vm.transformService), {data: vm.widget.storage.data}, response)
            }
            function response(event){
                vm.widget.storage.data = event;
            }
        }
        function setMode(mode) {
            vm.options.mode = mode;
            if (mode === 'code') {
                $timeout(function() {
                    vm.editor.editor.setOptions({maxLines: Infinity});
                    vm.editor.editor.on('change', function() {
                        $timeout(function() {
                            vm.numberOfErrors = vm.editor.editor.getSession().getAnnotations().length;
                        }, 300);
                    });
                });
            }
        }

        function listenToChanges() {
            $scope.$on('itemsFetch', function() {
                if (vm.inSync) {
                    resetWidgetStorage();
                }
            });
        }

        function unSync(){
            vm.widget.storage.atLeastOneItemChanged = true;
        }
    }
})();
<commit_msg>Make item editor load selected items on widget open<commit_after>/**
 * Created by daniel on 2015-08-11.
 */
(function () {
    'use strict';

    angular
        .module('app.itemEditor')
        .controller('ItemEditorController', ItemEditorController);

    ItemEditorController.$inject = ['$timeout', 'itemService', '$scope', 'dialogs', 'dashboardService', 'spServicesService'];
    /* @ngInject */
    function ItemEditorController($timeout, itemService, $scope, dialogs, dashboardService, spServicesService) {
        var vm = this;
        vm.widget = $scope.$parent.widget;
        vm.editor = null;
        vm.editorLoaded = editorLoaded;
        vm.setMode = setMode;
        vm.modes = ['tree', 'code'];
        vm.search = function() {vm.editor.search(vm.editor.searchBox.dom.search.value);};
        vm.options = {
            mode: 'tree'
        };
        vm.numberOfErrors = 0;
        vm.itemService = itemService;
        vm.save = save;
        vm.change = change;
        vm.inSync = true;
        vm.unSync = unSync;
        vm.showDetail = false;
        vm.transformService = "";

        activate();

        function activate() {
            if(vm.widget.storage === undefined) {
                resetWidgetStorage();
            }
            $scope.$on('closeRequest', function() {
                if (vm.widget.storage.atLeastOneItemChanged) {
                    var dialog = dialogs.confirm('Confirm close','You have unsaved changes. Do you still want to close?');
                    dialog.result.then(function(){
                        dashboardService.closeWidget(vm.widget.id);
                    });
                } else {
                    dashboardService.closeWidget(vm.widget.id);
                }
            });
            listenToChanges();

            vm.widget.storage.data = {};
        }

        function resetWidgetStorage() {
            vm.widget.storage = {
                data: {},
                itemChanged: {},
                atLeastOneItemChanged: false
            };
        }

        function editorLoaded(editorInstance) {
            vm.editor = editorInstance;
            editorInstance.setName('Selected items');
            updateSelected(itemService.selected,[]);
            actOnSelectionChanges();
            $scope.$on('itemUpdate', function() {change();});
        }

        function updateSelected(nowSelected, previouslySelected) {
            if (vm.inSync && !vm.widget.storage.atLeastOneItemChanged) {
                var isSame = (nowSelected.length == previouslySelected.length) && nowSelected.every(function (element, index) {
                    return element === previouslySelected[index];
                });
                if (!isSame) {
                    var selected = {};
                    for (var i = 0; i < nowSelected.length; i++) {
                        var item = nowSelected[i];
                        selected[item.name] = item;
                    }
                    vm.widget.storage.data = selected;
                }
            }
        }

        function actOnSelectionChanges() {
            $scope.$watchCollection(
                function() {
                    return itemService.selected;
                },
                updateSelected
            );
        }

        function change() {
            if (vm.inSync) {
                var keys = Object.keys(vm.widget.storage.data);
                var atLeastOneItemChanged = false;
                for (var i = 0; i < keys.length; i++) {
                    var key = keys[i];
                    if (vm.widget.storage.data.hasOwnProperty(key)) {
                        var editorItem = vm.widget.storage.data[key];
                        var centralItem = itemService.getItem(editorItem.id);
                        var equal = _.isEqual(editorItem, centralItem);
                        vm.widget.storage.itemChanged[editorItem.id] = !equal;
                        if (!equal) {
                            atLeastOneItemChanged = true;
                        }
                    }
                }
                vm.widget.storage.atLeastOneItemChanged = atLeastOneItemChanged;
            } else {

            }
        }
        function save() {
            if (vm.inSync) {
                var keys = Object.keys(vm.widget.storage.data);
                for (var i = 0; i < keys.length; i++) {
                    var key = keys[i];
                    if (vm.widget.storage.data.hasOwnProperty(key)) {
                        var editorItem = vm.widget.storage.data[key];
                        var centralItem = itemService.getItem(editorItem.id);
                        if (!_.isEqual(editorItem, centralItem)) {
                            //angular.extend(centralItem, editorItem);
                            itemService.saveItem(editorItem);
                        }
                    }
                }
                vm.widget.storage.atLeastOneItemChanged = false;
            } else {
                console.log("call service")
                spServicesService.callService(spServicesService.getService(vm.transformService), {data: vm.widget.storage.data}, response)
            }
            function response(event){
                vm.widget.storage.data = event;
            }
        }
        function setMode(mode) {
            vm.options.mode = mode;
            if (mode === 'code') {
                $timeout(function() {
                    vm.editor.editor.setOptions({maxLines: Infinity});
                    vm.editor.editor.on('change', function() {
                        $timeout(function() {
                            vm.numberOfErrors = vm.editor.editor.getSession().getAnnotations().length;
                        }, 300);
                    });
                });
            }
        }

        function listenToChanges() {
            $scope.$on('itemsFetch', function() {
                if (vm.inSync) {
                    resetWidgetStorage();
                }
            });
        }

        function unSync(){
            vm.widget.storage.atLeastOneItemChanged = true;
        }
    }
})();
<|endoftext|>


<commit_before>/**
 * mSupply Mobile
 * Sustainable Solutions (NZ) Ltd. 2019
 */

/**
 * Method using a factory pattern variant to get a reducer
 * for a particular page or page style.
 *
 * For a new page - create a constant object with the
 * methods from reducerMethods which are composed to create
 * a reducer. Add to PAGE_REDUCERS.
 *
 * Each key value pair in a reducer object should be in the form
 * action type: reducer function, returning a new state object
 *
 */

import {
  filterData,
  editTotalQuantity,
  focusNextCell,
  selectRow,
  deselectRow,
  deselectAll,
  focusCell,
  sortData,
  openBasicModal,
  closeBasicModal,
  addMasterListItems,
  addItem,
  editTheirRef,
  editComment,
  deleteRecordsById,
  refreshData,
  editBatchExpiry,
} from './reducerMethods';

/**
 * Used for actions that should be in all pages using a data table.
 */
const BASE_TABLE_PAGE_REDUCER = {
  focusNextCell,
  focusCell,
  sortData,
};

const customerInvoice = {
  ...BASE_TABLE_PAGE_REDUCER,
  filterData,
  editTotalQuantity,
  selectRow,
  deselectRow,
  deselectAll,
  openBasicModal,
  closeBasicModal,
  addMasterListItems,
  addItem,
  editTheirRef,
  editComment,
  deleteRecordsById,
  refreshData,
};

const customerInvoices = {
  ...BASE_TABLE_PAGE_REDUCER,
  filterData,
  selectRow,
  deselectRow,
  deselectAll,
  openBasicModal,
  closeBasicModal,
  deleteRecordsById,
};

const supplierInvoice = {
  ...BASE_TABLE_PAGE_REDUCER,
  filterData,
  selectRow,
  deselectRow,
  deselectAll,
  closeBasicModal,
  openBasicModal,
  editTheirRef,
  editComment,
  refreshData,
  addItem,
  editTotalQuantity,
  deleteRecordsById,
  editBatchExpiry,
};

const supplierRequisitions = {
  sortData,
  filterData,
  selectRow,
  deselectRow,
  openBasicModal,
  closeBasicModal,
};

const PAGE_REDUCERS = {
  customerInvoice,
  customerInvoices,
  supplierInvoice,
  supplierRequisitions,
};

const getReducer = page => {
  const reducer = PAGE_REDUCERS[page];
  return (state, action) => {
    const { type } = action;
    if (!reducer[type]) return state;
    return reducer[type](state, action);
  };
};

export default getReducer;
<commit_msg>Add deselect all to SupplierRequisitionsPage reducer<commit_after>/**
 * mSupply Mobile
 * Sustainable Solutions (NZ) Ltd. 2019
 */

/**
 * Method using a factory pattern variant to get a reducer
 * for a particular page or page style.
 *
 * For a new page - create a constant object with the
 * methods from reducerMethods which are composed to create
 * a reducer. Add to PAGE_REDUCERS.
 *
 * Each key value pair in a reducer object should be in the form
 * action type: reducer function, returning a new state object
 *
 */

import {
  filterData,
  editTotalQuantity,
  focusNextCell,
  selectRow,
  deselectRow,
  deselectAll,
  focusCell,
  sortData,
  openBasicModal,
  closeBasicModal,
  addMasterListItems,
  addItem,
  editTheirRef,
  editComment,
  deleteRecordsById,
  refreshData,
  editBatchExpiry,
} from './reducerMethods';

/**
 * Used for actions that should be in all pages using a data table.
 */
const BASE_TABLE_PAGE_REDUCER = {
  focusNextCell,
  focusCell,
  sortData,
};

const customerInvoice = {
  ...BASE_TABLE_PAGE_REDUCER,
  filterData,
  editTotalQuantity,
  selectRow,
  deselectRow,
  deselectAll,
  openBasicModal,
  closeBasicModal,
  addMasterListItems,
  addItem,
  editTheirRef,
  editComment,
  deleteRecordsById,
  refreshData,
};

const customerInvoices = {
  ...BASE_TABLE_PAGE_REDUCER,
  filterData,
  selectRow,
  deselectRow,
  deselectAll,
  openBasicModal,
  closeBasicModal,
  deleteRecordsById,
};

const supplierInvoice = {
  ...BASE_TABLE_PAGE_REDUCER,
  filterData,
  selectRow,
  deselectRow,
  deselectAll,
  closeBasicModal,
  openBasicModal,
  editTheirRef,
  editComment,
  refreshData,
  addItem,
  editTotalQuantity,
  deleteRecordsById,
  editBatchExpiry,
};

const supplierRequisitions = {
  sortData,
  filterData,
  selectRow,
  deselectRow,
  deselectAll,
  openBasicModal,
  closeBasicModal,
};

const PAGE_REDUCERS = {
  customerInvoice,
  customerInvoices,
  supplierInvoice,
  supplierRequisitions,
};

const getReducer = page => {
  const reducer = PAGE_REDUCERS[page];
  return (state, action) => {
    const { type } = action;
    if (!reducer[type]) return state;
    return reducer[type](state, action);
  };
};

export default getReducer;
<|endoftext|>


<commit_before>import { Meteor } from 'meteor/meteor';
import { ReactiveDict } from 'meteor/reactive-dict';
import { ReactiveVar } from 'meteor/reactive-var';
import { Template } from 'meteor/templating';

import Events from '/imports/api/events/events.js';

import { AddMessage } from '/imports/api/messages/methods.js';

import '/imports/ui/components/events/list/event-list.js';
import '/imports/ui/components/loading/loading.js';

import './course-events.html';

Template.courseEvents.onCreated(function() {
	var instance = this;
	var courseId = this.data.course._id;

	instance.eventSub = subs.subscribe('eventsForCourse', courseId);

	var maxEventsShown = 4;
	instance.showAllEvents = new ReactiveVar(false);

	instance.haveEvents = function() {
		return Events.findFilter({ course: courseId, start: minuteTime.get() }).count() > 0;
	};

	instance.haveMoreEvents = function() {
		return Events.findFilter({ course: courseId, start: minuteTime.get() }).count() > maxEventsShown;
	};

	instance.ongoingEvents = function() {
		return Events.findFilter({ course: courseId, ongoing: minuteTime.get() });
	};

	instance.futureEvents = function() {
		var limit = instance.showAllEvents.get() ? 0 : maxEventsShown;

		return Events.findFilter({ course: courseId, after: minuteTime.get() }, limit);
	};
});

Template.courseEvents.helpers({
	mayAdd: function() {
		return this.course.editableBy(Meteor.user());
	},

	haveEvents: function() {
		return Template.instance().haveEvents();
	},

	ongoingEvents: function() {
		return Template.instance().ongoingEvents();
	},

	haveOngoingEvents: function() {
		return Template.instance().ongoingEvents().count() > 0;
	},

	futureEvents: function() {
		return Template.instance().futureEvents();
	},

	haveFutureEvents: function() {
		return Template.instance().futureEvents().count() > 0;
	},

	haveMoreEvents: function() {
		var instance = Template.instance();
		return instance.haveMoreEvents() && (!instance.showAllEvents.get());
	},

	ready: function() {
		return Template.instance().eventSub.ready();
	}
});

Template.courseEvents.events({
	'click .js-show-all-events': function () {
		Template.instance().showAllEvents.set(true);
	},

	'scroll .js-scrollable-container': function(event, instance) {
		var scrollableContainer = instance.$('.js-scrollable-container');

		// Use dom element to get true height of clipped div
		// https://stackoverflow.com/questions/4612992/get-full-height-of-a-clipped-div#5627286
		var trueHeight = scrollableContainer[0].scrollHeight;
		var visibleHeight = scrollableContainer.height();

		// Compute height and subtract a possible deviation
		var computedHeight = trueHeight - visibleHeight - 1;

		instance.$(".fade-top ").fadeIn(200);

		if (scrollableContainer.scrollTop() === 0) {
			instance.$(".fade-top").fadeOut(200);
		} else if (scrollableContainer.scrollTop() >= computedHeight) {
			instance.$(".fade-bottom").fadeOut(200);
		} else {
			instance.$(".fade-top").fadeIn(200);
			instance.$(".fade-bottom").fadeIn(200);
		}
	}
});

Template.courseEventAdd.helpers({
	addEventQuery: function() {
		return 'courseId=' + this.course._id;
	}
});

Template.courseEventAdd.onRendered(function() {
	var instance = this;
	var eventCaption = instance.$('.event-caption-add');

	function toggleCaptionClass(e) {
		var removeClass = e.type == 'mouseout';
		eventCaption.toggleClass('placeholder', removeClass);
	}

	eventCaption.on('mouseover mouseout', function(e) { toggleCaptionClass(e); });
	instance.$('.event-caption-add-text').on('mouseover mouseout', function(e) { toggleCaptionClass(e); });
});

Template.deleteCourseEvents.helpers({
	upcomingEvents() {
		return Events.findFilter(
			{ course: this.course._id
			, after: minuteTime.get()
			}
		);
	}
});

Template.deleteCourseEvents.events({
	'click .js-show-events-delete-modal'(event, instance) {
		instance.$('#deleteEventsModal').modal('show');
	}
});

Template.deleteEventsModal.onCreated(function() {
	this.busy(false);

	this.state = new ReactiveDict();
	this.state.setDefault(
		{ selectedEvents: []
		, allEventsSelected: false
		, showDeleteConfirm: false
		}
	);

	this.autorun(() => {
		const cursor = Template.currentData().upcomingEvents;
		const allEventsSelected = cursor.count() === this.state.get('selectedEvents').length;
		this.state.set({ allEventsSelected });
	});
});

Template.deleteEventsModal.helpers({
	selectedEvents() {
		return Template.instance().state.get('selectedEvents');
	},

	isSelected() {
		return Template.instance().state.get('selectedEvents').find(e => e._id === this._id);
	},

	numSelectedEvents() {
		return Template.instance().state.get('selectedEvents').length;
	},

	disabledIfNoEventsSelected() {
		if (Template.instance().state.get('selectedEvents').length === 0) {
			return 'disabled';
		}
	}
});

Template.deleteEventsModal.events({
	'click .js-toggle-all'(event, instance) {
		let selectedEvents;
		if (instance.state.get('allEventsSelected')) {
			selectedEvents = [];
		} else {
			selectedEvents = Template.currentData().upcomingEvents.fetch();
		}

		instance.state.set({ selectedEvents });
	},

	'change input[type="checkbox"]'(event, instance) {
		let selectedEvents = instance.state.get('selectedEvents');
		if (event.target.checked) {
			selectedEvents.push(this);
		} else {
			selectedEvents = selectedEvents.filter(e => e._id !== this._id);
		}

		instance.state.set({ selectedEvents });
	},

	'click .js-show-delete-confirm'(event, instance) {
		instance.state.set('showDeleteConfirm', true);
	},

	'click .js-delete-events'(e, instance) {
		instance.busy('deleting');
		instance.state.get('selectedEvents').forEach((event, index, list) => {
			Meteor.call('event.remove', event._id, (err) => {
				if (index === list.length - 1) {
					if (err) {
						AddMessage(err.reason || 'Unknown error', 'danger');
					} else {
						AddMessage(mf(
							'deleteEventsModal.sucess',
							{ NUM: list.length },
							'{NUM, plural, one {Event was} other {# events were}} successfully deleted.'
						), 'success');
					}

					instance.busy(false);
					instance.state.set(
						{ selectedEvents: []
						, showDeleteConfirm: false
						}
					);
					instance.$('#deleteEventsModal').modal('hide');
				}
			});
		});
	},

	'click .js-cancel'(event, instance) {
		instance.state.set('showDeleteConfirm', false);
	}
});
<commit_msg>revisit error handling like supposed by @sbalmer<commit_after>import { Meteor } from 'meteor/meteor';
import { ReactiveDict } from 'meteor/reactive-dict';
import { ReactiveVar } from 'meteor/reactive-var';
import { Template } from 'meteor/templating';

import Events from '/imports/api/events/events.js';

import { AddMessage } from '/imports/api/messages/methods.js';

import '/imports/ui/components/events/list/event-list.js';
import '/imports/ui/components/loading/loading.js';

import './course-events.html';

Template.courseEvents.onCreated(function() {
	var instance = this;
	var courseId = this.data.course._id;

	instance.eventSub = subs.subscribe('eventsForCourse', courseId);

	var maxEventsShown = 4;
	instance.showAllEvents = new ReactiveVar(false);

	instance.haveEvents = function() {
		return Events.findFilter({ course: courseId, start: minuteTime.get() }).count() > 0;
	};

	instance.haveMoreEvents = function() {
		return Events.findFilter({ course: courseId, start: minuteTime.get() }).count() > maxEventsShown;
	};

	instance.ongoingEvents = function() {
		return Events.findFilter({ course: courseId, ongoing: minuteTime.get() });
	};

	instance.futureEvents = function() {
		var limit = instance.showAllEvents.get() ? 0 : maxEventsShown;

		return Events.findFilter({ course: courseId, after: minuteTime.get() }, limit);
	};
});

Template.courseEvents.helpers({
	mayAdd: function() {
		return this.course.editableBy(Meteor.user());
	},

	haveEvents: function() {
		return Template.instance().haveEvents();
	},

	ongoingEvents: function() {
		return Template.instance().ongoingEvents();
	},

	haveOngoingEvents: function() {
		return Template.instance().ongoingEvents().count() > 0;
	},

	futureEvents: function() {
		return Template.instance().futureEvents();
	},

	haveFutureEvents: function() {
		return Template.instance().futureEvents().count() > 0;
	},

	haveMoreEvents: function() {
		var instance = Template.instance();
		return instance.haveMoreEvents() && (!instance.showAllEvents.get());
	},

	ready: function() {
		return Template.instance().eventSub.ready();
	}
});

Template.courseEvents.events({
	'click .js-show-all-events': function () {
		Template.instance().showAllEvents.set(true);
	},

	'scroll .js-scrollable-container': function(event, instance) {
		var scrollableContainer = instance.$('.js-scrollable-container');

		// Use dom element to get true height of clipped div
		// https://stackoverflow.com/questions/4612992/get-full-height-of-a-clipped-div#5627286
		var trueHeight = scrollableContainer[0].scrollHeight;
		var visibleHeight = scrollableContainer.height();

		// Compute height and subtract a possible deviation
		var computedHeight = trueHeight - visibleHeight - 1;

		instance.$(".fade-top ").fadeIn(200);

		if (scrollableContainer.scrollTop() === 0) {
			instance.$(".fade-top").fadeOut(200);
		} else if (scrollableContainer.scrollTop() >= computedHeight) {
			instance.$(".fade-bottom").fadeOut(200);
		} else {
			instance.$(".fade-top").fadeIn(200);
			instance.$(".fade-bottom").fadeIn(200);
		}
	}
});

Template.courseEventAdd.helpers({
	addEventQuery: function() {
		return 'courseId=' + this.course._id;
	}
});

Template.courseEventAdd.onRendered(function() {
	var instance = this;
	var eventCaption = instance.$('.event-caption-add');

	function toggleCaptionClass(e) {
		var removeClass = e.type == 'mouseout';
		eventCaption.toggleClass('placeholder', removeClass);
	}

	eventCaption.on('mouseover mouseout', function(e) { toggleCaptionClass(e); });
	instance.$('.event-caption-add-text').on('mouseover mouseout', function(e) { toggleCaptionClass(e); });
});

Template.deleteCourseEvents.helpers({
	upcomingEvents() {
		return Events.findFilter(
			{ course: this.course._id
			, after: minuteTime.get()
			}
		);
	}
});

Template.deleteCourseEvents.events({
	'click .js-show-events-delete-modal'(event, instance) {
		instance.$('#deleteEventsModal').modal('show');
	}
});

Template.deleteEventsModal.onCreated(function() {
	this.busy(false);

	this.state = new ReactiveDict();
	this.state.setDefault(
		{ selectedEvents: []
		, allEventsSelected: false
		, showDeleteConfirm: false
		}
	);

	this.autorun(() => {
		const cursor = Template.currentData().upcomingEvents;
		const allEventsSelected = cursor.count() === this.state.get('selectedEvents').length;
		this.state.set({ allEventsSelected });
	});
});

Template.deleteEventsModal.helpers({
	selectedEvents() {
		return Template.instance().state.get('selectedEvents');
	},

	isSelected() {
		return Template.instance().state.get('selectedEvents').find(e => e._id === this._id);
	},

	numSelectedEvents() {
		return Template.instance().state.get('selectedEvents').length;
	},

	disabledIfNoEventsSelected() {
		if (Template.instance().state.get('selectedEvents').length === 0) {
			return 'disabled';
		}
	}
});

Template.deleteEventsModal.events({
	'click .js-toggle-all'(event, instance) {
		let selectedEvents;
		if (instance.state.get('allEventsSelected')) {
			selectedEvents = [];
		} else {
			selectedEvents = Template.currentData().upcomingEvents.fetch();
		}

		instance.state.set({ selectedEvents });
	},

	'change input[type="checkbox"]'(event, instance) {
		let selectedEvents = instance.state.get('selectedEvents');
		if (event.target.checked) {
			selectedEvents.push(this);
		} else {
			selectedEvents = selectedEvents.filter(e => e._id !== this._id);
		}

		instance.state.set({ selectedEvents });
	},

	'click .js-show-delete-confirm'(event, instance) {
		instance.state.set('showDeleteConfirm', true);
	},

	'click .js-delete-events'(e, instance) {
		instance.busy('deleting');

		const events = instance.state.get('selectedEvents');
		let removed = 0;
		let responses = 0;
		events.forEach((event, index) => {
			Meteor.call('event.remove', event._id, (err) => {
				responses++;
				if (err) {
					AddMessage(mf(
						'deleteEventsModal.errWithReason',
						{ REASON: err.reason || 'Unknown error'
						, TITLE: event.title
						, START: moment(event.startLocal).format('llll')
						},
						'Deleting the event "{TITLE} ({START})" failed: "{REASON}"'
					), 'danger');
				} else {
					removed++;
				}

				if (responses === events.length) {
					instance.busy(false);
					instance.state.set('showDeleteConfirm', false);
					if (removed) {
						AddMessage(mf(
							'deleteEventsModal.sucess',
							{ NUM: removed },
							'{NUM, plural, one {Event was} other {# events were}} successfully deleted.'
						), 'success');
					}
					if (removed === responses) {
						instance.state.set('selectedEvents', []);
						instance.$('#deleteEventsModal').modal('hide');
					}
				}
			});
		});
	},

	'click .js-cancel'(event, instance) {
		instance.state.set('showDeleteConfirm', false);
	}
});
<|endoftext|>