<commit_before>M.wrap('bitbucket/jillix/dms-tree/dev/tree.js', function (require, module, exports) {
var Bind = require("github/jillix/bind");
var Events = require("github/jillix/events");

var LIST_TEMPLATE_ID = "000000000000000000000004";

module.exports = function(config) {

    var DmsTree = this;
    Events.call(DmsTree, config);

    var DRAGGABLE = {
        revert: true,
        zIndex: 2500,
        start: function () {
            $(this).effect("highlight", {}, 1000);
            $(this).css("cursor", "move");
        },
        stop: function() {
            $(this).css("cursor", "default");
            $(".stack").css('z-index', '500');
        }
    };

    var storage = {};
    var currentTemplate;

    var ctrlDown = false;

    $(document).on("keydown", function (e) {
        if (e.keyCode === 17) {
            ctrlDown = true;
            console.log("> true");
        }
    }).on("keyup", function (e) {
        if (e.keyCode === 17) {
            ctrlDown = false;
            console.log("> false");
        }
    });

    ///////////////////
    // HANDLERS
    ///////////////////
    $(DmsTree.dom).on("click", ".list", function () {
        var $item = $(this).closest("li");

        DmsTree.removeActive("*");
        DmsTree.setActive($item);

        var filters = (storage[$item.attr("data-id")] || {}).filters || [];

        DmsTree.emit("setFilters", filters, true);

        return false;
    }).on("click", ".folder", function () {

        var $item = $(this);
        $item = $item.closest("li");

        if (DmsTree.isLoading($item)) { return; }

        var dataItem = storage[$item.attr("data-id")];

        if (DmsTree.folderIsOpened($item)) {
            DmsTree.closeFolder($item);
            DmsTree.collapse($item);
            return;
        }

        DmsTree.startLoading($item);

        // TODO add the template filter also for the children for correctness
        //var templateFilter;
        //for (var i in dataItem._ln) {
        //    if (dataItem._ln[i]._tp === "000000000000000000000000") {
        //        templateFilter = dataItem._ln[i];
        //    }
        //}

        var crudObj = {
            t: LIST_TEMPLATE_ID,
            q: {

            }
        };

        DmsTree.emit("find", crudObj, function (err, docs) {

            if (err) {
                alert(err);
                return;
            }

            // TODO Just simulating a timeout
            setTimeout(function () {

            DmsTree.expand($item, docs);

            DmsTree.removeActive(".dms-tree *");
            DmsTree.setActive($item);

            DmsTree.stopLoading($item);
            DmsTree.openFolder($item);
            }, 100);
        });
        return false;
    }).on("click", ".all", function () {

        DmsTree.removeActive(".dms-tree *");
        DmsTree.setActive($(this));

        DmsTree.emit("setFilters", [], true);
        return false;
    });

    ///////////////////////////////
    // Generate the tree from items
    ///////////////////////////////
    DmsTree.buildFrom = function (items) {

        var $tree = $(".dms-tree", DmsTree.dom);
        var $typeTemplates = $(".type-templates", DmsTree.dom);

        switch (Object.prototype.toString.call(items)) {
            // object
            case "[object Object]":

                currentTemplate = items;

                var crudObj = {
                    t: LIST_TEMPLATE_ID,
                    q: {
                        parent: {
                            $exists: false
                        }
                    },
                    o: {
                        sort: [["type", -1]]
                    }
                };

                // -> emit -> bind-crud -> callback -> buildFrom Array
                DmsTree.emit("find", crudObj, function (err, docs) {
                    if (err) {
                        alert(err);
                        return;
                    }

                    DmsTree.buildFrom(docs);
                });

                // count
                crudObj = {
                    t: LIST_TEMPLATE_ID,
                    q: {
                        type: {
                            $ne: "folder"
                        }
                    },
                    f: {
                        $none: 1,
                        _id: 0
                    }
                };

                DmsTree.emit("find", crudObj, function (err, docs) {
                    if (err) {
                        alert(err);
                        return;
                    }

                    var $all = $(".all-template", $typeTemplates)
                        .clone()
                        .removeClass("all-template");

                    $(".all-value", $all).text(docs.length);
                    $tree.prepend($all);
                });
                return;
            // array
            case "[object Array]":
                break;
            // other type
            default:
                return;
        }

        $tree.empty();
        storage = {};

        // an empty array
        if (!items || !items.length) { return; }

        var $itemsToAppend = $("<div>");

        for (var i in items) {
            var item = items[i];
            var $newItem = $("." + item.type + "-template", $typeTemplates).clone();

            storage[item._id] = item;

            $newItem
                .attr("data-id", item._id)
                .removeClass(item.type + "-template")
                .find(".name").text(item.name);

            $itemsToAppend.append($newItem);
        }

        $itemsToAppend.find("li").draggable(DRAGGABLE);

        $itemsToAppend.find(".folder").closest("li").droppable({
            over: DmsTree.dragAndDrop.over,
            out: DmsTree.dragAndDrop.out,
            drop: DmsTree.dragAndDrop.drop
        });

        $tree.append($itemsToAppend);
        $tree.find("li").hide().slideDown();
    };

    ///////////////////////////////
    // Set active class
    ///////////////////////////////
    DmsTree.setActive = function (jQueryElement) {
        jQueryElement = $(jQueryElement, DmsTree.dom);

        if (ctrlDown && jQueryElement.hasClass("active")) {
            jQueryElement.toggleClass("active");
        }
        else {
            jQueryElement.addClass("active");
        }

        DmsTree.emit("selectionChanged", DmsTree.getActive("item"));
    };

    DmsTree.removeActive = function (jQueryElement) {

        if (ctrlDown) { return; }

        jQueryElement = $(jQueryElement, DmsTree.dom);
        jQueryElement.removeClass("active");

        DmsTree.emit("selectionChanged", DmsTree.getActive("item"));
    };

    //////////////////////////////
    // Get active (item/element)
    //////////////////////////////
    DmsTree.getActive = function (item) {

        var jQueryElements = $(DmsTree.dom).find(".active");
        if (!jQueryElements.length) { return undefined; }

        if (item === "item") {
            var activeItems = [];

            if (jQueryElements.length === 1) {
                activeItems.push(storage[jQueryElements.attr("data-id")]);
                return activeItems
            }

            jQueryElements.each(function () {
                activeItems.push(storage[$(this).attr("data-id")]);
            })

            return activeItems;
        }

        return jQueryElements;
    };

    ///////////////////////////////
    // Open-Close functions
    ///////////////////////////////
    DmsTree.openFolder = function (jQueryElement) {

        jQueryElement = $(jQueryElement, DmsTree.dom);
        if (jQueryElement.attr("data-loading")) { return; }

        var $openClose = jQueryElement.find(".open-close");

        $openClose.children().first().addClass("hide");
        $openClose.children().last().removeClass("hide");
        jQueryElement.find(".chevron").toggleClass("icon-chevron-right icon-chevron-down");
    };

    DmsTree.closeFolder = function (jQueryElement) {
        jQueryElement = $(jQueryElement, DmsTree.dom);
        if (jQueryElement.attr("data-loading")) { return; }

        var $openClose = jQueryElement.find(".open-close");

        $openClose.children().last().addClass("hide");
        $openClose.children().first().removeClass("hide");
        jQueryElement.find(".chevron").toggleClass("icon-chevron-right icon-chevron-down");
    };

    DmsTree.folderIsOpened = function (jQueryElement) {
        jQueryElement = $(jQueryElement, DmsTree.dom);
        var $openClose = jQueryElement.find(".open-close");

        if ($openClose.children().last().hasClass("hide")) { return false; }
        return true;
    };

    ///////////////////////////////
    // Loading functions
    ///////////////////////////////
    DmsTree.startLoading = function (jQueryElement) {
        jQueryElement = $(jQueryElement, DmsTree.dom);
        var $loading = jQueryElement.find(".loading-toggle");

        $loading.children().first().removeClass("hide");
        $loading.children().last().addClass("hide");
        jQueryElement.attr("data-loading", "true");
    };

    DmsTree.stopLoading = function (jQueryElement) {
        jQueryElement = $(jQueryElement, DmsTree.dom);
        var $loading = jQueryElement.find(".loading-toggle");

        $loading.children().first().addClass("hide");
        var $last = $loading.children().last();
        $last.removeClass("hide");
        jQueryElement.attr("data-loading", "");
    };

    DmsTree.isLoading = function (jQueryElement) {
        jQueryElement = $(jQueryElement, DmsTree.dom);
        if (jQueryElement.attr("data-loading")) { return true; }
        return false;
    };

    ////////////////////
    // EXPAND / COLLAPSE
    ////////////////////
    DmsTree.expand = function (jQueryElement, docs) {

        jQueryElement = $(jQueryElement, DmsTree.dom);

        if (jQueryElement.next().prop("tagName") === "UL") { return; }

        var $ul = $("<ul>");
        for (var i in docs) {
            var doc = docs[i];
            storage[doc._id] = doc;

            var templClass = doc.type + "-template";
            var $newItem = $("." + templClass)
                            .clone()
                            .removeClass(templClass);

            $newItem.attr("data-id", doc._id)
                    .find(".name").text(doc.name);

            $ul.append($newItem);
        }

        $ul.find("li").draggable(DRAGGABLE);

        $(".folder", $ul).closest("li").droppable({
            over: DmsTree.dragAndDrop.over,
            out: DmsTree.dragAndDrop.out,
            drop: DmsTree.dragAndDrop.drop
        });

        jQueryElement.after($ul);
        $ul.hide().slideDown();
    };

    DmsTree.collapse = function (jQueryElement) {
        jQueryElement = $(jQueryElement, DmsTree.dom);
        var folderContent = jQueryElement.next();
        folderContent.slideUp(function () {
            folderContent.remove();
        });
    };

    //////////////////////
    // NEW LIST/NEW FOLDER
    //////////////////////
    DmsTree.newList = function (listObj, callback) {

        if (!currentTemplate) { return alert("Select a template, first."); }

        DmsTree.emit("getFilters", function (filters) {

            // TODO This will be removed when getFilters will not send dom references
            for (var i in filters) {
                delete filters[i].item;
                delete filters[i].hash;
            }

            listObj.filters = filters;
            listObj._ln = [
                {
                    _tp: "000000000000000000000002",
                    _id: currentTemplate._id
                }
            ];

            // TODO Parent???

            var crudObj = {
                t: "000000000000000000000002",
                d: listObj
            };

            DmsTree.emit("insert", crudObj, function (err, insertedDoc) {

                closeModals();

                if (err) {
                    alert(err);
                    return;
                }

                if (callback) { callback(err, insertedDoc); }
                DmsTree.emit("refresh");
            });
        });
    };

    //////////////////////
    // EDIT LIST
    //////////////////////
    DmsTree.editList = function (listObj, callback) {

        var activeItem = DmsTree.getActive("item")[0];

        for (var key in listObj) {
            activeItem[key] = listObj[key];
        }

        var newItem = JSON.parse(JSON.stringify(activeItem));
        delete newItem._id;

        DmsTree.emit("getFilters", function (filters) {

            // TODO This will be removed when getFilters will not send dom references
            for (var i in filters) {
                delete filters[i].item;
                delete filters[i].hash;
            }

            newItem.filters = filters;

            var crudObj = {
                t: "000000000000000000000002",
                q: {
                    _id: activeItem._id
                },
                d: newItem
            };

            DmsTree.emit("update", crudObj, function (err) {

                closeModals();
                if (err) { return alert(err); }

                DmsTree.emit("refresh");
            });
        });
    };

    //////////////////////
    // Delete LIST
    //////////////////////
    DmsTree.deleteList = function () {

        var activeItems = DmsTree.getActive("item");
        if (!activeItems || !activeItems.length) { return alert("No list selected."); }

        // var _ids = [];

        // for (var i in activeItems) {
        //     _ids.push(activeItems[i]._id);
        // }

        // TODO Until bind-crud #5 is fixed :: https://github.com/jillix/bind-crud/issues/5
        // var crudObj = {
        //     t: "_list",
        //     q: { _id: {
        //             $in: _ids
        //         }
        //     }
        // };

        var counter = 0;
        for (var i in activeItems) {

            var crudObj = {
                t: "000000000000000000000002",
                q: {
                    _id: activeItems[i]._id
                }
            };

            DmsTree.emit("remove", crudObj, function (err) {

                closeModals();

                if (err) { return alert(err); }
                if (++counter === activeItems.length) {
                    DmsTree.getActive().slideUp(function () {
                        $(this).remove();
                    });
                }
            });
        }

        // DmsTree.emit("remove", crudObj, function (err) {
        //     if (err) { return alert(err); }
        //     DmsTree.emit("buildFrom", currentTemplate);
        // });
    };

    ////////////////////////////
    // Drag and drop
    ///////////////////////////
    DmsTree.dragAndDrop = {
        over: function () {
            $(this).addClass("over");
        },
        out: function () {
            $(this).removeClass("over");
        },
        drop: function () {
            $(this).removeClass("over");
        }
    };

    function closeModals() {
        try {
            $(".modal").modal("hide");
        } catch (e) {}
    }

    DmsTree.emit("ready", config);
    DmsTree.on("refresh", function () {
        DmsTree.buildFrom(currentTemplate);
    });
};

return module; });
<commit_msg>Cleanup.<commit_after>M.wrap('bitbucket/jillix/dms-tree/dev/tree.js', function (require, module, exports) {
var Bind = require("github/jillix/bind");
var Events = require("github/jillix/events");

var LIST_TEMPLATE_ID = "000000000000000000000004";

module.exports = function(config) {

    var DmsTree = this;
    Events.call(DmsTree, config);

    var DRAGGABLE = {
        revert: true,
        zIndex: 2500,
        start: function () {
            $(this).effect("highlight", {}, 1000);
            $(this).css("cursor", "move");
        },
        stop: function() {
            $(this).css("cursor", "default");
            $(".stack").css('z-index', '500');
        }
    };

    var storage = {};
    var currentTemplate;

    var ctrlDown = false;

    $(document).on("keydown", function (e) {
        if (e.keyCode === 17) {
            ctrlDown = true;
            console.log("> true");
        }
    }).on("keyup", function (e) {
        if (e.keyCode === 17) {
            ctrlDown = false;
            console.log("> false");
        }
    });

    ///////////////////
    // HANDLERS
    ///////////////////
    $(DmsTree.dom).on("click", ".list", function () {
        var $item = $(this).closest("li");

        DmsTree.removeActive("*");
        DmsTree.setActive($item);

        var filters = (storage[$item.attr("data-id")] || {}).filters || [];

        DmsTree.emit("setFilters", filters, true);

        return false;
    }).on("click", ".folder", function () {

        var $item = $(this);
        $item = $item.closest("li");

        if (DmsTree.isLoading($item)) { return; }

        var dataItem = storage[$item.attr("data-id")];

        if (DmsTree.folderIsOpened($item)) {
            DmsTree.closeFolder($item);
            DmsTree.collapse($item);
            return;
        }

        DmsTree.startLoading($item);

        // TODO add the template filter also for the children for correctness
        //var templateFilter;
        //for (var i in dataItem._ln) {
        //    if (dataItem._ln[i]._tp === "000000000000000000000000") {
        //        templateFilter = dataItem._ln[i];
        //    }
        //}

        var crudObj = {
            t: LIST_TEMPLATE_ID,
            q: {}
        };

        DmsTree.emit("find", crudObj, function (err, docs) {

            if (err) {
                alert(err);
                return;
            }

            // TODO Just simulating a timeout
            setTimeout(function () {

            DmsTree.expand($item, docs);

            DmsTree.removeActive(".dms-tree *");
            DmsTree.setActive($item);

            DmsTree.stopLoading($item);
            DmsTree.openFolder($item);
            }, 100);
        });
        return false;
    }).on("click", ".all", function () {

        DmsTree.removeActive(".dms-tree *");
        DmsTree.setActive($(this));

        DmsTree.emit("setFilters", [], true);
        return false;
    });

    ///////////////////////////////
    // Generate the tree from items
    ///////////////////////////////
    DmsTree.buildFrom = function (items) {

        var $tree = $(".dms-tree", DmsTree.dom);
        var $typeTemplates = $(".type-templates", DmsTree.dom);

        switch (Object.prototype.toString.call(items)) {
            // object
            case "[object Object]":

                currentTemplate = items;

                var crudObj = {
                    t: LIST_TEMPLATE_ID,
                    q: {
                        parent: {
                            $exists: false
                        }
                    },
                    o: {
                        sort: [["type", -1]]
                    }
                };

                // -> emit -> bind-crud -> callback -> buildFrom Array
                DmsTree.emit("find", crudObj, function (err, docs) {
                    if (err) {
                        alert(err);
                        return;
                    }

                    DmsTree.buildFrom(docs);
                });

                return;
            // array
            case "[object Array]":
                break;
            // other type
            default:
                return;
        }

        $tree.empty();

        // count
        crudObj = {
            t: LIST_TEMPLATE_ID,
            q: { type: { $ne: "folder" } },
            f: { $none: 1, _id: 0 }
        };

        DmsTree.emit("find", crudObj, function (err, docs) {
            if (err) {
                alert(err);
                return;
            }

            var $all = $(".all-template", $typeTemplates)
                .clone()
                .removeClass("all-template");

            $(".all-value", $all).text(docs.length);
            $tree.prepend($all);
        });

        storage = {};

        // an empty array
        if (!items || !items.length) { return; }

        var $itemsToAppend = $("<div>");

        for (var i in items) {
            var item = items[i];
            var $newItem = $("." + item.type + "-template", $typeTemplates).clone();

            storage[item._id] = item;

            $newItem
                .attr("data-id", item._id)
                .removeClass(item.type + "-template")
                .find(".name").text(item.name);

            $itemsToAppend.append($newItem);
        }

        $itemsToAppend.find("li").draggable(DRAGGABLE);

        $itemsToAppend.find(".folder").closest("li").droppable({
            over: DmsTree.dragAndDrop.over,
            out: DmsTree.dragAndDrop.out,
            drop: DmsTree.dragAndDrop.drop
        });

        $tree.append($itemsToAppend);
        $tree.find("li").hide().slideDown();
    };

    ///////////////////////////////
    // Set active class
    ///////////////////////////////
    DmsTree.setActive = function (jQueryElement) {
        jQueryElement = $(jQueryElement, DmsTree.dom);

        if (ctrlDown && jQueryElement.hasClass("active")) {
            jQueryElement.toggleClass("active");
        }
        else {
            jQueryElement.addClass("active");
        }

        DmsTree.emit("selectionChanged", DmsTree.getActive("item"));
    };

    DmsTree.removeActive = function (jQueryElement) {

        if (ctrlDown) { return; }

        jQueryElement = $(jQueryElement, DmsTree.dom);
        jQueryElement.removeClass("active");

        DmsTree.emit("selectionChanged", DmsTree.getActive("item"));
    };

    //////////////////////////////
    // Get active (item/element)
    //////////////////////////////
    DmsTree.getActive = function (item) {

        var jQueryElements = $(DmsTree.dom).find(".active");
        if (!jQueryElements.length) { return undefined; }

        if (item === "item") {
            var activeItems = [];

            if (jQueryElements.length === 1) {
                activeItems.push(storage[jQueryElements.attr("data-id")]);
                return activeItems
            }

            jQueryElements.each(function () {
                activeItems.push(storage[$(this).attr("data-id")]);
            })

            return activeItems;
        }

        return jQueryElements;
    };

    ///////////////////////////////
    // Open-Close functions
    ///////////////////////////////
    DmsTree.openFolder = function (jQueryElement) {

        jQueryElement = $(jQueryElement, DmsTree.dom);
        if (jQueryElement.attr("data-loading")) { return; }

        var $openClose = jQueryElement.find(".open-close");

        $openClose.children().first().addClass("hide");
        $openClose.children().last().removeClass("hide");
        jQueryElement.find(".chevron").toggleClass("icon-chevron-right icon-chevron-down");
    };

    DmsTree.closeFolder = function (jQueryElement) {
        jQueryElement = $(jQueryElement, DmsTree.dom);
        if (jQueryElement.attr("data-loading")) { return; }

        var $openClose = jQueryElement.find(".open-close");

        $openClose.children().last().addClass("hide");
        $openClose.children().first().removeClass("hide");
        jQueryElement.find(".chevron").toggleClass("icon-chevron-right icon-chevron-down");
    };

    DmsTree.folderIsOpened = function (jQueryElement) {
        jQueryElement = $(jQueryElement, DmsTree.dom);
        var $openClose = jQueryElement.find(".open-close");

        if ($openClose.children().last().hasClass("hide")) { return false; }
        return true;
    };

    ///////////////////////////////
    // Loading functions
    ///////////////////////////////
    DmsTree.startLoading = function (jQueryElement) {
        jQueryElement = $(jQueryElement, DmsTree.dom);
        var $loading = jQueryElement.find(".loading-toggle");

        $loading.children().first().removeClass("hide");
        $loading.children().last().addClass("hide");
        jQueryElement.attr("data-loading", "true");
    };

    DmsTree.stopLoading = function (jQueryElement) {
        jQueryElement = $(jQueryElement, DmsTree.dom);
        var $loading = jQueryElement.find(".loading-toggle");

        $loading.children().first().addClass("hide");
        var $last = $loading.children().last();
        $last.removeClass("hide");
        jQueryElement.attr("data-loading", "");
    };

    DmsTree.isLoading = function (jQueryElement) {
        jQueryElement = $(jQueryElement, DmsTree.dom);
        if (jQueryElement.attr("data-loading")) { return true; }
        return false;
    };

    ////////////////////
    // EXPAND / COLLAPSE
    ////////////////////
    DmsTree.expand = function (jQueryElement, docs) {

        jQueryElement = $(jQueryElement, DmsTree.dom);

        if (jQueryElement.next().prop("tagName") === "UL") { return; }

        var $ul = $("<ul>");
        for (var i in docs) {
            var doc = docs[i];
            storage[doc._id] = doc;

            var templClass = doc.type + "-template";
            var $newItem = $("." + templClass)
                            .clone()
                            .removeClass(templClass);

            $newItem.attr("data-id", doc._id)
                    .find(".name").text(doc.name);

            $ul.append($newItem);
        }

        $ul.find("li").draggable(DRAGGABLE);

        $(".folder", $ul).closest("li").droppable({
            over: DmsTree.dragAndDrop.over,
            out: DmsTree.dragAndDrop.out,
            drop: DmsTree.dragAndDrop.drop
        });

        jQueryElement.after($ul);
        $ul.hide().slideDown();
    };

    DmsTree.collapse = function (jQueryElement) {
        jQueryElement = $(jQueryElement, DmsTree.dom);
        var folderContent = jQueryElement.next();
        folderContent.slideUp(function () {
            folderContent.remove();
        });
    };

    //////////////////////
    // NEW LIST/NEW FOLDER
    //////////////////////
    DmsTree.newList = function (listObj, callback) {

        if (!currentTemplate) { return alert("Select a template, first."); }

        DmsTree.emit("getFilters", function (filters) {

            listObj.filters = filters;
            listObj._ln = [
                {
                    _tp: "000000000000000000000002",
                    _id: currentTemplate._id
                }
            ];

            // TODO Parent???

            var crudObj = {
                t: "000000000000000000000002",
                d: listObj
            };

            DmsTree.emit("insert", crudObj, function (err, insertedDoc) {

                closeModals();

                if (err) {
                    alert(err);
                    return;
                }

                if (callback) { callback(err, insertedDoc); }
                DmsTree.emit("refresh");
            });
        });
    };

    //////////////////////
    // EDIT LIST
    //////////////////////
    DmsTree.editList = function (listObj, callback) {

        var activeItem = DmsTree.getActive("item")[0];

        for (var key in listObj) {
            activeItem[key] = listObj[key];
        }

        var newItem = JSON.parse(JSON.stringify(activeItem));
        delete newItem._id;

        DmsTree.emit("getFilters", function (filters) {

            newItem.filters = filters;

            var crudObj = {
                t: "000000000000000000000002",
                q: {
                    _id: activeItem._id
                },
                d: newItem
            };

            DmsTree.emit("update", crudObj, function (err) {

                closeModals();
                if (err) { return alert(err); }

                DmsTree.emit("refresh");
            });
        });
    };

    //////////////////////
    // Delete LIST
    //////////////////////
    DmsTree.deleteList = function () {

        var activeItems = DmsTree.getActive("item");
        if (!activeItems || !activeItems.length) { return alert("No list selected."); }

        // var _ids = [];

        // for (var i in activeItems) {
        //     _ids.push(activeItems[i]._id);
        // }

        // TODO Until bind-crud #5 is fixed :: https://github.com/jillix/bind-crud/issues/5
        // var crudObj = {
        //     t: "_list",
        //     q: { _id: {
        //             $in: _ids
        //         }
        //     }
        // };

        var counter = 0;
        for (var i in activeItems) {

            var crudObj = {
                t: "000000000000000000000002",
                q: {
                    _id: activeItems[i]._id
                }
            };

            DmsTree.emit("remove", crudObj, function (err) {

                closeModals();

                if (err) { return alert(err); }
                if (++counter === activeItems.length) {
                    DmsTree.getActive().slideUp(function () {
                        $(this).remove();
                    });
                }
            });
        }

        // DmsTree.emit("remove", crudObj, function (err) {
        //     if (err) { return alert(err); }
        //     DmsTree.emit("buildFrom", currentTemplate);
        // });
    };

    ////////////////////////////
    // Drag and drop
    ///////////////////////////
    DmsTree.dragAndDrop = {
        over: function () {
            $(this).addClass("over");
        },
        out: function () {
            $(this).removeClass("over");
        },
        drop: function () {
            $(this).removeClass("over");
        }
    };

    function closeModals() {
        try {
            $(".modal").modal("hide");
        } catch (e) {}
    }

    DmsTree.emit("ready", config);
    DmsTree.on("refresh", function () {
        DmsTree.buildFrom(currentTemplate);
    });
};

return module; });
<|endoftext|>


<commit_before>import React, { Component, Fragment } from 'react';
import { PropTypes as Types } from 'prop-types';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import { Message, WithTranslations } from 'retranslate';
import { Link } from 'react-router';

import { Loader, ErrorMessage } from '../common';
import PensionFundTable from './../onboardingFlow/selectSources/pensionFundTable';
import PendingExchangesTable from './pendingExchangeTable';
import ReturnComparison, { actions as returnComparisonActions } from '../returnComparison';
import getReturnComparisonStartDateOptions from '../returnComparison/options';
import Select from './Select';
import UpdateUserForm from './updateUserForm';
import { updateUser } from '../common/user/actions';

const noop = () => null;

export const TOTAL_CAPITAL = 3329280;

export class AccountPage extends Component {
  constructor(props) {
    super(props);

    const options = getReturnComparisonStartDateOptions();
    const returnComparisonStartDate = options[0].value;

    this.state = {
      options,
      returnComparisonStartDate,
    };

    this.onReturnComparisonStartDateChange = this.onReturnComparisonStartDateChange.bind(this);
  }

  onReturnComparisonStartDateChange(date) {
    this.props.getReturnComparisonForStartDate(date);
    this.setState({ returnComparisonStartDate: date });
  }

  render() {
    const {
      currentBalanceFunds,
      loadingCurrentBalance,
      initialCapital,
      memberNumber,
      conversion,
      pendingExchanges,
      loadingPendingExchanges,
      returnComparison,
      loadingReturnComparison,
      returnComparisonError,
      saveUser,
      error,
    } = this.props;
    const { returnComparisonStartDate, options } = this.state;

    const pendingExchangesSection = loadingPendingExchanges ? (
      <Loader className="align-middle mt-5" />
    ) : (
      pendingExchanges.length > 0 && (

            <Message>pending.exchanges.lead</Message>

          <PendingExchangesTable pendingExchanges={pendingExchanges} />

      )
    );

    const returnComparisonSection = !returnComparisonError && (

              <Message>returnComparison.title</Message>

            <WithTranslations>
              {({ translate }) => (
                <Select
                  options={options.map(option => ({ ...option, label: translate(option.label) }))}
                  selected={returnComparisonStartDate}
                  onChange={this.onReturnComparisonStartDateChange}
                />
              )}
            </WithTranslations>

        <ReturnComparison
          actualPercentage={returnComparison.actualPercentage}
          estonianPercentage={returnComparison.estonianPercentage}
          marketPercentage={returnComparison.marketPercentage}
          loading={loadingReturnComparison}
        />

    );

    return (
      <Fragment>

          {memberNumber ? (
            <Message params={{ memberNumber }}>account.member.statement</Message>
          ) : (

              <Message>account.non.member.statement</Message>{' '}

                <Message>login.join.tuleva</Message>

          )}{' '}
          {initialCapital ? (
            <Message
              params={{
                initialCapital: (TOTAL_CAPITAL * initialCapital.ownershipFraction).toFixed(2),
              }}
            >
              account.initial-capital.statement
            </Message>
          ) : (
            ''
          )}

            {currentBalanceFunds && currentBalanceFunds.length === 0 ? (
              <Message>account.second.pillar.missing</Message>
            ) : (
              ''
            )}

        {conversion && conversion.transfersComplete && conversion.selectionComplete ? (

            <Message>account.converted.user.statement</Message>

        ) : (
          ''
        )}
        {error ? <ErrorMessage errors={error.body} /> : ''}

            <Message className="mb-4 lead">select.sources.current.status</Message>

          {currentBalanceFunds &&
            currentBalanceFunds.length > 0 && (

                <Link className="btn btn-primary mb-3" to="/steps/select-sources">
                  <Message>change.my.pension.fund</Message>
                </Link>

            )}

        {loadingCurrentBalance ? (
          <Loader className="align-middle" />
        ) : (
          <PensionFundTable funds={currentBalanceFunds} />
        )}

        {pendingExchangesSection}
        {returnComparisonSection}

            <Message>update.user.details.title</Message>

          <UpdateUserForm onSubmit={saveUser} />

      </Fragment>
    );
  }
}

AccountPage.propTypes = {
  currentBalanceFunds: Types.arrayOf(Types.shape({})),
  loadingCurrentBalance: Types.bool,
  pendingExchanges: Types.arrayOf(Types.shape({})),
  loadingPendingExchanges: Types.bool,
  returnComparison: Types.shape({
    actualPercentage: Types.number,
    estonianPercentage: Types.number,
    marketPercentage: Types.number,
  }),
  returnComparisonError: Types.shape({}),
  loadingReturnComparison: Types.bool,
  getReturnComparisonForStartDate: Types.func,
  initialCapital: Types.shape({}),
  memberNumber: Types.number,
  conversion: Types.shape({}),
  saveUser: Types.func,
  error: Types.shape({}),
};

AccountPage.defaultProps = {
  currentBalanceFunds: [],
  loadingCurrentBalance: false,
  pendingExchanges: [],
  loadingPendingExchanges: false,
  returnComparison: {},
  returnComparisonError: null,
  loadingReturnComparison: false,
  getReturnComparisonForStartDate: noop,
  initialCapital: {},
  memberNumber: null,
  conversion: {},
  error: null,
  saveUser: noop,
};

const mapStateToProps = state => ({
  currentBalanceFunds: state.exchange.sourceFunds !== null ? state.exchange.sourceFunds : [],
  loadingCurrentBalance: state.exchange.loadingSourceFunds,
  pendingExchanges: state.exchange.pendingExchanges,
  loadingPendingExchanges: state.exchange.loadingPendingExchanges,
  returnComparison: state.returnComparison,
  loadingReturnComparison: state.returnComparison.loading,
  returnComparisonError: state.returnComparison.error,
  initialCapital: state.account.initialCapital,
  memberNumber: (state.login.user || {}).memberNumber,
  conversion: state.login.userConversion,
  error: state.exchange.error,
});
const mapDispatchToProps = dispatch =>
  bindActionCreators(
    {
      saveUser: updateUser,
      getReturnComparisonForStartDate: returnComparisonActions.getReturnComparisonForStartDate,
    },
    dispatch,
  );

const withRedux = connect(
  mapStateToProps,
  mapDispatchToProps,
);

export default withRedux(AccountPage);
<commit_msg>Hotfix prettier<commit_after>import React, { Component, Fragment } from 'react';
import { PropTypes as Types } from 'prop-types';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import { Message, WithTranslations } from 'retranslate';
import { Link } from 'react-router';

import { Loader, ErrorMessage } from '../common';
import PensionFundTable from './../onboardingFlow/selectSources/pensionFundTable';
import PendingExchangesTable from './pendingExchangeTable';
import ReturnComparison, { actions as returnComparisonActions } from '../returnComparison';
import getReturnComparisonStartDateOptions from '../returnComparison/options';
import Select from './Select';
import UpdateUserForm from './updateUserForm';
import { updateUser } from '../common/user/actions';

const noop = () => null;

export const TOTAL_CAPITAL = 3329280;

export class AccountPage extends Component {
  constructor(props) {
    super(props);

    const options = getReturnComparisonStartDateOptions();
    const returnComparisonStartDate = options[0].value;

    this.state = {
      options,
      returnComparisonStartDate,
    };

    this.onReturnComparisonStartDateChange = this.onReturnComparisonStartDateChange.bind(this);
  }

  onReturnComparisonStartDateChange(date) {
    this.props.getReturnComparisonForStartDate(date);
    this.setState({ returnComparisonStartDate: date });
  }

  render() {
    const {
      currentBalanceFunds,
      loadingCurrentBalance,
      initialCapital,
      memberNumber,
      conversion,
      pendingExchanges,
      loadingPendingExchanges,
      returnComparison,
      loadingReturnComparison,
      returnComparisonError,
      saveUser,
      error,
    } = this.props;
    const { returnComparisonStartDate, options } = this.state;

    const pendingExchangesSection = loadingPendingExchanges ? (
      <Loader className="align-middle mt-5" />
    ) : (
      pendingExchanges.length > 0 && (

            <Message>pending.exchanges.lead</Message>

          <PendingExchangesTable pendingExchanges={pendingExchanges} />

      )
    );

    const returnComparisonSection = !returnComparisonError && (

              <Message>returnComparison.title</Message>

            <WithTranslations>
              {({ translate }) => (
                <Select
                  options={options.map(option => ({ ...option, label: translate(option.label) }))}
                  selected={returnComparisonStartDate}
                  onChange={this.onReturnComparisonStartDateChange}
                />
              )}
            </WithTranslations>

        <ReturnComparison
          actualPercentage={returnComparison.actualPercentage}
          estonianPercentage={returnComparison.estonianPercentage}
          marketPercentage={returnComparison.marketPercentage}
          loading={loadingReturnComparison}
        />

    );

    return (
      <Fragment>

          {memberNumber ? (
            <Message params={{ memberNumber }}>account.member.statement</Message>
          ) : (

              <Message>account.non.member.statement</Message>{' '}

                <Message>login.join.tuleva</Message>

          )}{' '}
          {initialCapital ? (
            <Message
              params={{
                initialCapital: (TOTAL_CAPITAL * initialCapital.ownershipFraction).toFixed(2),
              }}
            >
              account.initial-capital.statement
            </Message>
          ) : (
            ''
          )}

            {currentBalanceFunds && currentBalanceFunds.length === 0 ? (
              <Message>account.second.pillar.missing</Message>
            ) : (
              ''
            )}

        {conversion && conversion.transfersComplete && conversion.selectionComplete ? (

            <Message>account.converted.user.statement</Message>

        ) : (
          ''
        )}
        {error ? <ErrorMessage errors={error.body} /> : ''}

            <Message className="mb-4 lead">select.sources.current.status</Message>

          {currentBalanceFunds &&
            currentBalanceFunds.length > 0 && (

                <Link className="btn btn-primary mb-3" to="/steps/select-sources">
                  <Message>change.my.pension.fund</Message>
                </Link>

            )}

        {loadingCurrentBalance ? (
          <Loader className="align-middle" />
        ) : (
          <PensionFundTable funds={currentBalanceFunds} />
        )}

        {pendingExchangesSection}
        {returnComparisonSection}

            <Message>update.user.details.title</Message>

          <UpdateUserForm onSubmit={saveUser} />

      </Fragment>
    );
  }
}

AccountPage.propTypes = {
  currentBalanceFunds: Types.arrayOf(Types.shape({})),
  loadingCurrentBalance: Types.bool,
  pendingExchanges: Types.arrayOf(Types.shape({})),
  loadingPendingExchanges: Types.bool,
  returnComparison: Types.shape({
    actualPercentage: Types.number,
    estonianPercentage: Types.number,
    marketPercentage: Types.number,
  }),
  returnComparisonError: Types.shape({}),
  loadingReturnComparison: Types.bool,
  getReturnComparisonForStartDate: Types.func,
  initialCapital: Types.shape({}),
  memberNumber: Types.number,
  conversion: Types.shape({}),
  saveUser: Types.func,
  error: Types.shape({}),
};

AccountPage.defaultProps = {
  currentBalanceFunds: [],
  loadingCurrentBalance: false,
  pendingExchanges: [],
  loadingPendingExchanges: false,
  returnComparison: {},
  returnComparisonError: null,
  loadingReturnComparison: false,
  getReturnComparisonForStartDate: noop,
  initialCapital: {},
  memberNumber: null,
  conversion: {},
  error: null,
  saveUser: noop,
};

const mapStateToProps = state => ({
  currentBalanceFunds: state.exchange.sourceFunds !== null ? state.exchange.sourceFunds : [],
  loadingCurrentBalance: state.exchange.loadingSourceFunds,
  pendingExchanges: state.exchange.pendingExchanges,
  loadingPendingExchanges: state.exchange.loadingPendingExchanges,
  returnComparison: state.returnComparison,
  loadingReturnComparison: state.returnComparison.loading,
  returnComparisonError: state.returnComparison.error,
  initialCapital: state.account.initialCapital,
  memberNumber: (state.login.user || {}).memberNumber,
  conversion: state.login.userConversion,
  error: state.exchange.error,
});
const mapDispatchToProps = dispatch =>
  bindActionCreators(
    {
      saveUser: updateUser,
      getReturnComparisonForStartDate: returnComparisonActions.getReturnComparisonForStartDate,
    },
    dispatch,
  );

const withRedux = connect(
  mapStateToProps,
  mapDispatchToProps,
);

export default withRedux(AccountPage);
<|endoftext|>


<commit_before>/*
 *
 */

console.log("load swx");

import * as fs from './filesystem.js'
import * as msg from './messaging.js'

import sysfs from './fs/sys.js'
import httpfs from './fs/http.js'
import html5fs from './fs/html5.js'
import githubfs from './fs/github.js'
import dropboxfs from './fs/dropbox.js'

import focalStorage from './external/focalStorage.js';

const storagePrefix = "LivelySync_";

class ServiceWorker {
  constructor() {

    this.filesystem = new fs.Filesystem()

    // default file system
    this.filesystem.mount('/', githubfs, {repo: 'LivelyKernel/Lively4', branch: 'master'}) // mounting lively4-core is to irritating
    this.filesystem.mount('/sys', sysfs, this)
    this.filesystem.mount('/local', html5fs)

    // here we should remount previous filesystem (remembered in focalStorage)
  }

  static instance() {
    var startTime = Date.now();
    var instance = new ServiceWorker()
    __instance__ = instance; // Global side effect #TODO

    return instance.filesystem.loadMounts().then( () => {
      console.log("mount FS in" + (Date.now() - startTime) + "ms");

      instance.resolvePendingRequests()
      return instance
    })
  }

  resolvePendingRequests() {

    if (!pendingRequests) {
      console.log("no pending requests");
      return
    }
    console.log("resolve pending requests: " + pendingRequests)
    // #Hack needed, because the swx-solved loads asyncronously and the service worker expects and syncronouse answer or promise.
    pendingRequests.forEach(ea => {
      console.log("work on pendingRequest " + ea.url)
      this.fetch(ea.event, ea)
    })
    pendingRequests = null; // stop listening to requests..
  }

   fetch(event) {
    // console.log("SWX.fetch " + event + ", " + pending)
    let request = event.request;
    if (!request) return

    let  url   = new URL(request.url),
      promise = undefined

    if(url.hostname !== 'lively4') {
      if (url.hostname == location.hostname && request.mode != 'navigate') {
        if (url.pathname.match(/\/_git\//))  return;
        if (url.pathname.match(/\/_search\//))  return;
        if (url.pathname.match(/\/_meta\//))  return;
        if (url.pathname.match(/lively4-serviceworker/))  return;

        try {
          var p = new Promise(async (resolve, reject) => {
            var email = await focalStorage.getItem(storagePrefix+ "githubEmail")
            var username = await focalStorage.getItem(storagePrefix+ "githubUsername")
            var token = await focalStorage.getItem(storagePrefix+ "githubToken")
            // console.log("email: " + email + " username: " + username + " token: " + token)
            // console.log("heimspiel: " + url);

             // we have to manually recreate a request, because you cannot modify the original
             // see http://stackoverflow.com/questions/35420980/how-to-alter-the-headers-of-a-request
             var options = {
                method: request.method,
                headers: new Headers(),
                mode: request.mode,
                credentials: request.credentials,
                redirect: request.redirect
            }
            if (request.method == "PUT") {
              options.body =  await request.blob()
            }

            // if (request.url.toString().match("dummy")) {
            //   debugger
            // }
            // for(var ea of request.headers.entries()) {console.log(ea) }

            for (var pair of request.headers.entries()) {
              // console.log("set header " + pair[0] + " to" + pair[1])
              options.headers.set(pair[0], pair[1]);
            }
            options.headers.set("gitusername", username);
            options.headers.set("gitemail", email);
            options.headers.set("gitpassword", token);

            var req = new Request(request.url, options );

            // console.log("username: " + req.headers.get("gitusername"));

            // use system here to prevent recursion...
            resolve(self.fetch(req).then(result => {
              // console.log("got result!" + result)
              if(result instanceof Response) {
                return result
              } else {
                return new Response(result)
              }
            }).catch(e => {
              console.log("fetch error: "  + e)
              return new Response("Could not fetch " + url +", because of: " + e)
            }))
          })
          return p
        } catch(err) {
          if (err.toString().match("The fetch event has already been responded to.")) {
            console.log("How can we check for this before? ", err)
          } else {
            throw err
          }
        }
      } else {
        // do nothing should be fine...
        // event.respondWith(self.fetch(request));
      }
    } else {
      // console.log("lively4 fetch " + request.url)
      let response = this.filesystem.handle(request, url)

      response = response.then((result) => {
        if(result instanceof Response) {
          return result
        } if(result && result.toResponse) {
          return result.toResponse()
        } else {
          return new Response(result)
        }
      }).catch((err) => {
        console.error('Error while processing fetch event:', err)

        let message = err.toString()
        let content = JSON.stringify({message: message})

        return new Response(content, {status: 500, statusText: message})
      })

      return response
    }
  }

  message(event) {
    return msg.process(event)
  }
}

/*
 * function to object adapter
 */

var __instance__
var __instancePromise__
export async function instance() {
  return __instance__
}

export async function instancePromise() {
  if(typeof  __instancePromise__ === 'undefined') {
    __instancePromise__ = ServiceWorker.instance() // sets __instance__
  }
  return  __instancePromise__
}

export function install() {
  return self.skipWaiting()
}

export function activate() {
  return self.clients.claim()
}

export function fetch(event) {
  // console.log("fetch swx.js " + event.request.url)
  return instancePromise().then( swx => swx.fetch(event))
}

export function message(event) {
  return instancePromise().then( swx => swx.message(event))
}

export {
  focalStorage
}

instancePromise(); // force constructor

// console.log("Loaded swx.js")
<commit_msg>reverted falsely commited wip refactoring in service worker<commit_after>/*
 *
 */

console.log("load swx");

import * as fs from './filesystem.js'
import * as msg from './messaging.js'

import sysfs from './fs/sys.js'
import httpfs from './fs/http.js'
import html5fs from './fs/html5.js'
import githubfs from './fs/github.js'
import dropboxfs from './fs/dropbox.js'

import focalStorage from './external/focalStorage.js';

const storagePrefix = "LivelySync_";

class ServiceWorker {
  constructor() {

    this.filesystem = new fs.Filesystem()

    // default file system
    this.filesystem.mount('/', githubfs, {repo: 'LivelyKernel/Lively4', branch: 'master'}) // mounting lively4-core is to irritating
    this.filesystem.mount('/sys', sysfs, this)
    this.filesystem.mount('/local', html5fs)

    // here we should remount previous filesystem (remembered in focalStorage)
  }

  static instance() {
    var startTime = Date.now();
    var instance = new ServiceWorker()
    __instance__ = instance; // Global side effect #TODO

    return instance.filesystem.loadMounts().then( () => {
      console.log("mount FS in" + (Date.now() - startTime) + "ms");

      instance.resolvePendingRequests()
      return instance
    })
  }

  resolvePendingRequests() {

    if (!pendingRequests) {
      console.log("no pending requests");
      return
    }
    console.log("resolve pending requests: " + pendingRequests)
    // #Hack needed, because the swx-solved loads asyncronously and the service worker expects and syncronouse answer or promise.
    pendingRequests.forEach(ea => {
      console.log("work on pendingRequest " + ea.url)
      this.fetch(ea.event, ea)
    })
    pendingRequests = null; // stop listening to requests..
  }

  fetch(event, pending) {
    // console.log("SWX.fetch " + event + ", " + pending)
    let request = event.request;
    if (!request) return

    let  url   = new URL(request.url),
      promise = undefined

    if(url.hostname !== 'lively4') {
      if (url.hostname == location.hostname && request.mode != 'navigate') {
        if (url.pathname.match(/\/_git\//))  return;
        if (url.pathname.match(/\/_search\//))  return;
        if (url.pathname.match(/\/_meta\//))  return;
        if (url.pathname.match(/lively4-serviceworker/))  return;

        try {
          var p = new Promise(async (resolve, reject) => {
            var email = await focalStorage.getItem(storagePrefix+ "githubEmail")
            var username = await focalStorage.getItem(storagePrefix+ "githubUsername")
            var token = await focalStorage.getItem(storagePrefix+ "githubToken")
            // console.log("email: " + email + " username: " + username + " token: " + token)
            // console.log("heimspiel: " + url);

             // we have to manually recreate a request, because you cannot modify the original
             // see http://stackoverflow.com/questions/35420980/how-to-alter-the-headers-of-a-request
             var options = {
                method: request.method,
                headers: new Headers(),
                mode: request.mode,
                credentials: request.credentials,
                redirect: request.redirect
            }
            if (request.method == "PUT") {
              options.body =  await request.blob()
            }

            // if (request.url.toString().match("dummy")) {
            //   debugger
            // }
            // for(var ea of request.headers.entries()) {console.log(ea) }

            for (var pair of request.headers.entries()) {
              // console.log("set header " + pair[0] + " to" + pair[1])
              options.headers.set(pair[0], pair[1]);
            }
            options.headers.set("gitusername", username);
            options.headers.set("gitemail", email);
            options.headers.set("gitpassword", token);

            var req = new Request(request.url, options );

            // console.log("username: " + req.headers.get("gitusername"));

            // use system here to prevent recursion...
            resolve(self.fetch(req).then(result => {
              // console.log("got result!" + result)
              if(result instanceof Response) {
                return result
              } else {
                return new Response(result)
              }
            }).catch(e => {
              console.log("fetch error: "  + e)
              return new Response("Could not fetch " + url +", because of: " + e)
            }))
          })
          if (pending)
            pending.resolve(p)
          else
            event.respondWith(p)
        } catch(err) {
          if (err.toString().match("The fetch event has already been responded to.")) {
            console.log("How can we check for this before? ", err)
          } else {
            throw err
          }
        }
      } else {
        // do nothing should be fine...
        // event.respondWith(self.fetch(request));
      }
    } else {
      // console.log("lively4 fetch " + request.url)
      let response = this.filesystem.handle(request, url)

      response = response.then((result) => {
        if(result instanceof Response) {
          return result
        } if(result && result.toResponse) {
          return result.toResponse()
        } else {
          return new Response(result)
        }
      }).catch((err) => {
        console.error('Error while processing fetch event:', err)

        let message = err.toString()
        let content = JSON.stringify({message: message})

        return new Response(content, {status: 500, statusText: message})
      })

      if (pending) {
        console.log("resolve pending request: " + pending.url)
        pending.resolve(response)
      } else
        event.respondWith(response)
    }
  }

  message(event) {
    return msg.process(event)
  }
}

/*
 * function to object adapter
 */

var __instance__
var __instancePromise__
export async function instance() {
  return __instance__
}

export async function instancePromise() {
  if(typeof  __instancePromise__ === 'undefined') {
    __instancePromise__ = ServiceWorker.instance() // sets __instance__
  }
  return  __instancePromise__
}

export function install() {
  return self.skipWaiting()
}

export function activate() {
  return self.clients.claim()
}

export function fetch(event) {
  // console.log("fetch swx.js " + event.request.url)
  return instancePromise().then( swx => swx.fetch(event))
}

export function message(event) {
  return instancePromise().then( swx => swx.message(event))
}

export {
  focalStorage
}

instancePromise(); // force constructor

// console.log("Loaded swx.js")
<|endoftext|>


<commit_before>/* eslint ember/order-in-components: 0 */
import { inject as service } from '@ember/service';
import Component from '@ember/component';
import { computed } from '@ember/object';
import { all } from 'rsvp';
import { isEmpty, isPresent } from '@ember/utils';

export default Component.extend({
  store: service(),
  tagName: 'section',
  classNames: ['school-competencies-expanded'],
  school: null,
  isManaging: false,
  isSaving: false,
  canUpdate: false,
  canDelete: false,
  canCreate: false,
  bufferedCompetencies: null,

  competencies: computed('school.competencies.[]', async function(){
    const school = this.school;
    return await school.get('competencies');
  }),

  domains: computed('school.competencies.[]', async function(){
    const competencies = await this.competencies;
    return competencies.filterBy('isDomain');
  }),

  childCompetencies: computed('school.competencies.[]', async function(){
    const competencies = await this.competencies;
    return competencies.filterBy('isNotDomain');
  }),

  showCollapsible: computed('isManaging', 'school.competencies.length', function(){
    const isManaging = this.isManaging;
    const school = this.school;
    const competencyIds = school.hasMany('competencies').ids();
    return competencyIds.length && ! isManaging;
  }),

  didReceiveAttrs(){
    this._super(...arguments);
    if (this.isManaging && isEmpty(this.bufferedCompetencies)) {
      const school = this.school;
      school.get('competencies').then(competencies => {
        this.set('bufferedCompetencies', competencies.toArray());
      });
    }
  },

  actions: {
    collapse(){
      const collapse = this.collapse;
      this.get('school.competencies').then(competencies => {
        if(competencies.length){
          collapse();
        }
      });
    },

    addCompetencyToBuffer(domain, title){
      let competency = this.store.createRecord('competency', {title, active: true});
      if (isPresent(domain)) {
        competency.set('parent', domain);
        domain.get('children').then(children => {
          children.pushObject(competency);
          this.bufferedCompetencies.pushObject(competency);
        });
      } else {
        this.bufferedCompetencies.pushObject(competency);
      }
    },

    removeCompetencyFromBuffer(competency){
      let buffer = this.bufferedCompetencies;
      if (buffer.includes(competency)) {
        buffer.removeObject(competency);
      }
    },
    async save(){
      this.set('isSaving', true);
      const setSchoolManageCompetencies = this.get('setSchoolManageCompetencies');
      const school = this.school;
      const schoolCompetencies = await school.get('competencies');
      const bufferedCompetencies = this.get('bufferedCompetencies');
      const domainsToRemove = schoolCompetencies.filter(competency => {
        return !bufferedCompetencies.includes(competency) && competency.get('isDomain');
      });
      const competenciesToRemove = schoolCompetencies.filter(competency => {
        return !bufferedCompetencies.includes(competency) && !competency.get('isDomain');
      });

      // delete all removed competencies first, then all removed domains
      await all(competenciesToRemove.invoke('destroyRecord'));
      await all(domainsToRemove.invoke('destroyRecord'));

      // set the school on new competencies
      bufferedCompetencies.filterBy('isNew').forEach(competency => {
        competency.set('school', school);
      });

      // update all modified competencies (this will include new ones).
      await all(
        bufferedCompetencies.filterBy('hasDirtyAttributes').invoke('save')
      );

      // repopulate school from buffer.
      schoolCompetencies.clear();
      bufferedCompetencies.forEach(competency => {
        schoolCompetencies.pushObject(competency);
      });

      // cleanup
      this.set('bufferedCompetencies', []);
      this.set('isSaving', false);
      setSchoolManageCompetencies(false);
    },

    cancel(){
      const setSchoolManageCompetencies = this.setSchoolManageCompetencies;
      setSchoolManageCompetencies(false);
    },

    manage(){
      const setSchoolManageCompetencies = this.setSchoolManageCompetencies;
      setSchoolManageCompetencies(true);
    }
  }
});
<commit_msg>async/await throughout. access component props directly.<commit_after>/* eslint ember/order-in-components: 0 */
import { inject as service } from '@ember/service';
import Component from '@ember/component';
import { computed } from '@ember/object';
import { all } from 'rsvp';
import { isEmpty, isPresent } from '@ember/utils';

export default Component.extend({
  store: service(),
  tagName: 'section',
  classNames: ['school-competencies-expanded'],
  school: null,
  isManaging: false,
  isSaving: false,
  canUpdate: false,
  canDelete: false,
  canCreate: false,
  bufferedCompetencies: null,

  competencies: computed('school.competencies.[]', async function(){
    const school = this.school;
    return await school.get('competencies');
  }),

  domains: computed('school.competencies.[]', async function(){
    const competencies = await this.competencies;
    return competencies.filterBy('isDomain');
  }),

  childCompetencies: computed('school.competencies.[]', async function(){
    const competencies = await this.competencies;
    return competencies.filterBy('isNotDomain');
  }),

  showCollapsible: computed('isManaging', 'school.competencies.length', function(){
    const isManaging = this.isManaging;
    const school = this.school;
    const competencyIds = school.hasMany('competencies').ids();
    return competencyIds.length && ! isManaging;
  }),

  async didReceiveAttrs(){
    this._super(...arguments);
    if (this.isManaging && isEmpty(this.bufferedCompetencies)) {
      const school = this.school;
      const competencies  = await school.get('competencies');
      this.set('bufferedCompetencies', competencies.toArray());
    }
  },

  actions: {
    async collapse(){
      const collapse = this.collapse;
      const school = this.school;
      const competencies = await school.get('competencies');
      if (competencies.length) {
        collapse();
      }
    },

    async addCompetencyToBuffer(domain, title){
      let competency = this.store.createRecord('competency', {title, active: true});
      if (isPresent(domain)) {
        competency.set('parent', domain);
        const children = await domain.get('children');
        children.pushObject(competency);
        this.bufferedCompetencies.pushObject(competency);
      } else {
        this.bufferedCompetencies.pushObject(competency);
      }
    },

    removeCompetencyFromBuffer(competency){
      let buffer = this.bufferedCompetencies;
      if (buffer.includes(competency)) {
        buffer.removeObject(competency);
      }
    },
    async save(){
      this.set('isSaving', true);
      const setSchoolManageCompetencies = this.setSchoolManageCompetencies;
      const school = this.school;
      const schoolCompetencies = await school.get('competencies');
      const bufferedCompetencies = this.bufferedCompetencies;
      const domainsToRemove = schoolCompetencies.filter(competency => {
        return !bufferedCompetencies.includes(competency) && competency.get('isDomain');
      });
      const competenciesToRemove = schoolCompetencies.filter(competency => {
        return !bufferedCompetencies.includes(competency) && !competency.get('isDomain');
      });

      // delete all removed competencies first, then all removed domains
      await all(competenciesToRemove.invoke('destroyRecord'));
      await all(domainsToRemove.invoke('destroyRecord'));

      // set the school on new competencies
      bufferedCompetencies.filterBy('isNew').forEach(competency => {
        competency.set('school', school);
      });

      // update all modified competencies (this will include new ones).
      await all(
        bufferedCompetencies.filterBy('hasDirtyAttributes').invoke('save')
      );

      // repopulate school from buffer.
      schoolCompetencies.clear();
      bufferedCompetencies.forEach(competency => {
        schoolCompetencies.pushObject(competency);
      });

      // cleanup
      this.set('bufferedCompetencies', []);
      this.set('isSaving', false);
      setSchoolManageCompetencies(false);
    },

    cancel(){
      const setSchoolManageCompetencies = this.setSchoolManageCompetencies;
      setSchoolManageCompetencies(false);
    },

    manage(){
      const setSchoolManageCompetencies = this.setSchoolManageCompetencies;
      setSchoolManageCompetencies(true);
    }
  }
});
<|endoftext|>


<commit_before>(function($) {

	/**
	 * Twenty-Four Hour Clock Face
	 *
	 * This class will generate a twenty-four our clock for FlipClock.js
	 *
	 * @param  object  The parent FlipClock.Factory object
	 * @param  object  An object of properties to override the default
	 */

	FlipClock.TwentyFourHourClockFace = FlipClock.Face.extend({

		/**
		 * Constructor
		 *
		 * @param  object  The parent FlipClock.Factory object
		 * @param  object  An object of properties to override the default
		 */

		constructor: function(factory, options) {
			this.base(factory, options);
		},

		/**
		 * Build the clock face
		 *
		 * @param  object  Pass the time that should be used to display on the clock.
		 */

		build: function() {
			var t        = this;
			var children = this.factory.$el.find('ul');

			if(!this.factory.time.time) {
				this.factory.original = new Date();

				this.factory.time = new FlipClock.Time(this.factory, this.factory.original);
			}

			var time = this.factory.time.getMilitaryTime();

			if(time.length > children.length) {
				$.each(time, function(i, digit) {
					t.createList(digit);
				});
			}

			this.createDivider();
			this.createDivider();

			$(this.dividers[0]).insertBefore(this.lists[this.lists.length - 2].$el);
			$(this.dividers[1]).insertBefore(this.lists[this.lists.length - 4].$el);

			this.base();
		},

		/**
		 * Flip the clock face
		 */

		flip: function(time, doNotAddPlayClass) {
			this.autoIncrement();

			time = time ? time : this.factory.time.getMilitaryTime();

			this.base(time, doNotAddPlayClass);
		}

	});

}(jQuery));<commit_msg>- (Bug Fix) Fixed an issue with the time being overridden upon inheritance in the TwentyFourHour clock face<commit_after>(function($) {

	/**
	 * Twenty-Four Hour Clock Face
	 *
	 * This class will generate a twenty-four our clock for FlipClock.js
	 *
	 * @param  object  The parent FlipClock.Factory object
	 * @param  object  An object of properties to override the default
	 */

	FlipClock.TwentyFourHourClockFace = FlipClock.Face.extend({

		/**
		 * Constructor
		 *
		 * @param  object  The parent FlipClock.Factory object
		 * @param  object  An object of properties to override the default
		 */

		constructor: function(factory, options) {
			this.base(factory, options);
		},

		/**
		 * Build the clock face
		 *
		 * @param  object  Pass the time that should be used to display on the clock.
		 */

		build: function(time) {
			var t        = this;
			var children = this.factory.$el.find('ul');

			if(!this.factory.time.time) {
				this.factory.original = new Date();

				this.factory.time = new FlipClock.Time(this.factory, this.factory.original);
			}

			var time = time ? time : this.factory.time.getMilitaryTime(false, this.showSeconds);

			if(time.length > children.length) {
				$.each(time, function(i, digit) {
					t.createList(digit);
				});
			}

			this.createDivider();
			this.createDivider();

			$(this.dividers[0]).insertBefore(this.lists[this.lists.length - 2].$el);
			$(this.dividers[1]).insertBefore(this.lists[this.lists.length - 4].$el);

			this.base();
		},

		/**
		 * Flip the clock face
		 */

		flip: function(time, doNotAddPlayClass) {
			this.autoIncrement();

			time = time ? time : this.factory.time.getMilitaryTime(false, this.showSeconds);

			this.base(time, doNotAddPlayClass);
		}

	});

}(jQuery));<|endoftext|>


<commit_before>/**
 * @license
 * Copyright 2017 The FOAM Authors. All Rights Reserved.
 * http://www.apache.org/licenses/LICENSE-2.0
 */

foam.CLASS({
  package: 'foam.swift.parse.json.output',
  name: 'Outputter',
  properties: [
    {
      name: 'beforeKey',
      class: 'String',
      value: '"',
    },
    {
      name: 'afterKey',
      class: 'String',
      value: '"',
    },
  ],
  methods: [
    {
      name: 'outputProperty',
      args: [
        {
          swiftAnnotations: ['inout'],
          swiftType: 'String',
          name: 'out',
        },
        {
          swiftType: 'FObject',
          name: 'o',
        },
        {
          swiftType: 'PropertyInfo',
          name: 'p',
        },
      ],
      swiftCode: function() {/*
out.append(beforeKey)
out.append(p.name)
out.append(afterKey)
out.append(":")
p.toJSON(outputter: self, out: &out, value: p.get(o))
      */},
    },
    {
      name: 'escape',
      args: [
        {
          swiftType: 'String',
          name: 'data',
        },
      ],
      swiftReturns: 'String',
      swiftCode: function() {/*
return data.replacingOccurrences(of: "\"", with: "\\\"")
      */},
    },
    {
      name: 'outputNil',
      args: [
        {
          swiftAnnotations: ['inout'],
          swiftType: 'String',
          name: 'out',
        },
      ],
      swiftCode: function() {/*
out.append("null")
      */},
    },
    {
      name: 'outputString',
      args: [
        {
          swiftAnnotations: ['inout'],
          swiftType: 'String',
          name: 'out',
        },
        {
          swiftType: 'String',
          name: 'data',
        },
      ],
      swiftCode: function() {/*
out.append("\"")
out.append(escape(data))
out.append("\"")
      */},
    },
    {
      name: 'outputBoolean',
      args: [
        {
          swiftAnnotations: ['inout'],
          swiftType: 'String',
          name: 'out',
        },
        {
          swiftType: 'Bool',
          name: 'data',
        },
      ],
      swiftCode: function() {/*
out.append(data ? "true" : "false")
      */},
    },
    {
      name: 'outputMap',
      args: [
        {
          swiftAnnotations: ['inout'],
          swiftType: 'String',
          name: 'out',
        },
        {
          swiftType: '[String:Any?]',
          name: 'data',
        },
      ],
      swiftCode: function() {/*
out.append("{")
for (i, d) in data.keys.enumerated() {
  outputString(&out, d)
  out.append(":")
  output(&out, data[d]!)
  if i < data.count - 1 { out.append(",") }
}
out.append("}")
      */},
    },
    {
      name: 'outputArray',
      args: [
        {
          swiftAnnotations: ['inout'],
          swiftType: 'String',
          name: 'out',
        },
        {
          swiftType: '[Any?]',
          name: 'data',
        },
      ],
      swiftCode: function() {/*
out.append("[")
for (i, d) in data.enumerated() {
  output(&out, d)
  if i < data.count - 1 { out.append(",") }
}
out.append("]")
      */},
    },
    {
      name: 'outputNumber',
      args: [
        {
          swiftAnnotations: ['inout'],
          swiftType: 'String',
          name: 'out',
        },
        {
          swiftType: 'NSNumber',
          name: 'data',
        },
      ],
      swiftCode: function() {/*
out.append(data.stringValue)
      */},
    },
    {
      name: 'outputDate',
      args: [
        {
          swiftAnnotations: ['inout'],
          swiftType: 'String',
          name: 'out'
        },
        {
          swiftType: 'Date',
          name: 'data'
        }
      ],
      swiftCode: function() {/*
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"
out.append("\"\(formatter.string(from: data))\"")
      */}
    },
    {
      name: 'output',
      args: [
        {
          swiftAnnotations: ['inout'],
          swiftType: 'String',
          name: 'out',
        },
        {
          swiftType: 'Any?',
          name: 'data',
        },
      ],
      swiftCode: function() {/*
if let data = data as? JSONOutputter {
  data.toJSON(outputter: self, out: &out)
} else if let data = data as? PropertyInfo {
  outputPropertyInfo(&out, data)
} else if let data = data as? String {
  outputString(&out, data)
} else if let data = data as? Bool {
  outputBoolean(&out, data)
} else if let data = data as? NSNumber {
  outputNumber(&out, data)
} else if let data = data as? [Any?] {
  outputArray(&out, data)
} else if let data = data as? [String:Any?] {
  outputMap(&out, data)
} else if let data = data as? Date {
  outputDate(&out, data)
} else if data == nil {
  outputNil(&out)
} else {
  NSLog("Unable to output %@", (data as AnyObject).description)
  outputNil(&out)
}
      */},
    },
    {
      name: 'outputPropertyInfo',
      args: [
        {
          swiftAnnotations: ['inout'],
          swiftType: 'String',
          name: 'out',
        },
        {
          swiftType: 'PropertyInfo',
          name: 'data',
        },
      ],
      swiftCode: function() {/*
out.append("{");
outputString(&out, "class");
out.append(":");
outputString(&out, "__Property__");
out.append(",");
outputString(&out, "forClass_");
out.append(":");
outputString(&out, data.classInfo.id);
out.append(",");
outputString(&out, "name");
out.append(":");
outputString(&out, data.name);
out.append("}");
      */},
    },
    {
      name: 'outputEnum',
      args: [
        {
          swiftAnnotations: ['inout'],
          swiftType: 'String',
          name: 'out',
        },
        {
          swiftType: 'FOAM_enum',
          name: 'data',
        },
      ],
      swiftCode: function() {/*
out.append("{");
outputString(&out, "class");
out.append(":");
outputString(&out, data.classId)
out.append(",");
outputString(&out, "ordinal");
out.append(":");
outputNumber(&out, data.ordinal as NSNumber)
out.append("}");

      */},
    },
    {
      name: 'outputFObject',
      args: [
        {
          swiftAnnotations: ['inout'],
          swiftType: 'String',
          name: 'out',
        },
        {
          swiftType: 'FObject',
          name: 'data',
        },
      ],
      swiftCode: function() {/*
let info = data.ownClassInfo()
out.append("{")

out.append(beforeKey)
out.append("class")
out.append(afterKey)
out.append(":")
outputString(&out, info.id)

for p in info.axioms(byType: PropertyInfo.self) {
  if !p.transient && data.hasOwnProperty(p.name) {
    out.append(",")
    outputProperty(&out, data, p)
  }
}

out.append("}");
      */},
    },
    {
      // Can't call it stringify because that method is actually inherited so
      // hacks are required to not have the args clobbered.
      name: 'swiftStringify',
      args: [
        {
          swiftType: 'FObject',
          name: 'data',
        },
      ],
      swiftReturns: 'String',
      swiftCode: function() {/*
var s = ""
output(&s, data)
return s
      */},
    },
  ]
});
<commit_msg>Removed Swift Enum Outputter<commit_after>/**
 * @license
 * Copyright 2017 The FOAM Authors. All Rights Reserved.
 * http://www.apache.org/licenses/LICENSE-2.0
 */

foam.CLASS({
  package: 'foam.swift.parse.json.output',
  name: 'Outputter',
  properties: [
    {
      name: 'beforeKey',
      class: 'String',
      value: '"',
    },
    {
      name: 'afterKey',
      class: 'String',
      value: '"',
    },
  ],
  methods: [
    {
      name: 'outputProperty',
      args: [
        {
          swiftAnnotations: ['inout'],
          swiftType: 'String',
          name: 'out',
        },
        {
          swiftType: 'FObject',
          name: 'o',
        },
        {
          swiftType: 'PropertyInfo',
          name: 'p',
        },
      ],
      swiftCode: function() {/*
out.append(beforeKey)
out.append(p.name)
out.append(afterKey)
out.append(":")
p.toJSON(outputter: self, out: &out, value: p.get(o))
      */},
    },
    {
      name: 'escape',
      args: [
        {
          swiftType: 'String',
          name: 'data',
        },
      ],
      swiftReturns: 'String',
      swiftCode: function() {/*
return data.replacingOccurrences(of: "\"", with: "\\\"")
      */},
    },
    {
      name: 'outputNil',
      args: [
        {
          swiftAnnotations: ['inout'],
          swiftType: 'String',
          name: 'out',
        },
      ],
      swiftCode: function() {/*
out.append("null")
      */},
    },
    {
      name: 'outputString',
      args: [
        {
          swiftAnnotations: ['inout'],
          swiftType: 'String',
          name: 'out',
        },
        {
          swiftType: 'String',
          name: 'data',
        },
      ],
      swiftCode: function() {/*
out.append("\"")
out.append(escape(data))
out.append("\"")
      */},
    },
    {
      name: 'outputBoolean',
      args: [
        {
          swiftAnnotations: ['inout'],
          swiftType: 'String',
          name: 'out',
        },
        {
          swiftType: 'Bool',
          name: 'data',
        },
      ],
      swiftCode: function() {/*
out.append(data ? "true" : "false")
      */},
    },
    {
      name: 'outputMap',
      args: [
        {
          swiftAnnotations: ['inout'],
          swiftType: 'String',
          name: 'out',
        },
        {
          swiftType: '[String:Any?]',
          name: 'data',
        },
      ],
      swiftCode: function() {/*
out.append("{")
for (i, d) in data.keys.enumerated() {
  outputString(&out, d)
  out.append(":")
  output(&out, data[d]!)
  if i < data.count - 1 { out.append(",") }
}
out.append("}")
      */},
    },
    {
      name: 'outputArray',
      args: [
        {
          swiftAnnotations: ['inout'],
          swiftType: 'String',
          name: 'out',
        },
        {
          swiftType: '[Any?]',
          name: 'data',
        },
      ],
      swiftCode: function() {/*
out.append("[")
for (i, d) in data.enumerated() {
  output(&out, d)
  if i < data.count - 1 { out.append(",") }
}
out.append("]")
      */},
    },
    {
      name: 'outputNumber',
      args: [
        {
          swiftAnnotations: ['inout'],
          swiftType: 'String',
          name: 'out',
        },
        {
          swiftType: 'NSNumber',
          name: 'data',
        },
      ],
      swiftCode: function() {/*
out.append(data.stringValue)
      */},
    },
    {
      name: 'outputDate',
      args: [
        {
          swiftAnnotations: ['inout'],
          swiftType: 'String',
          name: 'out'
        },
        {
          swiftType: 'Date',
          name: 'data'
        }
      ],
      swiftCode: function() {/*
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"
out.append("\"\(formatter.string(from: data))\"")
      */}
    },
    {
      name: 'output',
      args: [
        {
          swiftAnnotations: ['inout'],
          swiftType: 'String',
          name: 'out',
        },
        {
          swiftType: 'Any?',
          name: 'data',
        },
      ],
      swiftCode: function() {/*
if let data = data as? JSONOutputter {
  data.toJSON(outputter: self, out: &out)
} else if let data = data as? PropertyInfo {
  outputPropertyInfo(&out, data)
} else if let data = data as? String {
  outputString(&out, data)
} else if let data = data as? Bool {
  outputBoolean(&out, data)
} else if let data = data as? NSNumber {
  outputNumber(&out, data)
} else if let data = data as? [Any?] {
  outputArray(&out, data)
} else if let data = data as? [String:Any?] {
  outputMap(&out, data)
} else if let data = data as? Date {
  outputDate(&out, data)
} else if data == nil {
  outputNil(&out)
} else {
  NSLog("Unable to output %@", (data as AnyObject).description)
  outputNil(&out)
}
      */},
    },
    {
      name: 'outputPropertyInfo',
      args: [
        {
          swiftAnnotations: ['inout'],
          swiftType: 'String',
          name: 'out',
        },
        {
          swiftType: 'PropertyInfo',
          name: 'data',
        },
      ],
      swiftCode: function() {/*
out.append("{");
outputString(&out, "class");
out.append(":");
outputString(&out, "__Property__");
out.append(",");
outputString(&out, "forClass_");
out.append(":");
outputString(&out, data.classInfo.id);
out.append(",");
outputString(&out, "name");
out.append(":");
outputString(&out, data.name);
out.append("}");
      */},
    },
    {
      name: 'outputEnum',
      args: [
        {
          swiftAnnotations: ['inout'],
          swiftType: 'String',
          name: 'out',
        },
        {
          swiftType: 'FOAM_enum',
          name: 'data',
        },
      ],
      swiftCode: function() {/*
outputNumber(&out, data.ordinal as NSNumber)
      */},
    },
    {
      name: 'outputFObject',
      args: [
        {
          swiftAnnotations: ['inout'],
          swiftType: 'String',
          name: 'out',
        },
        {
          swiftType: 'FObject',
          name: 'data',
        },
      ],
      swiftCode: function() {/*
let info = data.ownClassInfo()
out.append("{")

out.append(beforeKey)
out.append("class")
out.append(afterKey)
out.append(":")
outputString(&out, info.id)

for p in info.axioms(byType: PropertyInfo.self) {
  if !p.transient && data.hasOwnProperty(p.name) {
    out.append(",")
    outputProperty(&out, data, p)
  }
}

out.append("}");
      */},
    },
    {
      // Can't call it stringify because that method is actually inherited so
      // hacks are required to not have the args clobbered.
      name: 'swiftStringify',
      args: [
        {
          swiftType: 'FObject',
          name: 'data',
        },
      ],
      swiftReturns: 'String',
      swiftCode: function() {/*
var s = ""
output(&s, data)
return s
      */},
    },
  ]
});
<|endoftext|>


<commit_before>import angular from 'angular';
import objectid from 'objectid-browser';
export default /*@ngInject*/function repeatSectionController($scope){
  function copyFields(fields) {
    return angular.copy(fields);
  }
  function addNew() {
    $scope.model[$scope.options.key] = $scope.model[$scope.options.key] || [];
    const repeatsection = $scope.model[$scope.options.key];
    //let lastSection = repeatsection[repeatsection.length - 1];
    const newsection = {_id: objectid()};
    repeatsection.push(newsection);
  }
  $scope.formOptions = {formState: $scope.formState};
  $scope.addNew = addNew;
  $scope.copyFields = copyFields;
}
<commit_msg>Add annotation<commit_after>import angular from 'angular';
import objectid from 'objectid-browser';
export default function repeatSectionController($scope){
  function copyFields(fields) {
    return angular.copy(fields);
  }
  function addNew() {
    $scope.model[$scope.options.key] = $scope.model[$scope.options.key] || [];
    const repeatsection = $scope.model[$scope.options.key];
    //let lastSection = repeatsection[repeatsection.length - 1];
    const newsection = {_id: objectid()};
    repeatsection.push(newsection);
  }
  $scope.formOptions = {formState: $scope.formState};
  $scope.addNew = addNew;
  $scope.copyFields = copyFields;
}
repeatSectionController.$inject = ['$scope'];
<|endoftext|>


<commit_before>import * as React from 'react';
import {getFields} from './utils/getFields.js';

/**
 * Component used to render Build Information.
 *
 * @param {*} props input properties containing build information
 */
export const BuildSnapshot = (props) => {
  // State variable indicating whether the BuildSnapshot is open or closed.
  // isOpen === true indicates the tray should be visible
  // and the indicator arrow on the Header should be facing downwards.
  const [isOpen, setIsOpen] = React.useState(false);

  const headerFields = ['description', 'commitHash', 'repository', 'status'];
  const trayFields = ['builders', 'timestamp'];

  const headerData = getFields(props.buildData, headerFields, '');
  const trayData = getFields(props.buildData, trayFields, '');

  return (

      <Tray isOpen = {isOpen} data = {trayData}/>

  );
}

/**
  * Subcomponent that holds the content displayed
  * when the BuildSnapshot is collapsed.
  *
  * @param props an object containing a 'data' field
  * which encapsulates the fields from headerFields.
 */
const Header = (props) => {
  return (

 props.onClick(toggle(props.isOpen))}>
      {props.data.commitHash}
      {props.data.description}
      <FailureGroup group = {'Group'}/>
      {props.data.status}

  );
}

/**
  * Subcomponent that holds the content revealed
  * when the BuildSnapshot is open (isOpen === true).
  *
  * @param props an object containing a 'data' field
  * which encapsualtes the fields from trayFields.
 */
const Tray = (props) => {
  // State variable indicating the builder whose data
  // should be rendered to the BuilderDataTable.
  // Represents the index of the builder in props.data.builders
  const [selectedBuilder,selectBuilder] = React.useState(0);
  const builder = props.data.builders[selectedBuilder];

  if(props.isOpen !== true) return null;
  return (

      {props.data.timestamp}

{builder.name}

      <BuilderGrid onClick = {selectBuilder} data = {props.data.builders}/>
      <BuilderDataTable builder = {builder}/>

  );
}
<commit_msg>Update formatting<commit_after>import * as React from 'react';
import {getFields} from './utils/getFields.js';

/**
 * Component used to render Build Information.
 *
 * @param {*} props input properties containing build information
 */
export const BuildSnapshot = (props) => {
  // State variable indicating whether the BuildSnapshot is open or closed.
  // isOpen === true indicates the tray should be visible
  // and the indicator arrow on the Header should be facing downwards.
  const [isOpen, setIsOpen] = React.useState(false);

  const headerFields = ['description', 'commitHash', 'repository', 'status'];
  const trayFields = ['builders', 'timestamp'];

  const headerData = getFields(props.buildData, headerFields, '');
  const trayData = getFields(props.buildData, trayFields, '');

  return (

      <Tray isOpen = {isOpen} data = {trayData}/>

  );
}

/**
  * Subcomponent that holds the content displayed
  * when the BuildSnapshot is collapsed.
  *
  * @param props an object containing a 'data' field
  * which encapsulates the fields from headerFields.
 */
const Header = (props) => {
  return (

 props.onClick(toggle(props.isOpen))}>
      {props.data.commitHash}
      {props.data.description}
      <FailureGroup group = {'Group'}/>
      {props.data.status}

  );
}

/**
  * Subcomponent that holds the content revealed
  * when the BuildSnapshot is open (isOpen === true).
  *
  * @param props an object containing a 'data' field
  * which encapsualtes the fields from trayFields.
 */
const Tray = (props) => {
  // State variable indicating the builder whose data
  // should be rendered to the BuilderDataTable.
  // Represents the index of the builder in props.data.builders
  const [selectedBuilder,selectBuilder] = React.useState(0);
  const builder = props.data.builders[selectedBuilder];

  if(props.isOpen !== true) return null;
  return (

      {props.data.timestamp}

        {builder.name}

      <BuilderGrid onClick = {selectBuilder} data = {props.data.builders}/>
      <BuilderDataTable builder = {builder}/>

  );
}
<|endoftext|>


<commit_before>//
// nntpchan.js -- frontend ui niceness
//

// insert a backlink for a post given its short hash
function nntpchan_backlink(shorthash)
{
  var elem = document.getElementById("postform_message");
  if ( elem )
  {
    elem.value += ">>" + shorthash.substr(0,10) + "\n";
  }
}

var banner_count = 3;

// inject a banner into an element
function nntpchan_inject_banners(elem, prefix) {
  var n = Math.floor(Math.random() * banner_count);
  var banner = prefix + "static/banners/banner_"+n+".jpg";
  var e = document.createElement("img");
  e.src = banner;
  e.setAttribute("class", "nntpchan_banner");
  elem.appendChild(e);
}
<commit_msg>revert banner injection<commit_after>//
// nntpchan.js -- frontend ui niceness
//

// insert a backlink for a post given its short hash
function nntpchan_backlink(shorthash)
{
  var elem = document.getElementById("postform_message");
  if ( elem )
  {
    elem.value += ">>" + shorthash.substr(0,10) + "\n";
  }
}

var banner_count = 3;

// inject a banner into an element
function nntpchan_inject_banners(elem, prefix) {
  var n = Math.floor(Math.random() * banner_count);
  var banner = prefix + "static/banner_"+n+".jpg";
  var e = document.createElement("img");
  e.src = banner;
  e.setAttribute("class", "nntpchan_banner");
  elem.appendChild(e);
}
<|endoftext|>