<commit_before>app.controller(
    'MainController',
    [
        '$scope',
        function ($scope) {
            // placeholder
        }
    ]
);

app.controller(
    'ImageSetListController',
    [
        '$scope',
        'ImageSet',
        'Species',
        'Magnification',
        'DevelopmentStage',
        'Probe',
        function ($scope, ImageSet, Species, Magnification, DevelopmentStage, Probe) {
            $scope.species = [];
            $scope.magnifications = [];
            $scope.development_stages = [];
            $scope.probes = [];
            $scope.image_sets = [];
            $scope.retrieving_data = false;

            var species = Species.query();
            species.$promise.then(function (data) {
                data.forEach(function (s) {
                    $scope.species.push(
                        {
                            'name': s,
                            'query': false
                        }
                    )
                });
            });

            var magnifications = Magnification.query();
            magnifications.$promise.then(function (data) {
                data.forEach(function (m) {
                    $scope.magnifications.push(
                        {
                            'name': m,
                            'query': false
                        }
                    )
                });
            });

            var development_stages = DevelopmentStage.query();
            development_stages.$promise.then(function (data) {
                data.forEach(function (d) {
                    $scope.development_stages.push(
                        {
                            'name': d,
                            'query': false
                        }
                    )
                });
            });

            var probes = Probe.query();
            probes.$promise.then(function (data) {
                data.forEach(function (p) {
                    $scope.probes.push(
                        {
                            'id': p.id,
                            'name': p.label,
                            'query': false
                        }
                    )
                });
            });

            $scope.filter_image_sets = function () {
                $scope.retrieving_data = true;
                $scope.image_sets = [];

                var species_filters = [];
                $scope.species.forEach(function (s) {
                    if (s.query) {
                        species_filters.push(s.name);
                    }
                });

                var mag_filters = [];
                $scope.magnifications.forEach(function (m) {
                    if (m.query) {
                        mag_filters.push(m.name);
                    }
                });

                var dev_stage_filters = [];
                $scope.development_stages.forEach(function (d) {
                    if (d.query) {
                        dev_stage_filters.push(d.name);
                    }
                });

                var probe_filters = [];
                $scope.probes.forEach(function (p) {
                    if (p.query) {
                        probe_filters.push(p.id);
                    }
                });

                $scope.image_sets = ImageSet.query(
                    {
                        'species': species_filters,
                        'magnification': mag_filters,
                        'development_stage': dev_stage_filters,
                        'probe': probe_filters
                    }
                );

                $scope.image_sets.$promise.then(function (data) {
                    $scope.retrieving_data = false;
                }, function (error) {
                    $scope.retrieving_data = false;
                });
            };
        }
    ]
);

app.controller(
    'ImageSetDetailController',
    [
        '$scope',
        '$q',
        '$routeParams',
        '$window',
        'ImageSet',
        'Image',
        'Subregion',
        'AnatomyProbeMap',
        'Classify',
        'TrainModel',
        function ($scope, $q, $routeParams, $window, ImageSet, Image,
                  Subregion, AnatomyProbeMap, Classify, TrainModel) {
            $scope.images = [];
            $scope.selected_image = null;
            $scope.selected_classification = null;
            $scope.mode = 'train';  // can be 'train', or 'classify'

            // drw-poly vars
            $scope.enabled = false;
            $scope.regions = {
                'svg': []
            };
            $scope.poly_height = 997;
            $scope.poly_width = 997;

            $scope.image_set = ImageSet.get({'image_set_id': $routeParams.image_set_id});

            $scope.image_set.$promise.then(function(data) {
                $scope.images = Image.query({'image_set': data.id});
                var anatomy_promises = [];

                data.probes.forEach(function(probe) {
                    anatomy_promises.push(AnatomyProbeMap.query(
                        {
                            'probe': probe.probe
                        }).$promise
                    );
                });

                $q.all(anatomy_promises).then(function(results) {
                    $scope.anatomies = [];

                    results.forEach(function(anatomy_probe_map) {
                        anatomy_probe_map.forEach(function(anatomy_probe) {
                            $scope.anatomies.push(
                                {
                                    'id': anatomy_probe.anatomy,
                                    'name': anatomy_probe.anatomy_name
                                }
                            );
                        });
                    });
                }, function(error) {
                    // Error callback where reason is the value of the first rejected promise
                    $window.alert(JSON.stringify(error, null, 4));
                });
            });

            $scope.image_selected = function(img) {
                $scope.selected_image = img;
                if (!img.image_orig_sha1) {
                    var save_response = Image.get(
                        {
                            'id': img.id
                        },
                        {}
                    );

                    save_response.$promise.then(function(data) {
                        $scope.selected_image = data;
                        $scope.select_classification($scope.selected_classification);
                    }, function (error) {
                        // TODO: figure out how to turn retrieving off for experiment
                        $window.alert(JSON.stringify(error, null, 4))
                    });
                } else {
                    $scope.select_classification($scope.selected_classification);
                }
            };

            $scope.select_classification = function(classification) {
                $scope.selected_classification = classification;

                if ($scope.selected_classification === null) {
                    return false;
                }

                var existing_sub_regions = Subregion.query(
                    {
                        'image': $scope.selected_image.id,
                        'anatomy': classification.id
                    }
                );

                var new_regions = [];
                var new_region_points =[];

                existing_sub_regions.$promise.then(function(data) {
                    data.forEach(function(region) {
                        // empty array for our new region
                        new_region_points = [];

                        region.points.forEach(function(p) {
                            new_region_points.push(
                                [
                                    p.x,
                                    p.y
                                ]
                            );
                        });

                        new_regions.push(new_region_points);
                    });

                    if (new_regions.length > 0 || $scope.image_set.trainedmodel !== null) {
                        $scope.regions.svg = new_regions;
                        $scope.enabled = false;
                    } else {
                        $scope.regions.svg = [];
                        $scope.enabled = true;
                    }
                });
            };

            $scope.set_mode = function (mode) {
                $scope.mode = mode;
                $scope.regions.svg = [];

                if (mode === 'classify') {
                    $scope.enabled = true;
                } else if (mode === 'train') {
                    if ($scope.selected_classification !== null) {
                        $scope.select_classification($scope.selected_classification);
                    }
                } else {
                    $scope.enabled = false;
                }
            };

            $scope.post_regions = function () {
                // will post all the regions for this classification in bulk,
                // since there cannot be any existing regions for the image / class combo.
                var regions = [];

                if ($scope.regions.svg.length === 0) {
                    $window.alert('There are no regions drawn, please segment something first.');
                } else if ($scope.selected_classification === null) {
                    $window.alert('There is no label associated with the active polygon, please choose a label first.');
                } else {
                    $scope.regions.svg.forEach(function(p) {
                        var region = {};
                        var region_points = [];

                        //Get points
                        for (var i = 0; i < p.length; i++) {
                            region_points.push(
                                {
                                    "x": p[i][0],
                                    "y": p[i][1],
                                    "order": i
                                }
                            );
                        }

                        region.anatomy = $scope.selected_classification.id;
                        region.image = $scope.selected_image.id;
                        region.points = region_points;

                        regions.push(region)
                    });

                    // How to get results of post to conditionally get ready for next
                    var post_region_response = Subregion.save(regions);

                    var new_regions = [];
                    var new_region_points =[];

                    post_region_response.$promise.then(function(data) {
                        data.forEach(function(region) {
                            // empty array for our new region
                            new_region_points = [];

                            region.points.forEach(function(p) {
                                new_region_points.push(
                                    [
                                        p.x,
                                        p.y
                                    ]
                                );
                            });

                            new_regions.push(new_region_points);
                        });

                        if (new_regions.length > 0) {
                            $scope.regions.svg = new_regions;
                            $scope.enabled = false;
                        }
                    }, function (error) {
                        $window.alert(JSON.stringify(error.data, null, 4))
                    });
                }
            };

            $scope.train_model = function () {
                TrainModel.save(
                    {
                        'imageset': $scope.image_set.id
                    }
                );
            };

            $scope.classify_region = function () {
                var classify_promises = [];

                $scope.regions.svg.forEach(function (region) {
                    var payload = {};
                    var points = [];

                    //Get points
                    for (var i = 0; i < region.length; i++) {
                        points.push(
                            {
                                "x": region[i][0],
                                "y": region[i][1],
                                "order": i
                            }
                        );
                    }
                    payload.image_id = $scope.selected_image.id;
                    payload.points = points;

                    // How to get results of post to conditionally get ready for next
                    classify_promises.push(Classify.save(payload).$promise);
                });

                $q.all(classify_promises).then(function (results) {
                    console.log(results);
                    $window.alert(JSON.stringify(results, null, 4));
                });
            }
        }
    ]
);
<commit_msg>refresh image set on successful POST of new sub-regions (closes #31)<commit_after>app.controller(
    'MainController',
    [
        '$scope',
        function ($scope) {
            // placeholder
        }
    ]
);

app.controller(
    'ImageSetListController',
    [
        '$scope',
        'ImageSet',
        'Species',
        'Magnification',
        'DevelopmentStage',
        'Probe',
        function ($scope, ImageSet, Species, Magnification, DevelopmentStage, Probe) {
            $scope.species = [];
            $scope.magnifications = [];
            $scope.development_stages = [];
            $scope.probes = [];
            $scope.image_sets = [];
            $scope.retrieving_data = false;

            var species = Species.query();
            species.$promise.then(function (data) {
                data.forEach(function (s) {
                    $scope.species.push(
                        {
                            'name': s,
                            'query': false
                        }
                    )
                });
            });

            var magnifications = Magnification.query();
            magnifications.$promise.then(function (data) {
                data.forEach(function (m) {
                    $scope.magnifications.push(
                        {
                            'name': m,
                            'query': false
                        }
                    )
                });
            });

            var development_stages = DevelopmentStage.query();
            development_stages.$promise.then(function (data) {
                data.forEach(function (d) {
                    $scope.development_stages.push(
                        {
                            'name': d,
                            'query': false
                        }
                    )
                });
            });

            var probes = Probe.query();
            probes.$promise.then(function (data) {
                data.forEach(function (p) {
                    $scope.probes.push(
                        {
                            'id': p.id,
                            'name': p.label,
                            'query': false
                        }
                    )
                });
            });

            $scope.filter_image_sets = function () {
                $scope.retrieving_data = true;
                $scope.image_sets = [];

                var species_filters = [];
                $scope.species.forEach(function (s) {
                    if (s.query) {
                        species_filters.push(s.name);
                    }
                });

                var mag_filters = [];
                $scope.magnifications.forEach(function (m) {
                    if (m.query) {
                        mag_filters.push(m.name);
                    }
                });

                var dev_stage_filters = [];
                $scope.development_stages.forEach(function (d) {
                    if (d.query) {
                        dev_stage_filters.push(d.name);
                    }
                });

                var probe_filters = [];
                $scope.probes.forEach(function (p) {
                    if (p.query) {
                        probe_filters.push(p.id);
                    }
                });

                $scope.image_sets = ImageSet.query(
                    {
                        'species': species_filters,
                        'magnification': mag_filters,
                        'development_stage': dev_stage_filters,
                        'probe': probe_filters
                    }
                );

                $scope.image_sets.$promise.then(function (data) {
                    $scope.retrieving_data = false;
                }, function (error) {
                    $scope.retrieving_data = false;
                });
            };
        }
    ]
);

app.controller(
    'ImageSetDetailController',
    [
        '$scope',
        '$q',
        '$routeParams',
        '$window',
        'ImageSet',
        'Image',
        'Subregion',
        'AnatomyProbeMap',
        'Classify',
        'TrainModel',
        function ($scope, $q, $routeParams, $window, ImageSet, Image,
                  Subregion, AnatomyProbeMap, Classify, TrainModel) {
            $scope.images = [];
            $scope.selected_image = null;
            $scope.selected_classification = null;
            $scope.mode = 'train';  // can be 'train', or 'classify'

            // drw-poly vars
            $scope.enabled = false;
            $scope.regions = {
                'svg': []
            };
            $scope.poly_height = 997;
            $scope.poly_width = 997;

            $scope.image_set = ImageSet.get({'image_set_id': $routeParams.image_set_id});

            $scope.image_set.$promise.then(function(data) {
                $scope.images = Image.query({'image_set': data.id});
                var anatomy_promises = [];

                data.probes.forEach(function(probe) {
                    anatomy_promises.push(AnatomyProbeMap.query(
                        {
                            'probe': probe.probe
                        }).$promise
                    );
                });

                $q.all(anatomy_promises).then(function(results) {
                    $scope.anatomies = [];

                    results.forEach(function(anatomy_probe_map) {
                        anatomy_probe_map.forEach(function(anatomy_probe) {
                            $scope.anatomies.push(
                                {
                                    'id': anatomy_probe.anatomy,
                                    'name': anatomy_probe.anatomy_name
                                }
                            );
                        });
                    });
                }, function(error) {
                    // Error callback where reason is the value of the first rejected promise
                    $window.alert(JSON.stringify(error, null, 4));
                });
            });

            $scope.image_selected = function(img) {
                $scope.selected_image = img;
                if (!img.image_orig_sha1) {
                    var save_response = Image.get(
                        {
                            'id': img.id
                        },
                        {}
                    );

                    save_response.$promise.then(function(data) {
                        $scope.selected_image = data;
                        $scope.select_classification($scope.selected_classification);
                    }, function (error) {
                        // TODO: figure out how to turn retrieving off for experiment
                        $window.alert(JSON.stringify(error, null, 4))
                    });
                } else {
                    $scope.select_classification($scope.selected_classification);
                }
            };

            $scope.select_classification = function(classification) {
                $scope.selected_classification = classification;

                if ($scope.selected_classification === null) {
                    return false;
                }

                var existing_sub_regions = Subregion.query(
                    {
                        'image': $scope.selected_image.id,
                        'anatomy': classification.id
                    }
                );

                var new_regions = [];
                var new_region_points =[];

                existing_sub_regions.$promise.then(function(data) {
                    data.forEach(function(region) {
                        // empty array for our new region
                        new_region_points = [];

                        region.points.forEach(function(p) {
                            new_region_points.push(
                                [
                                    p.x,
                                    p.y
                                ]
                            );
                        });

                        new_regions.push(new_region_points);
                    });

                    if (new_regions.length > 0 || $scope.image_set.trainedmodel !== null) {
                        $scope.regions.svg = new_regions;
                        $scope.enabled = false;
                    } else {
                        $scope.regions.svg = [];
                        $scope.enabled = true;
                    }
                });
            };

            $scope.set_mode = function (mode) {
                $scope.mode = mode;
                $scope.regions.svg = [];

                if (mode === 'classify') {
                    $scope.enabled = true;
                } else if (mode === 'train') {
                    if ($scope.selected_classification !== null) {
                        $scope.select_classification($scope.selected_classification);
                    }
                } else {
                    $scope.enabled = false;
                }
            };

            $scope.post_regions = function () {
                // will post all the regions for this classification in bulk,
                // since there cannot be any existing regions for the image / class combo.
                var regions = [];

                if ($scope.regions.svg.length === 0) {
                    $window.alert('There are no regions drawn, please segment something first.');
                } else if ($scope.selected_classification === null) {
                    $window.alert('There is no label associated with the active polygon, please choose a label first.');
                } else {
                    $scope.regions.svg.forEach(function(p) {
                        var region = {};
                        var region_points = [];

                        //Get points
                        for (var i = 0; i < p.length; i++) {
                            region_points.push(
                                {
                                    "x": p[i][0],
                                    "y": p[i][1],
                                    "order": i
                                }
                            );
                        }

                        region.anatomy = $scope.selected_classification.id;
                        region.image = $scope.selected_image.id;
                        region.points = region_points;

                        regions.push(region)
                    });

                    // How to get results of post to conditionally get ready for next
                    var post_region_response = Subregion.save(regions);

                    var new_regions = [];
                    var new_region_points =[];

                    post_region_response.$promise.then(function(data) {
                        data.forEach(function(region) {
                            // empty array for our new region
                            new_region_points = [];

                            region.points.forEach(function(p) {
                                new_region_points.push(
                                    [
                                        p.x,
                                        p.y
                                    ]
                                );
                            });

                            new_regions.push(new_region_points);
                        });

                        if (new_regions.length > 0) {
                            $scope.regions.svg = new_regions;
                            $scope.enabled = false;
                            $scope.image_set = ImageSet.get(
                                {
                                    'image_set_id': $routeParams.image_set_id
                                }
                            );
                        }
                    }, function (error) {
                        $window.alert(JSON.stringify(error.data, null, 4))
                    });
                }
            };

            $scope.train_model = function () {
                TrainModel.save(
                    {
                        'imageset': $scope.image_set.id
                    }
                );
            };

            $scope.classify_region = function () {
                var classify_promises = [];

                $scope.regions.svg.forEach(function (region) {
                    var payload = {};
                    var points = [];

                    //Get points
                    for (var i = 0; i < region.length; i++) {
                        points.push(
                            {
                                "x": region[i][0],
                                "y": region[i][1],
                                "order": i
                            }
                        );
                    }
                    payload.image_id = $scope.selected_image.id;
                    payload.points = points;

                    // How to get results of post to conditionally get ready for next
                    classify_promises.push(Classify.save(payload).$promise);
                });

                $q.all(classify_promises).then(function (results) {
                    console.log(results);
                    $window.alert(JSON.stringify(results, null, 4));
                });
            }
        }
    ]
);
<|endoftext|>


<commit_before>/*==================================================
 *  Simile Timeplot API
 *
 *  Include Timeplot in your HTML file as follows:
 *    <script src="http://static.simile.mit.edu/timeplot/api/timeplot-api.js" type="text/javascript"></script>
 *
 *==================================================*/

(function() {

    var debug = false;

    if (document.location.search.length > 0) {
        var params = document.location.search.substr(1).split("&");
        for (var i = 0; i < params.length; i++) {
            if (params[i] == "debug") {
                debug = true;
            }
        }
    }

    var loadMe = function() {

        if (typeof window.Timeplot != "undefined") {
            return;
        }

        window.Timeplot = {
            loaded:     false,
            params:     { bundle: true, autoCreate: true },
            namespace:  "http://simile.mit.edu/2007/06/timeplot#",
            importers:  {}
        };

        var javascriptFiles = [
            "timeplot.js",
            "plot.js",
            "sources.js",
            "geometry.js",
            "color.js",
            "math.js",
            "processor.js"
        ];
        var cssFiles = [
            "timeplot.css"
        ];

        var locales = [ "en" ];

        var defaultClientLocales = ("language" in navigator ? navigator.language : navigator.browserLanguage).split(";");
        for (var l = 0; l < defaultClientLocales.length; l++) {
            var locale = defaultClientLocales[l];
            if (locale != "en") {
                var segments = locale.split("-");
                if (segments.length > 1 && segments[0] != "en") {
                    locales.push(segments[0]);
                }
                locales.push(locale);
            }
        }

        var paramTypes = { bundle:Boolean, js:Array, css:Array, autoCreate:Boolean };
        if (typeof Timeplot_urlPrefix == "string") {
            Timeplot.urlPrefix = Timeplot_urlPrefix;
            if ("Timeplot_parameters" in window) {
                SimileAjax.parseURLParameters(Timeplot_parameters, Timeplot.params, paramTypes);
            }
        } else {
            var url = SimileAjax.findScript(document, "/timeplot-api.js");
            if (url == null) {
                Timeplot.error = new Error("Failed to derive URL prefix for Simile Timeplot API code files");
                return;
            }
            Timeplot.urlPrefix = url.substr(0, url.indexOf("timeplot-api.js"));

            SimileAjax.parseURLParameters(url, Timeplot.params, paramTypes);
        }

        if (Timeplot.params.locale) { // ISO-639 language codes,
            // optional ISO-3166 country codes (2 characters)
            if (Timeplot.params.locale != "en") {
                var segments = Timeplot.params.locale.split("-");
                if (segments.length > 1 && segments[0] != "en") {
                    locales.push(segments[0]);
                }
                locales.push(Timeplot.params.locale);
            }
        }

        var scriptURLs = Timeplot.params.js || [];
        var cssURLs = Timeplot.params.css || [];

        // External components
        scriptURLs.push(debug ?
                "/timeline/api/timeline-api.js?bundle=false" :
                "http://static.simile.mit.edu/timeline/api/timeline-api.js?bundle=true");

        // Core scripts and styles
        if (Timeplot.params.bundle) {
            scriptURLs.push(Timeplot.urlPrefix + "timeplot-bundle.js");
            cssURLs.push(Timeplot.urlPrefix + "timeplot-bundle.css");
        } else {
            SimileAjax.prefixURLs(scriptURLs, Timeplot.urlPrefix + "scripts/", javascriptFiles);
            SimileAjax.prefixURLs(cssURLs, Timeplot.urlPrefix + "styles/", cssFiles);
        }

        // Localization
        for (var i = 0; i < locales.length; i++) {
            scriptURLs.push(Timeplot.urlPrefix + "locales/" + locales[i] + "/locale.js");
        };

        if (Timeplot.params.callback) {
            window.SimileAjax_onLoad = function() {
                eval(Timeplot.params.callback + "()");
            }
        }

        SimileAjax.includeJavascriptFiles(document, "", scriptURLs);
        SimileAjax.includeCssFiles(document, "", cssURLs);
        Timeplot.loaded = true;
    };

    // Load SimileAjax if it's not already loaded
    if (typeof SimileAjax == "undefined") {
        window.SimileAjax_onLoad = loadMe;

        var url = debug ?
            "/ajax/api-2.0/simile-ajax-api.js?bundle=false" :
            "http://static.simile.mit.edu/ajax/api-2.0/simile-ajax-api.js?bundle=true";

        var createScriptElement = function() {
            var script = document.createElement("script");
            script.type = "text/javascript";
            script.language = "JavaScript";
            script.src = url;
            document.getElementsByTagName("head")[0].appendChild(script);
        }

        if (document.body == null) {
            try {
                document.write("<script src='" + url + "' type='text/javascript'></script>");
            } catch (e) {
                createScriptElement();
            }
        } else {
            createScriptElement();
        }
    } else {
        loadMe();
    }
})();
<commit_msg>fixing the link in the comments<commit_after>/*==================================================
 *  Simile Timeplot API
 *
 *  Include Timeplot in your HTML file as follows:
 *    <script src="http://static.simile.mit.edu/timeplot/api/1.0/timeplot-api.js" type="text/javascript"></script>
 *
 *==================================================*/

(function() {

    var debug = false;

    if (document.location.search.length > 0) {
        var params = document.location.search.substr(1).split("&");
        for (var i = 0; i < params.length; i++) {
            if (params[i] == "debug") {
                debug = true;
            }
        }
    }

    var loadMe = function() {

        if (typeof window.Timeplot != "undefined") {
            return;
        }

        window.Timeplot = {
            loaded:     false,
            params:     { bundle: true, autoCreate: true },
            namespace:  "http://simile.mit.edu/2007/06/timeplot#",
            importers:  {}
        };

        var javascriptFiles = [
            "timeplot.js",
            "plot.js",
            "sources.js",
            "geometry.js",
            "color.js",
            "math.js",
            "processor.js"
        ];
        var cssFiles = [
            "timeplot.css"
        ];

        var locales = [ "en" ];

        var defaultClientLocales = ("language" in navigator ? navigator.language : navigator.browserLanguage).split(";");
        for (var l = 0; l < defaultClientLocales.length; l++) {
            var locale = defaultClientLocales[l];
            if (locale != "en") {
                var segments = locale.split("-");
                if (segments.length > 1 && segments[0] != "en") {
                    locales.push(segments[0]);
                }
                locales.push(locale);
            }
        }

        var paramTypes = { bundle:Boolean, js:Array, css:Array, autoCreate:Boolean };
        if (typeof Timeplot_urlPrefix == "string") {
            Timeplot.urlPrefix = Timeplot_urlPrefix;
            if ("Timeplot_parameters" in window) {
                SimileAjax.parseURLParameters(Timeplot_parameters, Timeplot.params, paramTypes);
            }
        } else {
            var url = SimileAjax.findScript(document, "/timeplot-api.js");
            if (url == null) {
                Timeplot.error = new Error("Failed to derive URL prefix for Simile Timeplot API code files");
                return;
            }
            Timeplot.urlPrefix = url.substr(0, url.indexOf("timeplot-api.js"));

            SimileAjax.parseURLParameters(url, Timeplot.params, paramTypes);
        }

        if (Timeplot.params.locale) { // ISO-639 language codes,
            // optional ISO-3166 country codes (2 characters)
            if (Timeplot.params.locale != "en") {
                var segments = Timeplot.params.locale.split("-");
                if (segments.length > 1 && segments[0] != "en") {
                    locales.push(segments[0]);
                }
                locales.push(Timeplot.params.locale);
            }
        }

        var scriptURLs = Timeplot.params.js || [];
        var cssURLs = Timeplot.params.css || [];

        // External components
        scriptURLs.push(debug ?
                "/timeline/api/timeline-api.js?bundle=false" :
                "http://static.simile.mit.edu/timeline/api/timeline-api.js?bundle=true");

        // Core scripts and styles
        if (Timeplot.params.bundle) {
            scriptURLs.push(Timeplot.urlPrefix + "timeplot-bundle.js");
            cssURLs.push(Timeplot.urlPrefix + "timeplot-bundle.css");
        } else {
            SimileAjax.prefixURLs(scriptURLs, Timeplot.urlPrefix + "scripts/", javascriptFiles);
            SimileAjax.prefixURLs(cssURLs, Timeplot.urlPrefix + "styles/", cssFiles);
        }

        // Localization
        for (var i = 0; i < locales.length; i++) {
            scriptURLs.push(Timeplot.urlPrefix + "locales/" + locales[i] + "/locale.js");
        };

        if (Timeplot.params.callback) {
            window.SimileAjax_onLoad = function() {
                eval(Timeplot.params.callback + "()");
            }
        }

        SimileAjax.includeJavascriptFiles(document, "", scriptURLs);
        SimileAjax.includeCssFiles(document, "", cssURLs);
        Timeplot.loaded = true;
    };

    // Load SimileAjax if it's not already loaded
    if (typeof SimileAjax == "undefined") {
        window.SimileAjax_onLoad = loadMe;

        var url = debug ?
            "/ajax/api-2.0/simile-ajax-api.js?bundle=false" :
            "http://static.simile.mit.edu/ajax/api-2.0/simile-ajax-api.js?bundle=true";

        var createScriptElement = function() {
            var script = document.createElement("script");
            script.type = "text/javascript";
            script.language = "JavaScript";
            script.src = url;
            document.getElementsByTagName("head")[0].appendChild(script);
        }

        if (document.body == null) {
            try {
                document.write("<script src='" + url + "' type='text/javascript'></script>");
            } catch (e) {
                createScriptElement();
            }
        } else {
            createScriptElement();
        }
    } else {
        loadMe();
    }
})();
<|endoftext|>


<commit_before>
function SubmitFormField($scope, $element) {
  var loginForm = $($element);
  //console.log(loginForm);
  $scope.isInvalid = function() {
    return !loginForm.form('validate form');
  };

  $scope.checkField = function () {
    if (this.isInvalid()) {
      return false;
    }

    alert("Register was clicked!");
    return true;
  };
}

$(function () {

	var globalSectionId = 5;
	$( "#sortable" ).sortable({
      placeholder: "ui-state-highlight"
    });
    $( "#sortable" ).disableSelection();

    $('#lol').click(function () {
    	var formClientData = {};

    	$('.uis').each(function () {
    		var data='', object = {},
    		    id = $(this).attr('href'),
    			emptySection = true,
    			heading = $(id).find('.label--text.heading').text();
    		$(id).find('.form-control').each(function () {
    			if($(this).val()!=null && $(this).val()!=''){
		        	/*if (data=='')
		        		data = $(id +' .form-control').index(this) + '|^|' + $(this).val();
		        	else
			        	data = data + '|&|' + $(id +' .form-control').index(this) + '|^|' + $(this).val();
    				*/
    				object[$(this).attr('name')] = $(this).val();
    				emptySection = false;
    			}
		    });
		    if(!emptySection){
		    	formClientData[heading] = object;
		    }
    	});
    	//console.log(formClientData['Basic information']);
    	//formClientData = JSON.stringify(formClientData);
    	buildoPreviewCv(formClientData);

    });

    $('.save--form').click(function () {
    	var jsonFormData = buildoPreviewCv();
    	// save to DB
    	$.ajax({
		  url: "http://myapp.com:8000s/users/save-data",
		  context: document.body
		}).done(function() {
		  $( this ).addClass( "done" );
		});
    });

    $('.add-new-job').click(function () {
    	var newJobSection = '

' + $('.cv-work-experience').html()+'
';
		$('.add-new-job').before(newJobSection);
        dynamicWorkexPopoverBinder();

    });

	$('.add-new-education').click(function (){
		var newEduSection = '

' + $('.cv-education').html()+'
';
		$('.add-new-education').before(newEduSection);
	});

    $(document).on('click', '.save-section-title' ,function () {
    	console.log($('.tab-pane.active').attr('id'));
    	var text = $('.prompt-section-title').val();
    	$('.tab-pane.active .label--text.heading').text(text);
    	// change sortable li's
    	text = '  ' + text;
    	$('#sortable li[href="#'+$('.tab-pane.active').attr('id')+'"').html(text);
    	$('#myModal').modal('hide');
    });
    $(document).on('click', '.save-font-size' ,function () {
    	var text = $('.prompt-section-title').val() + 'px';
    	$('.tab-pane.active .label--text.heading').css({'font-size':text});
    });

    $(document).on('click', '.fa.fa-pencil' ,function () {
    	$('.modal-footer button:nth-child(2)').attr('class', 'btn btn-primary save-section-title');
    });

    $(document).on('click', '.fa.fa-text-height' ,function () {
    	$('.modal-footer button:nth-child(2)').attr('class', 'btn btn-primary save-font-size');
    });
    $(document).on('click', '.fa.fa-font' ,function () {
    	console.log($('#fontSel').click());
    });
    $(document).on('change', '.fontSel', function(){
    	console.log('c');
	  	$('.tab-pane.active .label--text.heading').css({'color':$(this).val()});
	});
    $(document).on('click', '.fa.fa-times' ,function () {
    	var id = $('.tab-pane.active').attr('id');
    	$('#'+ $('.tab-pane.active').attr('id')).remove();
    	console.log($('#sortable section li[href="#'+id+'"').parent().prev().html());
    	if($('#sortable li[href="#'+id+'"').prev()) {
	    	$('#sortable li[href="#'+id+'"').prev().click();
	    }
	    else
	    	$('#sortable li[href="#1"]').click();
	    $('#sortable li[href="#'+id+'"').parent().remove();
    });

	var newEntry = '
'
		+
		''
			+
  '
'+
	    'Heading'+
	    '
' +
	    	'<input type="text" class="form-control" name="heading" placeholder="Enter Heading">'+
	    '
'+
	  '
'+
	  '
'+
	    'Content'+
	    '
'+
	    	'<textarea class="form-control" name="content" placeholder="Enter Content"></textarea>'+
	    '
'+
	  '
'+

'
';

function buildoPreviewCv(f) {
	// view cv in modal view container
	var renderFormData = '
';

    $('#myModalPreview').modal('show');

    for (var key in f) {
    	console.log(key);

	    if(key == 'Basic information') {
	    	renderFormData = '
'+
    			'
';
	    	if(f[key]['cv__fullname'])
		    	renderFormData = renderFormData + String(f['Basic information']['cv__fullname']);
	   		renderFormData = renderFormData +'
'+
	   		'
';
	    	if(f[key]['cv__address'])
		        renderFormData = renderFormData + '
Address: '+f['Basic information']['cv__address']+'
';
		    if(f[key]['cv__contact'])
		        renderFormData = renderFormData + '
Contact: '+f['Basic information']['cv__contact']+'
';
		    if(f[key]['cv__email'])
		        renderFormData = renderFormData + '
Email: '+f['Basic information']['cv__email']+'
';
		    if(f[key]['cv__website'])
		        renderFormData = renderFormData + '
Website: '+f['Basic information']['cv__website']+'
';
	    	renderFormData = renderFormData + '
'+
				'

';
	    }

	    else if(key == 'Work Experience') {
	    	renderFormData = renderFormData + '
' +
    			'
'+
        		''+ key +'' +
			    '
'+
			    '
'+
			        '
'+
			            '
';
			if(f[key]['cv__jobtitle'])
				renderFormData = renderFormData + ''+f[key]['cv__jobtitle']+'';
			renderFormData = renderFormData + '
'+
            '
';
            if(f[key]['cv__companyname'])
            	renderFormData = renderFormData + ''+f[key]['cv__companyname']+'';
            renderFormData = renderFormData +'
'+
          		'
';
            if(f[key]['cv__companystart'] && f[key]['cv__companyend']){
                renderFormData = renderFormData + ''+f[key]['cv__companystart'] +'' +
                ''+f[key]['cv__companyend'] +'';
            }
            renderFormData = renderFormData + '
' +
        	'
';
        	if(f[key]['cv__companydesc'])
        		renderFormData = renderFormData + '
'+f[key]['cv__companydesc']+'
';

    		renderFormData = renderFormData + '
'+
				'
';
	    }
	    else if(key == 'Education') {
	    	renderFormData = renderFormData + '
'+
    			'
';
        	if(f[key])
        		renderFormData = renderFormData +''+key+'';

    		renderFormData = renderFormData + '
'+
    			'
';
        	if(f[key]['cv__coursename'])
        		renderFormData = renderFormData +''+f[key]['cv__coursename'];
    		if(f[key]['cv__eduperiod'])
    			renderFormData = renderFormData + ',' +f[key]['cv__eduperiod'];
    		renderFormData = renderFormData + '';

    		if(f[key]['cv__instiname'])
    			renderFormData = renderFormData + '
'+f[key]['cv__instiname']+'';
    		if(f[key]['cv__instidescription'])
    			renderFormData = renderFormData + '
'+f[key]['cv__instidescription']+'
';

    		renderFormData = renderFormData + '
';
				'
';
	    }
	    else if(key == 'Achievements') {
	    	renderFormData = renderFormData + '
'+
    			'
';
        	if(f[key])
        		renderFormData = renderFormData +''+key+'';

    		renderFormData = renderFormData + '
'+
    			'
';
        	if(f[key]['cv__achievemnet'])
        		renderFormData = renderFormData +'
'+f[key]['cv__achievemnet']+'
';
    		renderFormData = renderFormData + '
'+
				'
';
	    }
	    else {
	    	renderFormData = renderFormData + '
'+
    			'
';
        	if(f[key])
        		renderFormData = renderFormData +''+key+'';

    		renderFormData = renderFormData + '
'+
    			'
';
        	if(f[key]['cv__fielddata'])
        		renderFormData = renderFormData +'
'+f[key]['cv__fielddata']+'
';
    		renderFormData = renderFormData + '
'+
				'
';
	    }

	}
	renderFormData = renderFormData + '
'
    $('.preview-generated-cv').html(renderFormData);

}
	function addSectionDetail(globalId) {
		var sectionAddData = ''+
			'
'+
				'New Section'+
				''+
					' '+
					''+
				''+
				'
'+
				'
\
					Detail\
					<textarea class="form-control mod-text-box" rows="3" name="cv__fielddata"></textarea>\

'+
				'
'+
				'<button class="btn btn-primary add--entry">Add Entry</button>'+
			'
';

				$('.tab-content').append(sectionAddData);

	}

	$('.add--new').click(function () {
		$('.btn-success.submit-form').before(newSection);
	});
	$(document).on('click', '.btn.add--entry', function () {

	});
	$('.add--section').click(function () {
		var newSection = '

 New Section

';
		$('#sortable').append(newSection);
		addSectionDetail(globalSectionId);
		$('li.uis').last().click();
		globalSectionId++;
	});

});

<commit_msg>serialized work ex entries to json<commit_after>
function SubmitFormField($scope, $element) {
  var loginForm = $($element);
  //console.log(loginForm);
  $scope.isInvalid = function() {
    return !loginForm.form('validate form');
  };

  $scope.checkField = function () {
    if (this.isInvalid()) {
      return false;
    }

    alert("Register was clicked!");
    return true;
  };
}

$(function () {

	var globalSectionId = 5;
	$( "#sortable" ).sortable({
      placeholder: "ui-state-highlight"
    });
    $( "#sortable" ).disableSelection();

    $('#preview').click(function () {
    	var formClientData = {};

    	$('.sortable-tab--field').each(function () {
    		var data='', object = {},
    		    id = $(this).attr('href'),
    			emptySection = true,
    			heading = $(id).find('.label--text.heading').text();
    		//console.log(id);
            if(id == '#2') {
                var workExObject = {},
                    workExArray = [];
                $(id).find('.cv-work-experience').each(function (i) {
                    $('.cv-work-experience:eq('+i+') .form-control').each(function (i) {
                        if($(this).val()!=null && $(this).val()!=''){
                            workExObject[$(this).attr('name')] = $(this).val();
                            emptySection = false;
                        }
                    });
                    if(!emptySection){
                        workExArray.push(workExObject);
                        workExObject = {};
                    }
                });
                if(workExArray.length>0){
                    formClientData[heading] = workExArray;
                }
            }
            else {
                $(id).find('.form-control').each(function () {
        			if($(this).val()!=null && $(this).val()!=''){
        				object[$(this).attr('name')] = $(this).val();
        				emptySection = false;
        			}
    		    });
                if(!emptySection){
                    formClientData[heading] = object;
                }
            }

    	});
    	console.log(formClientData);
    	//formClientData = JSON.stringify(formClientData);
    	buildoPreviewCv(formClientData);

    });

    $('.save--form').click(function () {
    	//var jsonFormData = buildoPreviewCv();
    	// save to DB
    	$.ajax({
		  url: "http://myapp.com:8000s/users/save-data",
		  context: document.body
		}).done(function() {
		  $( this ).addClass( "done" );
		});
    });

    $('.add-new-job').click(function () {
    	var newJobSection = '

' + $('.cv-work-experience').html()+'
';
		$('.add-new-job').before(newJobSection);
        dynamicWorkexPopoverBinder();

    });

	$('.add-new-education').click(function (){
		var newEduSection = '

' + $('.cv-education').html()+'
';
		$('.add-new-education').before(newEduSection);
	});

    $(document).on('click', '.save-section-title' ,function () {
    	console.log($('.tab-pane.active').attr('id'));
    	var text = $('.prompt-section-title').val();
    	$('.tab-pane.active .label--text.heading').text(text);
    	// change sortable li's
    	text = '  ' + text;
    	$('#sortable li[href="#'+$('.tab-pane.active').attr('id')+'"').html(text);
    	$('#myModal').modal('hide');
    });
    $(document).on('click', '.save-font-size' ,function () {
    	var text = $('.prompt-section-title').val() + 'px';
    	$('.tab-pane.active .label--text.heading').css({'font-size':text});
    });

    $(document).on('click', '.fa.fa-pencil' ,function () {
    	$('.modal-footer button:nth-child(2)').attr('class', 'btn btn-primary save-section-title');
    });

    $(document).on('click', '.fa.fa-text-height' ,function () {
    	$('.modal-footer button:nth-child(2)').attr('class', 'btn btn-primary save-font-size');
    });
    $(document).on('click', '.fa.fa-font' ,function () {
    	console.log($('#fontSel').click());
    });
    $(document).on('change', '.fontSel', function(){
    	console.log('c');
	  	$('.tab-pane.active .label--text.heading').css({'color':$(this).val()});
	});
    $(document).on('click', '.fa.fa-times' ,function () {
    	var id = $('.tab-pane.active').attr('id');
    	$('#'+ $('.tab-pane.active').attr('id')).remove();
    	console.log($('#sortable section li[href="#'+id+'"').parent().prev().html());
    	if($('#sortable li[href="#'+id+'"').prev()) {
	    	$('#sortable li[href="#'+id+'"').prev().click();
	    }
	    else
	    	$('#sortable li[href="#1"]').click();
	    $('#sortable li[href="#'+id+'"').parent().remove();
    });

	var newEntry = '
'
		+
		''
			+
  '
'+
	    'Heading'+
	    '
' +
	    	'<input type="text" class="form-control" name="heading" placeholder="Enter Heading">'+
	    '
'+
	  '
'+
	  '
'+
	    'Content'+
	    '
'+
	    	'<textarea class="form-control" name="content" placeholder="Enter Content"></textarea>'+
	    '
'+
	  '
'+

'
';

function buildoPreviewCv(f) {
	// view cv in modal view container
	var renderFormData = '
';

    $('#myModalPreview').modal('show');

    for (var key in f) {
    	console.log(key);

	    if(key == 'Basic information') {
	    	renderFormData = '
'+
    			'
';
	    	if(f[key]['cv__fullname'])
		    	renderFormData = renderFormData + String(f['Basic information']['cv__fullname']);
	   		renderFormData = renderFormData +'
'+
	   		'
';
	    	if(f[key]['cv__address'])
		        renderFormData = renderFormData + '
Address: '+f['Basic information']['cv__address']+'
';
		    if(f[key]['cv__contact'])
		        renderFormData = renderFormData + '
Contact: '+f['Basic information']['cv__contact']+'
';
		    if(f[key]['cv__email'])
		        renderFormData = renderFormData + '
Email: '+f['Basic information']['cv__email']+'
';
		    if(f[key]['cv__website'])
		        renderFormData = renderFormData + '
Website: '+f['Basic information']['cv__website']+'
';
	    	renderFormData = renderFormData + '
'+
				'

';
	    }

	    else if(key == 'Work Experience') {
	    	renderFormData = renderFormData + '
' +
    			'
'+
        		''+ key +'' +
			    '
';

            for (var work in f[key]) {
    			renderFormData = renderFormData + '
'+
    			    '
'+
    			       '
';
    			if(f[key][work]['cv__jobtitle'])
    				renderFormData = renderFormData + ''+f[key][work]['cv__jobtitle']+'';
    			renderFormData = renderFormData + '
'+
                '
';
                if(f[key][work]['cv__companyname'])
                	renderFormData = renderFormData + ''+f[key][work]['cv__companyname']+'';
                renderFormData = renderFormData +'
'+
              		'
';
                if(f[key][work]['cv__companystart'] && f[key][work]['cv__companyend']){
                    renderFormData = renderFormData + ''+f[key][work]['cv__companystart'] +'' +
                    ''+f[key][work]['cv__companyend'] +'';
                }                renderFormData = renderFormData + '
' +
            	'
';
            	if(f[key][work]['cv__companydesc'])
            		renderFormData = renderFormData + '
'+f[key][work]['cv__companydesc']+'
';

        		renderFormData = renderFormData + '
'+
    				'
';
            }
	    }
	    else if(key == 'Education') {
	    	renderFormData = renderFormData + '
'+
    			'
';
        	if(f[key])
        		renderFormData = renderFormData +''+key+'';

    		renderFormData = renderFormData + '
'+
    			'
';
        	if(f[key]['cv__coursename'])
        		renderFormData = renderFormData +''+f[key]['cv__coursename'];
    		if(f[key]['cv__eduperiod'])
    			renderFormData = renderFormData + ',' +f[key]['cv__eduperiod'];
    		renderFormData = renderFormData + '';

    		if(f[key]['cv__instiname'])
    			renderFormData = renderFormData + '
'+f[key]['cv__instiname']+'';
    		if(f[key]['cv__instidescription'])
    			renderFormData = renderFormData + '
'+f[key]['cv__instidescription']+'
';

    		renderFormData = renderFormData + '
';
				'
';
	    }
	    else if(key == 'Achievements') {
	    	renderFormData = renderFormData + '
'+
    			'
';
        	if(f[key])
        		renderFormData = renderFormData +''+key+'';

    		renderFormData = renderFormData + '
'+
    			'
';
        	if(f[key]['cv__achievemnet'])
        		renderFormData = renderFormData +'
'+f[key]['cv__achievemnet']+'
';
    		renderFormData = renderFormData + '
'+
				'
';
	    }
	    else {
	    	renderFormData = renderFormData + '
'+
    			'
';
        	if(f[key])
        		renderFormData = renderFormData +''+key+'';

    		renderFormData = renderFormData + '
'+
    			'
';
        	if(f[key]['cv__fielddata'])
        		renderFormData = renderFormData +'
'+f[key]['cv__fielddata']+'
';
    		renderFormData = renderFormData + '
'+
				'
';
	    }

	}
	renderFormData = renderFormData + '
'
    $('.preview-generated-cv').html(renderFormData);

}
	function addSectionDetail(globalId) {
		var sectionAddData = ''+
			'
'+
				'New Section'+
				''+
					' '+
					''+
				''+
				'
'+
				'
\
					Detail\
					<textarea class="form-control mod-text-box" rows="3" name="cv__fielddata"></textarea>\

'+
				'
'+
				'<button class="btn btn-primary add--entry">Add Entry</button>'+
			'
';

				$('.tab-content').append(sectionAddData);

	}

	$('.add--new').click(function () {
		$('.btn-success.submit-form').before(newSection);
	});
	$(document).on('click', '.btn.add--entry', function () {

	});
	$('.add--section').click(function () {
		var newSection = '

 New Section

';
		$('#sortable').append(newSection);
		addSectionDetail(globalSectionId);
		$('li.sortable-tab--field').last().click();
		globalSectionId++;
	});

});

<|endoftext|>


<commit_before>function constrainFeatures(allFeaturesList, selectedsystems, showpolicies) {
    // constrain output ot only features in the list.
    var constraintedFeatures = { "type": "FeatureCollection", "features": [] };
    var allFeatures = JSON.parse(allFeaturesList);
    var selectedsystems = JSON.parse(selectedsystems);
    var af = allFeatures.features;
    var featlen = af.length;
    var counter = 0;
    var fullproc = featlen;
    for (var d = 0; d < featlen; d++) {

        var curfeatprop = af[d].properties;
        var curFeatSys = curfeatprop.sysname;

        var isPolicy = curfeatprop.isPolicy;
        console.log(curfeatprop, isPolicy)
        if (isPolicy && parseInt(showpolicies)) {
            constraintedFeatures.features.push(af[d]);

        } else {
            if (selectedsystems.indexOf(curFeatSys) > -1) {
                constraintedFeatures.features.push(af[d]);
            }
        }
        counter += 1;
        self.postMessage({
            'percentcomplete': parseInt((100 * counter) / fullproc),
            'mode': 'status',
        });
    }

    self.postMessage({
        'polygons': JSON.stringify(constraintedFeatures)
    });
}

self.onmessage = function(e) {
    constrainFeatures(e.data.allFeaturesList, e.data.selectedsystems, e.data.showpolicies);
}<commit_msg>Update constrainGeneratedFeatures.js<commit_after>function constrainFeatures(allFeaturesList, selectedsystems, showpolicies) {
    // constrain output ot only features in the list.
    var constraintedFeatures = { "type": "FeatureCollection", "features": [] };
    var allFeatures = JSON.parse(allFeaturesList);
    var selectedsystems = JSON.parse(selectedsystems);
    var af = allFeatures.features;
    var featlen = af.length;
    var counter = 0;
    var fullproc = featlen;
    for (var d = 0; d < featlen; d++) {

        var curfeatprop = af[d].properties;
        var curFeatSys = curfeatprop.sysname;

        var isPolicy = curfeatprop.isPolicy;
        console.log(curfeatprop, isPolicy, showpolicies)
        if (isPolicy && parseInt(showpolicies)) {
            constraintedFeatures.features.push(af[d]);

        } else {
            if (selectedsystems.indexOf(curFeatSys) > -1) {
                constraintedFeatures.features.push(af[d]);
            }
        }
        counter += 1;
        self.postMessage({
            'percentcomplete': parseInt((100 * counter) / fullproc),
            'mode': 'status',
        });
    }

    self.postMessage({
        'polygons': JSON.stringify(constraintedFeatures)
    });
}

self.onmessage = function(e) {
    constrainFeatures(e.data.allFeaturesList, e.data.selectedsystems, e.data.showpolicies);
}<|endoftext|>


<commit_before>/*extern JSON, JsonML */
/*
	JsonML2.js

	Created: 2006-11-09-0116
	Modified: 2008-05-25-2326

	Released under an open-source license:
	http://jsonml.org/License.htm

    This file adds these methods to JavaScript:

        JsonML.parse(string|array, filter)

            This method produces a tree of DOM elements from a JsonML tree. The
            array must not contain any cyclical references.

            The optional filter parameter is a function which can filter and
            transform the results. It receives each of the DOM nodes, and
            its return value is used instead of the original value. If it
            returns what it received, then structure is not modified. If it
            returns undefined then the member is deleted.

			This is useful for binding unobtrusive JavaScript to the generated
			DOM elements.

            Example:

            // Parses the structure. If an element has a specific CSS value then
            // takes appropriate action: Remove from results, add special event
            // handlers, or bind to a custom component.

            var myUI = JsonML.parse(myUITemplate, function (elem) {
				if (elem.className.indexOf("Remove-Me") >= 0) {
					// this will remove from resulting DOM tree
					return undefined;
				}

				if (elem.tagName && elem.tagName.toLowerCase() === "a" &&
					elem.className.indexOf("External-Link") >= 0) {
					// this is the equivalent of target="_blank"
					elem.onclick = function(evt) {
						window.open(elem.href); return false;
					};

				} else if (elem.className.indexOf("Fancy-Widgit") >= 0) {
					// bind to a custom component
					FancyWidgit.bindDOM(elem);
				}
				return elem;
			});

*/

if ("undefined" === typeof JsonML) {
	window.JsonML = {};
}

JsonML.parse = function(/*JsonML*/ jml, /*element function(element)*/ filter) {

	//attribute name mapping
	var am = {
		rowspan : "rowSpan",
		colspan : "colSpan",
		cellpadding : "cellPadding",
		cellspacing : "cellSpacing",
		tabindex : "tabIndex",
		accesskey : "accessKey",
		hidefocus : "hideFocus",
		usemap : "useMap",
		maxlength : "maxLength",
		readonly : "readOnly",
		contenteditable : "contentEditable"
		// can add more attributes here as needed
	};

	//addAttributes
	/*void*/ function aa(/*element*/ el, /*Object*/ a) {
		// for each attributeName
		for (var an in a) {
			if (an && "string" === typeof a[an]) {
				if (an.toLowerCase() === "style") {
					if ("undefined" !== typeof el.style.cssText) {
						el.style.cssText = a[an];
					} else {
						el.style = a[an];
					}
				} else if (an.toLowerCase() === "class") {
					el.className = a[an];
				} else if (am[an.toLowerCase()]) {
					el.setAttribute(am[an.toLowerCase()], a[an]);
				} else {
					el.setAttribute(an, a[an]);
				}
			}
		}
	}

	//appendChild
	/*void*/ function ac(/*element*/ el, /*Array or String*/ c) {
		var ct, tb;
		if (c) {
			if (el.tagName.toLowerCase() === "table" && el.tBodies) {
				// in IE must explicitly nest TDs in TBODY
				ct = c.tagName ? c.tagName.toLowerCase() : null;// child tagName
				if (ct && ct!=="tbody" && ct!=="thead") {
					// insert in last tbody
					tb = el.tBodies.length>0 ? el.tBodies[el.tBodies.length-1] : null;// tBody
					if (!tb) {
						tb = document.createElement("tbody");
						el.appendChild(tb);
					}
					tb.appendChild(c);
				}
			} else {
				el.appendChild(c);
			}
		}
	}

	//JsonML.parse
	/*element*/ function p(/*JsonML*/ jml) {
		if (!jml) {
			return null;
		}
		if (typeof(jml) === "string") {
			return document.createTextNode(jml);
		}

		if (!(jml instanceof Array) || jml.length < 1 || "string" !== typeof jml[0]) {
			throw new Error("JsonML.parse");
		}

		var t = jml[0]; // tagName
		var x = (t.toLowerCase() === "script"); // check for scripts
		var el = x ? null : document.createElement(t);

		for (var i=1; i<jml.length; i++) {
			if (!x) {
				if (jml[i] instanceof Array || "string" === typeof jml[i]) {
					// append children
					ac(el, p(jml[i]));
				} else if ("object" === typeof jml[i]) {
					// add attributes
					aa(el, jml[i]);
				}
			//} else if (typeof(jml[i]) === "string") {
				/*	JSLint: "eval is evil"
					uncomment at your own risk, executes script elements */
				//eval( "(" + jml[i] + ")" );
			}
		}

		return (el && "function" === typeof filter) ? filter(el) : el;
	}

	if (jml instanceof Array) {
		return p(jml);
	} else if ("string" === typeof jml) {

		try {
			jml = JSON.parse(jml);
		} catch (ex) {
			return null;
		}

		if (jml instanceof Array) {
			return JsonML.parse(jml, filter);
		}
	}
	return null;
};
<commit_msg>- JSLint updates<commit_after>/*global JSON, JsonML */
/*
	JsonML2.js

	Created: 2006-11-09-0116
	Modified: 2008-05-25-2326

	Released under an open-source license:
	http://jsonml.org/License.htm

    This file adds these methods to JavaScript:

        JsonML.parse(string|array, filter)

            This method produces a tree of DOM elements from a JsonML tree. The
            array must not contain any cyclical references.

            The optional filter parameter is a function which can filter and
            transform the results. It receives each of the DOM nodes, and
            its return value is used instead of the original value. If it
            returns what it received, then structure is not modified. If it
            returns undefined then the member is deleted.

			This is useful for binding unobtrusive JavaScript to the generated
			DOM elements.

            Example:

            // Parses the structure. If an element has a specific CSS value then
            // takes appropriate action: Remove from results, add special event
            // handlers, or bind to a custom component.

            var myUI = JsonML.parse(myUITemplate, function (elem) {
				if (elem.className.indexOf("Remove-Me") >= 0) {
					// this will remove from resulting DOM tree
					return undefined;
				}

				if (elem.tagName && elem.tagName.toLowerCase() === "a" &&
					elem.className.indexOf("External-Link") >= 0) {
					// this is the equivalent of target="_blank"
					elem.onclick = function(evt) {
						window.open(elem.href); return false;
					};

				} else if (elem.className.indexOf("Fancy-Widgit") >= 0) {
					// bind to a custom component
					FancyWidgit.bindDOM(elem);
				}
				return elem;
			});

*/

if ("undefined" === typeof JsonML) {
	window.JsonML = {};
}

JsonML.parse = function(/*JsonML*/ jml, /*element function(element)*/ filter) {

	//attribute name mapping
	var am = {
		rowspan : "rowSpan",
		colspan : "colSpan",
		cellpadding : "cellPadding",
		cellspacing : "cellSpacing",
		tabindex : "tabIndex",
		accesskey : "accessKey",
		hidefocus : "hideFocus",
		usemap : "useMap",
		maxlength : "maxLength",
		readonly : "readOnly",
		contenteditable : "contentEditable"
		// can add more attributes here as needed
	};

	//addAttributes
	/*void*/ function aa(/*element*/ el, /*Object*/ a) {
		// for each attributeName
		for (var an in a) {
			if (an && "string" === typeof a[an]) {
				if (an.toLowerCase() === "style") {
					if ("undefined" !== typeof el.style.cssText) {
						el.style.cssText = a[an];
					} else {
						el.style = a[an];
					}
				} else if (an.toLowerCase() === "class") {
					el.className = a[an];
				} else if (am[an.toLowerCase()]) {
					el.setAttribute(am[an.toLowerCase()], a[an]);
				} else {
					el.setAttribute(an, a[an]);
				}
			}
		}
	}

	//appendChild
	/*void*/ function ac(/*element*/ el, /*Array or String*/ c) {
		var ct, tb;
		if (c) {
			if (el.tagName.toLowerCase() === "table" && el.tBodies) {
				// in IE must explicitly nest TDs in TBODY
				ct = c.tagName ? c.tagName.toLowerCase() : null;// child tagName
				if (ct && ct!=="tbody" && ct!=="thead") {
					// insert in last tbody
					tb = el.tBodies.length>0 ? el.tBodies[el.tBodies.length-1] : null;// tBody
					if (!tb) {
						tb = document.createElement("tbody");
						el.appendChild(tb);
					}
					tb.appendChild(c);
				}
			} else {
				el.appendChild(c);
			}
		}
	}

	//JsonML.parse
	/*element*/ function p(/*JsonML*/ jml) {
		if (!jml) {
			return null;
		}
		if (typeof(jml) === "string") {
			return document.createTextNode(jml);
		}

		if (!(jml instanceof Array) || jml.length < 1 || "string" !== typeof jml[0]) {
			throw new Error("JsonML.parse");
		}

		var t = jml[0]; // tagName
		var x = (t.toLowerCase() === "script"); // check for scripts
		var el = x ? null : document.createElement(t);

		for (var i=1; i<jml.length; i++) {
			if (!x) {
				if (jml[i] instanceof Array || "string" === typeof jml[i]) {
					// append children
					ac(el, p(jml[i]));
				} else if ("object" === typeof jml[i]) {
					// add attributes
					aa(el, jml[i]);
				}
			//} else if (typeof(jml[i]) === "string") {
				/*	JSLint: "eval is evil"
					uncomment at your own risk, executes script elements */
				//eval( "(" + jml[i] + ")" );
			}
		}

		return (el && "function" === typeof filter) ? filter(el) : el;
	}

	if (jml instanceof Array) {
		return p(jml);
	} else if ("string" === typeof jml) {

		try {
			jml = JSON.parse(jml);
		} catch (ex) {
			return null;
		}

		if (jml instanceof Array) {
			return JsonML.parse(jml, filter);
		}
	}
	return null;
};
<|endoftext|>


<commit_before>import AWS from 'aws-sdk';

module.exports = class Sessions {
    constructor() {
        this.SESSION_TABLE = `${process.env.SERVERLESS_PROJECT}-sessions-${process.env.SERVERLESS_STAGE}`;
        this.db = new AWS.DynamoDB.DocumentClient();
    }

    read(id) {
        return new Promise((resolve, reject) => {
            const params = {
                Key: { id },
                TableName: this.SESSION_TABLE,
                ConsistentRead: true
            };

            this.db.get(params, (err, data) => {
                if (err) {
                    console.error(err.toString());
                    return reject(err);
                }

                console.log('db read: ' + JSON.stringify(data));

                return resolve(data.Item.context);
            });
        });
    }

    write(id, context) {
        return new Promise((resolve, reject) => {
            if (!id) {
                return reject(new TypeError('No session ID'));
            }

            // coerce session id to string
            id = id + '';

            const params = {
                TableName: this.SESSION_TABLE,
                Item: {
                    id,
                    context
                }
            };

            console.log('db write: ' + JSON.stringify(context));

            this.db.put(params, (err, data) => {
                if (err) {
                    console.error(err.toString());
                    return reject(err);
                }

                return resolve(context);
            });
        });
    }
}
<commit_msg>Fix 'cannot get context of undefined' exception<commit_after>import AWS from 'aws-sdk';

module.exports = class Sessions {
    constructor() {
        this.SESSION_TABLE = `${process.env.SERVERLESS_PROJECT}-sessions-${process.env.SERVERLESS_STAGE}`;
        this.db = new AWS.DynamoDB.DocumentClient();
    }

    read(id) {
        return new Promise((resolve, reject) => {
            const params = {
                Key: { id },
                TableName: this.SESSION_TABLE,
                ConsistentRead: true
            };

            this.db.get(params, (err, data) => {
                if (err) {
                    console.error(err.toString());
                    return reject(err);
                }

                console.log('db read: ' + JSON.stringify(data));

                if (data.Item !== undefined) {
                    return resolve(data.Item.context);
                } else {
                    // return an empty context for new sessions
                    return resolve({});
                }
            });
        });
    }

    write(id, context) {
        return new Promise((resolve, reject) => {
            if (!id) {
                return reject(new TypeError('No session ID'));
            }

            // coerce session id to string
            id = id + '';

            const params = {
                TableName: this.SESSION_TABLE,
                Item: {
                    id,
                    context
                }
            };

            console.log('db write: ' + JSON.stringify(context));

            this.db.put(params, (err, data) => {
                if (err) {
                    console.error(err.toString());
                    return reject(err);
                }

                return resolve(context);
            });
        });
    }
}
<|endoftext|>


<commit_before>const Actor = require('../../components/actor.js');
const story = require('./story.js');
const c = require('../../components/constants.js');
const utility = require('./utility.js');

const _ = require('lodash');

/*
 * Replaces the constants SOURCE and TARGET with the IDs of the actors that
 * triggered this rule
 */
function populateRuleType(eventTemplate, eventTrigger) {
  if (!eventTemplate || !eventTemplate.length) return false;

  return eventTemplate.map(value => {
    if (value === c.source) {
      return eventTrigger[0];
    } else if (value === c.target) {
      return eventTrigger[2];
    }
    return value;
  });
}

function processElementValue(world, element) {
  let result = [];
  _.each(element, (el) => {
    let actor = utility.getPiece(world, el);

    if (actor !== undefined) {
      actor = actor.name !== undefined ? actor.name : actor;
      result.push(actor);
    }
  }, this);
  result = _.compact(result);
  let body = result.join(' ');
  if (!body.length) {
    return '';
  }
  body += '. ';
  const head = body[0].toUpperCase();
  const tail = body.substring(1);
  body = head + tail;
  return body;
}

function addConsequentActor(world, rule, storyEvent) {
  const consequentActor = new Actor(rule.consequentActor, storyEvent, world);
  consequentActor.parentId = rule.id;
  world.addActor(consequentActor);
}

function runMutations(world, rule, storyEvent) {
  const source = world.getActorById(storyEvent[0]);
  const target = world.getActorById(storyEvent[2]);
  rule.mutations(source, target);
}

function applyConsequent(world, typeExpression) {
  if (!typeExpression.length || typeExpression[0] === undefined) return false;
  const typeExpressionArray = Array.isArray(typeExpression[0]) ? typeExpression : [typeExpression];
  let result = '';
  _.each(typeExpressionArray, (expr) => {
    switch (expr[1]) {
      case c.vanish: {
        const actor = expr[0];
        utility.removeActor(world, actor);
        break;
      }
      case c.move_in: {
        const actor = world.getActorById(expr[0]);
        actor.location = expr[2];
        break;
      }
      default: {
        const source = utility.getPiece(expr[0]);
        const target = utility.getPiece(expr[2]);
        const rule = story.matchRuleFor(world, source, target, expr[1]);
        if (rule !== undefined) {
          /* eslint-disable no-use-before-define */
          result += processEvent(rule, expr);
        }
      }
    }
  }, this);
  return result;
}

function processEvent(world, rule, storyEvent) {
  const causeType = populateRuleType(rule.cause.template, storyEvent);
  const consequentType = populateRuleType(rule.consequent.template, storyEvent);
  const tertiaryType = populateRuleType(rule.consequent.type, storyEvent);
  const cause = processElementValue(world, causeType);
  const consequent = processElementValue(world, consequentType);
  const tertiary = !!tertiaryType ? applyConsequent(world, tertiaryType) : '';

  if (!!rule.consequentActor) {
    addConsequentActor(world, rule, storyEvent);
  }
  if (!!rule.mutations) {
    runMutations(world, rule, storyEvent);
  }
  const result = cause + consequent + tertiary;
  return result;
}

module.exports = {
  processEvent,
  addConsequentActor,
  runMutations,
  applyConsequent,
  populateRuleType,
  processElementValue,
};
<commit_msg>improve naming of functions and variables in events.js<commit_after>const Actor = require('../../components/actor.js');
const story = require('./story.js');
const c = require('../../components/constants.js');
const utility = require('./utility.js');

const _ = require('lodash');

/*
 * Replaces the constants SOURCE and TARGET with the IDs of the actors that
 * triggered this rule
 */
function populateTemplate(eventTemplate, eventTrigger) {
  if (!eventTemplate || !eventTemplate.length) return false;

  return eventTemplate.map(value => {
    if (value === c.source) {
      return eventTrigger[0];
    } else if (value === c.target) {
      return eventTrigger[2];
    }
    return value;
  });
}

function renderTemplate(world, element) {
  let result = [];
  _.each(element, (el) => {
    let actor = utility.getPiece(world, el);

    if (actor !== undefined) {
      actor = actor.name !== undefined ? actor.name : actor;
      result.push(actor);
    }
  }, this);
  result = _.compact(result);
  let body = result.join(' ');
  if (!body.length) {
    return '';
  }
  body += '. ';
  const head = body[0].toUpperCase();
  const tail = body.substring(1);
  body = head + tail;
  return body;
}

function addConsequentActor(world, rule, storyEvent) {
  const consequentActor = new Actor(rule.consequentActor, storyEvent, world);
  consequentActor.parentId = rule.id;
  world.addActor(consequentActor);
}

function runMutations(world, rule, storyEvent) {
  const source = world.getActorById(storyEvent[0]);
  const target = world.getActorById(storyEvent[2]);
  rule.mutations(source, target);
}

function applyConsequent(world, typeExpression) {
  if (!typeExpression.length || typeExpression[0] === undefined) return false;
  const typeExpressionArray = Array.isArray(typeExpression[0]) ? typeExpression : [typeExpression];
  let result = '';
  _.each(typeExpressionArray, (expr) => {
    switch (expr[1]) {
      case c.vanish: {
        const actor = expr[0];
        utility.removeActor(world, actor);
        break;
      }
      case c.move_in: {
        const actor = world.getActorById(expr[0]);
        actor.location = expr[2];
        break;
      }
      default: {
        const source = utility.getPiece(expr[0]);
        const target = utility.getPiece(expr[2]);
        const rule = story.matchRuleFor(world, source, target, expr[1]);
        if (rule !== undefined) {
          /* eslint-disable no-use-before-define */
          result += processEvent(rule, expr);
        }
      }
    }
  }, this);
  return result;
}

function processEvent(world, rule, storyEvent) {
  const causeTemplate = populateTemplate(rule.cause.template, storyEvent);
  const consequentTemplate = populateTemplate(rule.consequent.template, storyEvent);
  const tertiaryTemplate = populateTemplate(rule.consequent.type, storyEvent);
  const causeText = renderTemplate(world, causeTemplate);
  const consequentText = renderTemplate(world, consequentTemplate);
  const tertiary = !!tertiaryTemplate ? applyConsequent(world, tertiaryTemplate) : '';

  if (!!rule.consequentActor) {
    addConsequentActor(world, rule, storyEvent);
  }
  if (!!rule.mutations) {
    runMutations(world, rule, storyEvent);
  }
  const result = causeText + consequentText + tertiary;
  return result;
}

module.exports = {
  processEvent,
  addConsequentActor,
  runMutations,
  applyConsequent,
  populateTemplate,
  renderTemplate,
};
<|endoftext|>


<commit_before>/*

Uses the Google Sheets API to pull data from Sheets and load it onto shared
state. Writes the data out to JSON for later reference. Does not currently
check for existing data to merge--it does a fresh pull every time.

Sheets must be both A) shared publicly and B) "published to web" before they
can be accessed by this task.

*/

var project = require("../project.json");
var async = require("async");
var sheets = require("google-spreadsheets");

var camelCase = function(str) {
  return str.replace(/[^\w]+(\w)/g, function(all, match) {
    return match.toUpperCase();
  });
};

var cast = function(str) {
  if (typeof str !== "string") {
    if (typeof str.value == "string") {
      str = str.value;
    } else {
      return str;
    }
  }
  if (str.match(/^[\d\.,]+$/)) {
    //number
    return Number(str.replace(/,/g, ""));
  }
  if (str.toLowerCase() == "true" || str.toLowerCase() == "false") {
    return str.toLowerCase() == "true" ? true : false;
  }
  return str;
};

module.exports = function(grunt) {

  grunt.registerTask("sheets", "Downloads from Google Sheets -> JSON", function() {

    var auth = {};
    try {
      auth = require("../auth.json");
    } catch (_) { /* no auth.json, that's fine */ }
    var sheetKeys = project.sheets || (auth.google && auth.google.sheets);

    if (!sheetKeys || !sheetKeys.length) {
      return grunt.fail.fatal("You must specify a spreadsheet key in project.json or auth.json!");
    }

    var done = this.async();

    async.each(sheetKeys, function(key, bookDone) {
      sheets({
        key: key,
        worksheet: 1
      }, function(err, book) {
        if (err || !book) {
          grunt.fail.warn("Unable to access book for " + key + ", is it 'published' in Sheets?");
          return bookDone();
        }
        //download each worksheet
        async.each(book.worksheets, function(page, pageDone) {
          sheets.cells({ key: key, worksheet: page.id }, function(err, cells) {
            if (err) {
              grunt.fail.warn("Couldn't load sheet for " + book.title);
              return pageDone();
            }
            cells = cells.cells;

            //get the header row
            var rowNumbers = Object.keys(cells);
            var headerNumber = rowNumbers.shift();
            var headers = cells[headerNumber];
            var isKeyed = false;
            for (var cell in headers) {
              headers[cell] = headers[cell].value;
              if (headers[cell] == "key") {
                isKeyed = true;
              }
            }

            var output = isKeyed ? {} : [];

            //create the rows
            rowNumbers.forEach(function(rowNum) {
              var line = cells[rowNum];
              var columnNumbers = Object.keys(line);
              var row = {};
              columnNumbers.forEach(function(colNum) {
                var value = line[colNum];
                var key = headers[colNum];
                row[key] = cast(value);
              });
              if (isKeyed) {
                output[row.key] = row;
                delete row.key;
              } else {
                output.push(row);
              }
            });

            var filename = "data/" + camelCase(book.title) + "_" + camelCase(page.title) + ".sheet.json";
            grunt.file.write(filename, JSON.stringify(output, null, 2));
            pageDone();
          });
        }, function() {
          //when done with all sheets, continue
          bookDone();
        });
      });
    }, function() {
      return done();
    });

  });

};
<commit_msg>Sheets task code cleanup<commit_after>/*

Uses the Google Sheets API to pull data from Sheets and load it onto shared
state. Writes the data out to JSON for later reference. Does not currently
check for existing data to merge--it does a fresh pull every time.

Sheets must be both A) shared publicly and B) "published to web" before they
can be accessed by this task.

*/

var project = require("../project.json");
var async = require("async");
var sheets = require("google-spreadsheets");

var camelCase = function(str) {
  return str.replace(/[^\w]+(\w)/g, function(all, match) {
    return match.toUpperCase();
  });
};

var cast = function(str) {
  if (typeof str !== "string") {
    if (typeof str.value == "string") {
      str = str.value;
    } else {
      return str;
    }
  }
  if (str.match(/^[\d\.,]+$/)) {
    //number
    return Number(str.replace(/,/g, ""));
  }
  if (str.toLowerCase() == "true" || str.toLowerCase() == "false") {
    return str.toLowerCase() == "true" ? true : false;
  }
  return str;
};

module.exports = function(grunt) {

  grunt.registerTask("sheets", "Downloads from Google Sheets -> JSON", function() {

    var auth = {};
    try {
      auth = require("../auth.json");
    } catch (_) { /* no auth.json, that's fine */ }
    var sheetKeys = project.sheets || (auth.google && auth.google.sheets);

    if (!sheetKeys || !sheetKeys.length) {
      return grunt.fail.fatal("You must specify a spreadsheet key in project.json or auth.json!");
    }

    var done = this.async();

    async.each(sheetKeys, function(key, bookDone) {
      sheets({
        key: key
      }, function(err, book) {
        if (err || !book) {
          grunt.fail.warn("Unable to access book for " + key + ", is it 'published' in Sheets?");
          return bookDone();
        }
        //download each worksheet
        async.each(book.worksheets, function(page, pageDone) {
          sheets.cells({ key: key, worksheet: page.id }, function(err, cells) {
            if (err) {
              grunt.fail.warn("Couldn't load sheet " + page.id + " for " + book.title);
              return pageDone();
            }
            cells = cells.cells;

            //get the header row
            var rowNumbers = Object.keys(cells);
            var headerNumber = rowNumbers.shift();
            var headers = cells[headerNumber];
            var isKeyed = false;
            for (var cell in headers) {
              headers[cell] = headers[cell].value;
              if (headers[cell] == "key") {
                isKeyed = true;
              }
            }

            var output = isKeyed ? {} : [];

            //create the rows
            rowNumbers.forEach(function(rowNum) {
              var line = cells[rowNum];
              var columnNumbers = Object.keys(line);
              var row = {};
              columnNumbers.forEach(function(colNum) {
                var value = line[colNum];
                var key = headers[colNum];
                row[key] = cast(value);
              });
              if (isKeyed) {
                output[row.key] = row;
                delete row.key;
              } else {
                output.push(row);
              }
            });

            var filename = "data/" + camelCase(book.title) + "_" + camelCase(page.title) + ".sheet.json";
            grunt.file.write(filename, JSON.stringify(output, null, 2));
            pageDone();
          });
        }, bookDone);
      });
    }, done);

  });

};
<|endoftext|>


<commit_before>/**
 * @module /silence-sk
 * @description
silence-sk

 *
 * @evt add-silence-note Sent when the user adds a note to an silence.
 *    The detail includes the text of the note and the key of the silence.
 *
 *

 *     detail {
 *       key: "12312123123",
 *       text: "blah blah blah",
 *     }
 *

 *
 * @evt del-silence-note Sent when the user deletes a note on an silence.
 *    The detail includes the index of the note and the key of the silence.
 *
 *

 *     detail {
 *       key: "12312123123",
 *       index: 0,
 *     }
 *

 *
 * @evt save-silence Sent when the user saves a silence.
 *    The detail is the silence.
 *
 *

 *     detail {
 *       silence: {...},
 *     }
 *

 *
 * @evt archive-silence Sent when the user archives a silence.
 *    The detail is the silence.
 *
 *

 *     detail {
 *       silence: {...},
 *     }
 *

 *
 * @evt reactivate-silence Sent when the user reactivates a silence.
 *    The detail is the silence.
 *
 *

 *     detail {
 *       silence: {...},
 *     }
 *

 *
 * @evt delete-silence Sent when the user deletes a silence.
 *    The detail is the silence.
 *
 *

 *     detail {
 *       silence: {...},
 *     }
 *

 *
 * @evt delete-silence-param Sent when the user deletes a param from a silence.
 *    The detail is a copy of the silence with the parameter deleted.
 *
 *

 *     detail {
 *       silence: {...},
 *     }
 *

 *
 */
import 'elements-sk/icon/delete-icon-sk'

import * as paramset from '../paramset'
import { $$ } from 'common-sk/modules/dom'
import { abbr, displaySilence, expiresIn, notes } from '../am'
import { diffDate } from 'common-sk/modules/human'
import { html, render } from 'lit-html'
import { upgradeProperty } from 'elements-sk/upgradeProperty'

function table(ele, o) {
  let keys = Object.keys(o);
  keys.sort();
  return keys.filter(k => !k.startsWith('__')).map((k) =>
    html`<tr><td><delete-icon-sk title='Delete rule.' @click=${(e) => ele._deleteRule(e, k)}></delete-icon-sk></td><th>${k}</th><td>${o[k].join(', ')}</td></tr>`);
}

function addNote(ele) {
  if (ele._state.key) {
    return html`
    <textarea rows=2 cols=80></textarea>
    <button @click=${ele._addNote}>Submit</button>
  `;
  } else {
    return html`<textarea rows=2 cols=80></textarea>`;
  }
}

function matches(ele) {
  if (!ele._incidents) {
    return ``;
  }
  return ele._incidents.filter(
    incident => paramset.match(ele._state.param_set, incident.params) && incident.active
  ).map(incident => html`<h2> ${incident.params.alertname} ${abbr(incident)}</h2>`);
}

function classOfH2(silence) {
  if (!silence.active) {
    return 'inactive';
  }
  return '';
}

function actionButtons(ele) {
  if (ele._state.active) {
    return html`<button @click=${ele._save}>Save</button>
                <button @click=${ele._archive}>Archive</button>`;
  } else {
    return html`<button @click=${ele._reactivate}>Reactivate</button>
                <delete-icon-sk title='Delete silence.' @click=${ele._delete}></delete-icon-sk>`;
  }
}

const template = (ele) => html`

${displaySilence(ele._state)}

      ${actionButtons(ele)}

User:	${ele._state.user}

Duration:	<input @change=${ele._durationChange} value=${ele._state.duration}></input>

Created	${diffDate(ele._state.created*1000)}

Expires	${expiresIn(ele._state)}

      ${table(ele, ele._state.param_set)}

      ${notes(ele)}

      ${addNote(ele)}

Matches

      ${matches(ele)}

`;

window.customElements.define('silence-sk', class extends HTMLElement {
  constructor() {
    super();
    this._incidents = [];
  }

  connectedCallback() {
    upgradeProperty(this, 'state');
    upgradeProperty(this, 'incidents');
  }

  /** @prop state {Object} A Silence. */
  get state() { return this._state }
  set state(val) {
    this._state = val;
    this._render();
  }

  /** @prop incidents {string} The current active incidents. */
  get incidents() { return this._incidents }
  set incidents(val) {
    this._incidents = val;
    this._render();
  }

  _headerClick(e) {
    if (this.hasAttribute('collapsed')) {
      this.removeAttribute('collapsed');
    } else {
      this.setAttribute('collapsed', '');
    }
  }

  _durationChange(e) {
    this._state.duration = e.target.value;
  }

  _save(e) {
    let detail = {
      silence: this._state,
    };
    if (!this._state.key) {
      let textarea = $$('textarea', this);
      detail.silence.notes = [{
        text: textarea.value,
        ts: Math.floor(new Date().getTime()/1000),
      }]
    }
    this.dispatchEvent(new CustomEvent('save-silence', { detail: detail, bubbles: true }));
  }

  _archive(e) {
    let detail = {
      silence: this._state,
    };
    this.dispatchEvent(new CustomEvent('archive-silence', { detail: detail, bubbles: true }));
  }

  _reactivate(e) {
    let detail = {
      silence: this._state,
    };
    this.dispatchEvent(new CustomEvent('reactivate-silence', { detail: detail, bubbles: true }));
  }

  _delete(e) {
    let detail = {
      silence: this._state,
    };
    this.dispatchEvent(new CustomEvent('delete-silence', { detail: detail, bubbles: true }));
  }

  _deleteRule(e, key) {
    let silence = JSON.parse(JSON.stringify(this._state));
    delete silence.param_set[key];
    let detail = {
      silence: silence,
    };
    this.dispatchEvent(new CustomEvent('delete-silence-param', { detail: detail, bubbles: true }));
  }

  _addNote(e) {
    let textarea = $$('textarea', this);
    let detail = {
      key: this._state.key,
      text: textarea.value,
    };
    this.dispatchEvent(new CustomEvent('add-silence-note', { detail: detail, bubbles: true }));
    textarea.value = '';
  }

  _deleteNote(e, index) {
    let detail = {
      key: this._state.key,
      index: index,
    };
    this.dispatchEvent(new CustomEvent('del-silence-note', { detail: detail, bubbles: true }));
  }

  _render() {
    render(template(this), this, {eventContext: this});
  }

});
<commit_msg>[AM] Make silence description mandatory + add a placeholder<commit_after>/**
 * @module /silence-sk
 * @description
silence-sk

 *
 * @evt add-silence-note Sent when the user adds a note to an silence.
 *    The detail includes the text of the note and the key of the silence.
 *
 *

 *     detail {
 *       key: "12312123123",
 *       text: "blah blah blah",
 *     }
 *

 *
 * @evt del-silence-note Sent when the user deletes a note on an silence.
 *    The detail includes the index of the note and the key of the silence.
 *
 *

 *     detail {
 *       key: "12312123123",
 *       index: 0,
 *     }
 *

 *
 * @evt save-silence Sent when the user saves a silence.
 *    The detail is the silence.
 *
 *

 *     detail {
 *       silence: {...},
 *     }
 *

 *
 * @evt archive-silence Sent when the user archives a silence.
 *    The detail is the silence.
 *
 *

 *     detail {
 *       silence: {...},
 *     }
 *

 *
 * @evt reactivate-silence Sent when the user reactivates a silence.
 *    The detail is the silence.
 *
 *

 *     detail {
 *       silence: {...},
 *     }
 *

 *
 * @evt delete-silence Sent when the user deletes a silence.
 *    The detail is the silence.
 *
 *

 *     detail {
 *       silence: {...},
 *     }
 *

 *
 * @evt delete-silence-param Sent when the user deletes a param from a silence.
 *    The detail is a copy of the silence with the parameter deleted.
 *
 *

 *     detail {
 *       silence: {...},
 *     }
 *

 *
 */
import 'elements-sk/icon/delete-icon-sk'

import * as paramset from '../paramset'
import { $$ } from 'common-sk/modules/dom'
import { abbr, displaySilence, expiresIn, notes } from '../am'
import { diffDate } from 'common-sk/modules/human'
import { errorMessage } from 'elements-sk/errorMessage'
import { html, render } from 'lit-html'
import { upgradeProperty } from 'elements-sk/upgradeProperty'

function table(ele, o) {
  let keys = Object.keys(o);
  keys.sort();
  return keys.filter(k => !k.startsWith('__')).map((k) =>
    html`<tr><td><delete-icon-sk title='Delete rule.' @click=${(e) => ele._deleteRule(e, k)}></delete-icon-sk></td><th>${k}</th><td>${o[k].join(', ')}</td></tr>`);
}

function addNote(ele) {
  if (ele._state.key) {
    return html`
    <textarea rows=2 cols=80 placeholder="Add description for the silence"></textarea>
    <button @click=${ele._addNote}>Submit</button>
  `;
  } else {
    return html`<textarea rows=2 cols=80 placeholder="Add description for the silence"></textarea>`;
  }
}

function matches(ele) {
  if (!ele._incidents) {
    return ``;
  }
  return ele._incidents.filter(
    incident => paramset.match(ele._state.param_set, incident.params) && incident.active
  ).map(incident => html`<h2> ${incident.params.alertname} ${abbr(incident)}</h2>`);
}

function classOfH2(silence) {
  if (!silence.active) {
    return 'inactive';
  }
  return '';
}

function actionButtons(ele) {
  if (ele._state.active) {
    return html`<button @click=${ele._save}>Save</button>
                <button @click=${ele._archive}>Archive</button>`;
  } else {
    return html`<button @click=${ele._reactivate}>Reactivate</button>
                <delete-icon-sk title='Delete silence.' @click=${ele._delete}></delete-icon-sk>`;
  }
}

const template = (ele) => html`

${displaySilence(ele._state)}

      ${actionButtons(ele)}

User:	${ele._state.user}

Duration:	<input @change=${ele._durationChange} value=${ele._state.duration}></input>

Created	${diffDate(ele._state.created*1000)}

Expires	${expiresIn(ele._state)}

      ${table(ele, ele._state.param_set)}

      ${notes(ele)}

      ${addNote(ele)}

Matches

      ${matches(ele)}

`;

window.customElements.define('silence-sk', class extends HTMLElement {
  constructor() {
    super();
    this._incidents = [];
  }

  connectedCallback() {
    upgradeProperty(this, 'state');
    upgradeProperty(this, 'incidents');
  }

  /** @prop state {Object} A Silence. */
  get state() { return this._state }
  set state(val) {
    this._state = val;
    this._render();
  }

  /** @prop incidents {string} The current active incidents. */
  get incidents() { return this._incidents }
  set incidents(val) {
    this._incidents = val;
    this._render();
  }

  _headerClick(e) {
    if (this.hasAttribute('collapsed')) {
      this.removeAttribute('collapsed');
    } else {
      this.setAttribute('collapsed', '');
    }
  }

  _durationChange(e) {
    this._state.duration = e.target.value;
  }

  _save(e) {
    let detail = {
      silence: this._state,
    };
    if (!this._state.key) {
      let textarea = $$('textarea', this);
      if (!textarea.value) {
        errorMessage("Please enter a description for the silence");
        textarea.focus();
        return;
      }
      detail.silence.notes = [{
        text: textarea.value,
        ts: Math.floor(new Date().getTime()/1000),
      }]
    }
    this.dispatchEvent(new CustomEvent('save-silence', { detail: detail, bubbles: true }));
  }

  _archive(e) {
    let detail = {
      silence: this._state,
    };
    this.dispatchEvent(new CustomEvent('archive-silence', { detail: detail, bubbles: true }));
  }

  _reactivate(e) {
    let detail = {
      silence: this._state,
    };
    this.dispatchEvent(new CustomEvent('reactivate-silence', { detail: detail, bubbles: true }));
  }

  _delete(e) {
    let detail = {
      silence: this._state,
    };
    this.dispatchEvent(new CustomEvent('delete-silence', { detail: detail, bubbles: true }));
  }

  _deleteRule(e, key) {
    let silence = JSON.parse(JSON.stringify(this._state));
    delete silence.param_set[key];
    let detail = {
      silence: silence,
    };
    this.dispatchEvent(new CustomEvent('delete-silence-param', { detail: detail, bubbles: true }));
  }

  _addNote(e) {
    let textarea = $$('textarea', this);
    let detail = {
      key: this._state.key,
      text: textarea.value,
    };
    this.dispatchEvent(new CustomEvent('add-silence-note', { detail: detail, bubbles: true }));
    textarea.value = '';
  }

  _deleteNote(e, index) {
    let detail = {
      key: this._state.key,
      index: index,
    };
    this.dispatchEvent(new CustomEvent('del-silence-note', { detail: detail, bubbles: true }));
  }

  _render() {
    render(template(this), this, {eventContext: this});
  }

});
<|endoftext|>