<commit_before>/** @format */
import customExtendedTemplates from 'custom/extended.js'

const autocompleteTemplate = `\

    <input type="text"
            size="37"
            ng-model="input"
            escaper
            typeahead-min-length="0"
            typeahead-input-formatter="typeaheadInputFormatter($model)"
            uib-typeahead="tuple[0] as tuple[1] for tuple in getRows($viewValue)"></input>

`

const selectTemplate =
    "<select ng-show='!inputOnly' ng-model='input' escaper ng-options='tuple[0] as tuple[1] for tuple in dataset'></select>" +
    "<input ng-show='inputOnly' type='text' ng-model='input'/>"
const localize = ($scope) =>
    function (str) {
        if (!$scope.translationKey) {
            return str
        } else {
            return util.getLocaleString(($scope.translationKey || "") + str)
        }
    }

const selectController = (autocomplete) => [
    "$scope",
    "structService",
    function ($scope, structService) {
        const attribute = $scope.$parent.tokenValue.value
        const selectedCorpora = settings.corpusListing.selected

        // check which corpora support attributes
        const corpora = []
        for (let corpusSettings of selectedCorpora) {
            if (
                attribute in corpusSettings.structAttributes ||
                attribute in corpusSettings.attributes
            ) {
                corpora.push(corpusSettings.id)
            }
        }

        $scope.$watch("orObj.op", (newVal, oldVal) => {
            $scope.inputOnly = $scope.orObj.op !== "=" && $scope.orObj.op !== "!="
            if (newVal !== oldVal) {
                $scope.input = ""
            }
        })

        $scope.loading = true
        const opts = { count: false, returnByCorpora: false }
        if ($scope.type === "set") {
            opts.split = true
        }
        structService.getStructValues(corpora, [attribute], opts).then(
            function (data) {
                $scope.loading = false
                const localizer = localize($scope)

                const dataset = _.map(_.uniq(data), function (item) {
                    if (item === "") {
                        return [item, util.getLocaleString("empty")]
                    }
                    return [item, localizer(item)]
                })
                $scope.dataset = _.sortBy(dataset, (tuple) => tuple[1])
                if (!autocomplete) {
                    $scope.input = $scope.input || $scope.dataset[0][0]
                }
            },
            () => c.log("struct_values error")
        )

        $scope.getRows = function (input) {
            if (input) {
                return _.filter(
                    $scope.dataset,
                    (tuple) => tuple[0].toLowerCase().indexOf(input.toLowerCase()) !== -1
                )
            } else {
                return $scope.dataset
            }
        }

        $scope.typeaheadInputFormatter = (model) => localize($scope)(model)
    },
]

// Select-element. Use the following settings in the corpus:
// - dataset: an object or an array of values
// - translationKey: a key that will be prepended to the value for lookup in translation files
// - escape: boolean, will be used by the escaper-directive
export default _.merge({
    datasetSelect: {
        template: selectTemplate,
        controller: [
            "$scope",
            function ($scope) {
                let dataset
                const localizer = localize($scope)
                if (_.isArray($scope.dataset)) {
                    dataset = _.map($scope.dataset, (item) => [item, localizer(item)])
                } else {
                    dataset = _.map($scope.dataset, (v, k) => [k, localizer(v)])
                }
                $scope.dataset = _.sortBy(dataset, (tuple) => tuple[1])
                $scope.model = $scope.model || $scope.dataset[0][0]
            },
        ],
    },

    // Select-element. Gets values from "struct_values"-command. Use the following settings in the corpus:
    // - translationKey: a key that will be prepended to the value for lookup in translation files
    // - escape: boolean, will be used by the escaper-directive
    structServiceSelect: {
        template: selectTemplate,
        controller: selectController(false),
    },

    // Autocomplete. Gets values from "struct_values"-command. Use the following settings in the corpus:
    // - translationKey: a key that will be prepended to the value for lookup in translation files
    // - escape: boolean, will be used by the escaper-directive
    structServiceAutocomplete: {
        template: autocompleteTemplate,
        controller: selectController(true),
    },

    // puts the first values from a dataset paramater into model
    singleValue: {
        template: '<input type="hidden">',
        controller: ["$scope", ($scope) => ($scope.model = _.values($scope.dataset)[0])],
    },
    default: {
        template: _.template(`\
            <input ng-model='input' class='arg_value' escaper
                    ng-model-options='{debounce : {default : 300, blur : 0}, updateOn: "default blur"}'
            <%= maybe_placeholder %>>
             Aa

{{'case_sensitive' | loc:lang}}

{{'case_insensitive' | loc:lang}}

        `),
        controller: [
            "$scope",
            function ($scope) {
                if ($scope.orObj.flags && $scope.orObj.flags.c) {
                    $scope.case = "insensitive"
                } else {
                    $scope.case = "sensitive"
                }

                $scope.makeSensitive = function () {
                    $scope.case = "sensitive"
                    if ($scope.orObj.flags) {
                        delete $scope.orObj.flags["c"]
                    }
                }

                $scope.makeInsensitive = function () {
                    const flags = $scope.orObj.flags || {}
                    flags["c"] = true
                    $scope.orObj.flags = flags

                    $scope.case = "insensitive"
                }
            },
        ],
    },
    autocExtended: (options) => ({
        template: `
        <autoc
            input="input"
            is-raw-input="isRawInput"
            type='${options.type || 'lemgram'}'
            on-change="onChange(output, isRawOutput)"
            error-on-empty="${options.errorOnEmpty}"
            error-message="choose_value">
        </autoc>`,
        controller: [
            "$scope",
            function ($scope) {
                if($scope.model) {
                    $scope.input = unregescape($scope.model)
                    $scope.isRawInput = false
                }

                $scope.onChange = (output, isRawOutput) => {
                    if (!isRawOutput) {
                        $scope.model = regescape(output)
                    }
                }
            },
        ],
    })
}, customExtendedTemplates)
<commit_msg>redo translations of values<commit_after>/** @format */
import customExtendedTemplates from 'custom/extended.js'

const autocompleteTemplate = `\

    <input type="text"
            size="37"
            ng-model="input"
            escaper
            typeahead-min-length="0"
            typeahead-input-formatter="typeaheadInputFormatter($model)"
            uib-typeahead="tuple[0] as tuple[1] for tuple in getRows($viewValue)"></input>

`

const selectTemplate =
    "<select ng-show='!inputOnly' ng-model='input' escaper ng-options='tuple[0] as tuple[1] for tuple in dataset'></select>" +
    "<input ng-show='inputOnly' type='text' ng-model='input'/>"
const localize = ($scope) =>
    function (str) {
        return util.translateAttribute(null, $scope.translation, str)
    }

const selectController = (autocomplete) => [
    "$scope",
    "structService",
    function ($scope, structService) {
        const attribute = $scope.$parent.tokenValue.value
        const selectedCorpora = settings.corpusListing.selected

        // check which corpora support attributes
        const corpora = []
        for (let corpusSettings of selectedCorpora) {
            if (
                attribute in corpusSettings.structAttributes ||
                attribute in corpusSettings.attributes
            ) {
                corpora.push(corpusSettings.id)
            }
        }

        $scope.$watch("orObj.op", (newVal, oldVal) => {
            $scope.inputOnly = !["=", "!=", "contains", "not contains"].includes($scope.orObj.op)
            if (newVal !== oldVal) {
                if (!autocomplete) {
                    $scope.input = "" || $scope.dataset[0][0]
                }
            }
        })

        $scope.loading = true
        const opts = { count: false, returnByCorpora: false }
        if ($scope.type === "set") {
            opts.split = true
        }
        structService.getStructValues(corpora, [attribute], opts).then(
            function (data) {
                $scope.loading = false
                const localizer = localize($scope)

                const dataset = _.map(_.uniq(data), function (item) {
                    if (item === "") {
                        return [item, util.getLocaleString("empty")]
                    }
                    return [item, localizer(item)]
                })
                $scope.dataset = _.sortBy(dataset, (tuple) => tuple[1])
                if (!autocomplete) {
                    $scope.input = $scope.input || $scope.dataset[0][0]
                }
            },
            () => c.log("struct_values error")
        )

        $scope.getRows = function (input) {
            if (input) {
                return _.filter(
                    $scope.dataset,
                    (tuple) => tuple[0].toLowerCase().indexOf(input.toLowerCase()) !== -1
                )
            } else {
                return $scope.dataset
            }
        }

        $scope.typeaheadInputFormatter = (model) => localize($scope)(model)
    },
]

// Select-element. Use the following settings in the corpus:
// - dataset: an object or an array of values
// - escape: boolean, will be used by the escaper-directive
export default _.merge({
    datasetSelect: {
        template: selectTemplate,
        controller: [
            "$scope",
            function ($scope) {
                let dataset
                const localizer = localize($scope)
                if (_.isArray($scope.dataset)) {
                    dataset = _.map($scope.dataset, (item) => [item, localizer(item)])
                } else {
                    dataset = _.map($scope.dataset, (v, k) => [k, localizer(v)])
                }
                $scope.dataset = _.sortBy(dataset, (tuple) => tuple[1])
                $scope.model = $scope.model || $scope.dataset[0][0]
            },
        ],
    },

    // Select-element. Gets values from "struct_values"-command. Use the following settings in the corpus:
    // - escape: boolean, will be used by the escaper-directive
    structServiceSelect: {
        template: selectTemplate,
        controller: selectController(false),
    },

    // Autocomplete. Gets values from "struct_values"-command. Use the following settings in the corpus:
    // - escape: boolean, will be used by the escaper-directive
    structServiceAutocomplete: {
        template: autocompleteTemplate,
        controller: selectController(true),
    },

    // puts the first values from a dataset paramater into model
    singleValue: {
        template: '<input type="hidden">',
        controller: ["$scope", ($scope) => ($scope.model = _.values($scope.dataset)[0])],
    },
    default: {
        template: _.template(`\
            <input ng-model='input' class='arg_value' escaper
                    ng-model-options='{debounce : {default : 300, blur : 0}, updateOn: "default blur"}'
            <%= maybe_placeholder %>>
             Aa

{{'case_sensitive' | loc:lang}}

{{'case_insensitive' | loc:lang}}

        `),
        controller: [
            "$scope",
            function ($scope) {
                if ($scope.orObj.flags && $scope.orObj.flags.c) {
                    $scope.case = "insensitive"
                } else {
                    $scope.case = "sensitive"
                }

                $scope.makeSensitive = function () {
                    $scope.case = "sensitive"
                    if ($scope.orObj.flags) {
                        delete $scope.orObj.flags["c"]
                    }
                }

                $scope.makeInsensitive = function () {
                    const flags = $scope.orObj.flags || {}
                    flags["c"] = true
                    $scope.orObj.flags = flags

                    $scope.case = "insensitive"
                }
            },
        ],
    },
    autocExtended: (options) => ({
        template: `
        <autoc
            input="input"
            is-raw-input="isRawInput"
            type='${options.type || 'lemgram'}'
            on-change="onChange(output, isRawOutput)"
            error-on-empty="${options.errorOnEmpty}"
            error-message="choose_value">
        </autoc>`,
        controller: [
            "$scope",
            function ($scope) {
                if($scope.model) {
                    $scope.input = unregescape($scope.model)
                    $scope.isRawInput = false
                }

                $scope.onChange = (output, isRawOutput) => {
                    if (!isRawOutput) {
                        $scope.model = regescape(output)
                    }
                }
            },
        ],
    })
}, customExtendedTemplates)
<|endoftext|>


<commit_before>/**
 * Tools for managing Hoodie workers
 */

var config = require('./config'),
    client = require('./client'),
    utils = require('./utils'),
    _ = require('underscore');

/**
 * Starts all workers defined in the project's package.json file
 */

exports.startAll = function (cfg, callback) {
    // get couchdb admin password from npm
    config.getAdminPassword(cfg.app.name, function (err, password) {
        if (err) {
            return callback(err);
        }

        // create a client interface to hoodie server and couchdb
        client.createClient(cfg, password, function (err, hoodie) {
            if (err) {
                return callback(err);
            }

            // worker config
            var wconfig = {
                server: cfg.couch.url,
                persistent_since_storage: false,
                admin: {
                    user: "admin",
                    pass: password
                }
            };

            // loop through workers and start
            var names = exports.getWorkerNames(cfg.app);
            var workers = names.map(function (name) {
                wconfig.name = name;
                return exports.startWorker(wconfig, hoodie);
            });

            console.log("All workers started.");
            callback();
        });
    });
};

/**
 * Starts the named Hoodie worker
 */

exports.startWorker = function (wconfig, hoodie) {
    console.log("Starting: '%s'", wconfig.name);
    var wmodule = require('hoodie-' + wconfig.name);
    return wmodule(utils.jsonClone(wconfig), hoodie);
};

/**
 * Finds all the dependencies in the app's package.json which
 * start with 'worker-'
 */

exports.getWorkerNames = function (pkg) {
    return _.filter(Object.keys(pkg.dependencies), function (d) {
        return d.substr(0, 7) == "worker-";
    });
};
<commit_msg>remove "worker-" prefix from worker.name. Please review @caolan<commit_after>/**
 * Tools for managing Hoodie workers
 */

var config = require('./config'),
    client = require('./client'),
    utils = require('./utils'),
    _ = require('underscore');

/**
 * Starts all workers defined in the project's package.json file
 */

exports.startAll = function (cfg, callback) {
    // get couchdb admin password from npm
    config.getAdminPassword(cfg.app.name, function (err, password) {
        if (err) {
            return callback(err);
        }

        // create a client interface to hoodie server and couchdb
        client.createClient(cfg, password, function (err, hoodie) {
            if (err) {
                return callback(err);
            }

            // worker config
            var wconfig = {
                server: cfg.couch.url,
                persistent_since_storage: false,
                admin: {
                    user: "admin",
                    pass: password
                }
            };

            // loop through workers and start
            var names = exports.getWorkerNames(cfg.app);
            var workers = names.map(function (name) {
                wconfig.name = name;
                return exports.startWorker(wconfig, hoodie);
            });

            console.log("All workers started.");
            callback();
        });
    });
};

/**
 * Starts the named Hoodie worker
 */

exports.startWorker = function (wconfig, hoodie) {
    console.log("Starting: '%s'", wconfig.name);
    var wmodule = require('hoodie-worker-' + wconfig.name);
    return wmodule(utils.jsonClone(wconfig), hoodie);
};

/**
 * Finds all the dependencies in the app's package.json which
 * start with 'worker-'
 */

exports.getWorkerNames = function (pkg) {
    var names = _.filter( Object.keys(pkg.dependencies), function (d) {
        return d.substr(0, 7) == "worker-";
    });
    names = _.map(names, function(name) {
        return name.replace(/^worker-/, '');
    });
    return names;
};<|endoftext|>


<commit_before>/*************************************************
 * Copyright (c) 2015 Ansible, Inc.
 *
 * All Rights Reserved
 *************************************************/

export default
    angular.module('CompletedJobsDefinition', ['sanitizeFilter'])
    .value( 'CompletedJobsList', {
        // These tooltip fields are consumed to build disabled related tabs tooltips in the form > add view
        awToolTip: 'Please save and run a job to view',
        dataPlacement: 'top',
        name: 'completed_jobs',
        basePath: 'job_templates/:id/jobs/?or__status=successful&or__status=failed&or__status=error&or__status=canceled',
        iterator: 'completed_job',
        editTitle: 'Completed Jobs',
        index: false,
        hover: true,
        well: false,
        emptyListText: 'No completed jobs',

        fields: {
            status: {
                label: '',
                searchLabel: 'Status',
                columnClass: 'List-staticColumn--smallStatus',
                awToolTip: "{{ completed_job.status_tip }}",
                awTipPlacement: "right",
                dataTitle: "{{ completed_job.status_popover_title }}",
                icon: 'icon-job-{{ completed_job.status }}',
                iconOnly: true,
                ngClick:"viewJobDetails(completed_job)",
                searchable: true,
                searchType: 'select',
                nosort: true,
                searchOptions: [
                    { label: "Success", value: "successful" },
                    { label: "Error", value: "error" },
                    { label: "Failed", value: "failed" },
                    { label: "Canceled", value: "canceled" }
                ]
            },
            id: {
                label: 'ID',
                ngClick:"viewJobDetails(completed_job)",
                searchType: 'int',
                columnClass: 'col-lg-1 col-md-1 col-sm-2 col-xs-2 List-staticColumnAdjacent',
                awToolTip: "{{ completed_job.status_tip }}",
                dataPlacement: 'top'
            },
            name: {
                label: 'Name',
                columnClass: 'col-lg-4 col-md-4 col-sm-4 col-xs-6',
                ngClick: "viewJobDetails(completed_job)",
                defaultSearchField: true,
                awToolTip: "{{ completed_job.name | sanitize }}",
                dataPlacement: 'top'
            },
            finished: {
                label: 'Finished',
                noLink: true,
                searchable: false,
                filter: "longDate",
                columnClass: "col-lg-3 col-md-3 col-sm-3 hidden-xs",
                key: true,
                desc: true
            },
            type: {
                label: 'Type',
                ngBind: 'completed_job.type_label',
                link: false,
                columnClass: "col-lg-2 col-md-2 hidden-sm hidden-xs",
                columnShow: "showJobType",
                searchOnly: true,
                searchType: 'select',
                searchOptions: []    // populated via GetChoices() in controller
            },
            failed: {
                label: 'Job failed?',
                searchSingleValue: true,
                searchType: 'boolean',
                searchValue: 'true',
                searchOnly: true,
                nosort: true
            }
        },

        actions: { },

        fieldActions: {

            columnClass: 'col-lg-2 col-md-2 col-sm-3 col-xs-4',

            submit: {
                icon: 'icon-rocket',
                mode: 'all',
                ngClick: 'relaunchJob($event, completed_job.id)',
                awToolTip: 'Relaunch using the same parameters',
                dataPlacement: 'top',
                ngHide: "completed_job.type == 'system_job' "
            },
            "delete": {
                mode: 'all',
                ngClick: 'deleteJob(completed_job.id)',
                awToolTip: 'Delete the job',
                dataPlacement: 'top'
            }
        }
    });
<commit_msg>Matched job listing<commit_after>/*************************************************
 * Copyright (c) 2015 Ansible, Inc.
 *
 * All Rights Reserved
 *************************************************/

export default
    angular.module('CompletedJobsDefinition', ['sanitizeFilter'])
    .value( 'CompletedJobsList', {
        // These tooltip fields are consumed to build disabled related tabs tooltips in the form > add view
        awToolTip: 'Please save and run a job to view',
        dataPlacement: 'top',
        name: 'completed_jobs',
        basePath: 'job_templates/:id/jobs/?or__status=successful&or__status=failed&or__status=error&or__status=canceled',
        iterator: 'completed_job',
        editTitle: 'Completed Jobs',
        index: false,
        hover: true,
        well: false,
        emptyListText: 'No completed jobs',

        fields: {
            status: {
                label: '',
                searchLabel: 'Status',
                columnClass: 'List-staticColumn--smallStatus',
                awToolTip: "{{ completed_job.status_tip }}",
                awTipPlacement: "right",
                dataTitle: "{{ completed_job.status_popover_title }}",
                icon: 'icon-job-{{ completed_job.status }}',
                iconOnly: true,
                ngClick:"viewJobDetails(completed_job)",
                searchable: true,
                searchType: 'select',
                nosort: true,
                searchOptions: [
                    { label: "Success", value: "successful" },
                    { label: "Error", value: "error" },
                    { label: "Failed", value: "failed" },
                    { label: "Canceled", value: "canceled" }
                ]
            },
            id: {
                label: 'ID',
                ngClick:"viewJobDetails(completed_job)",
                searchType: 'int',
                columnClass: 'col-lg-1 col-md-1 col-sm-2 col-xs-2 List-staticColumnAdjacent',
                awToolTip: "{{ completed_job.status_tip }}",
                dataPlacement: 'top'
            },
            name: {
                label: 'Name',
                columnClass: 'col-lg-4 col-md-4 col-sm-4 col-xs-6',
                ngClick: "viewJobDetails(completed_job)",
                defaultSearchField: true,
                awToolTip: "{{ completed_job.name | sanitize }}",
                dataPlacement: 'top'
            },
            finished: {
                label: 'Finished',
                noLink: true,
                searchable: false,
                filter: "longDate",
                columnClass: "col-lg-3 col-md-3 col-sm-3 hidden-xs",
                key: true,
                desc: true
            },
            type: {
                label: 'Type',
                ngBind: 'completed_job.type_label',
                link: false,
                columnClass: "col-lg-2 col-md-2 hidden-sm hidden-xs",
                searchable: true,
                searchType: 'select',
                searchOptions: []    // populated via GetChoices() in controller
            },
            failed: {
                label: 'Job failed?',
                searchSingleValue: true,
                searchType: 'boolean',
                searchValue: 'true',
                searchOnly: true,
                nosort: true
            }
        },

        actions: { },

        fieldActions: {

            columnClass: 'col-lg-2 col-md-2 col-sm-3 col-xs-4',

            submit: {
                icon: 'icon-rocket',
                mode: 'all',
                ngClick: 'relaunchJob($event, completed_job.id)',
                awToolTip: 'Relaunch using the same parameters',
                dataPlacement: 'top',
                ngHide: "completed_job.type == 'system_job' "
            },
            "delete": {
                mode: 'all',
                ngClick: 'deleteJob(completed_job.id)',
                awToolTip: 'Delete the job',
                dataPlacement: 'top'
            }
        }
    });
<|endoftext|>


<commit_before>/* Copyright (c) 2014 Jason Ish
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

/**
 * Centralized configuration.
 *
 * Merges server provided configuration with local storage configuration.
 */
app.factory("Config", function ($http, $location) {

    var defaultConfig = {
        "elasticSearch": {
            "url": "http://" + window.location.hostname + ":9200",
            "size": 100,
            "timeout": 6000
        }
    };

    var serverConfig = {};
    var localConfig = {};

    try {
        serverConfig = config;
    }
    catch (error) {
        serverConfig = {};
    }

    if ("config" in localStorage) {
        localConfig = angular.fromJson(localStorage.config);
    }

    service = {};
    _.merge(service, defaultConfig);
    _.merge(service, serverConfig);
    _.merge(service, localConfig);

    var pruneConfig = function (config, serverConfig) {
        _.forIn(config, function (value, key) {
            if (!_.isFunction(value)) {
                if (serverConfig[key] != undefined) {
                    if (_.isObject(value)) {
                        pruneConfig(value, serverConfig[key]);
                    }
                    else if (serverConfig[key] == config[key]) {
                        delete(config[key]);
                    }
                }

                if (_.size(value) == 0) {
                    delete(config[key]);
                }
            }
        });
    };

    service.save = function () {
        pruneConfig(service, serverConfig);
        localStorage.config = angular.toJson(service);

        // Force full refresh.
        window.location.reload();
    };

    return service;
});

/**
 * Service containing utility functions.
 */
app.factory("Util", function () {

    var service = {};

    /**
     * Return an object as JSON.  Used in EveBox mainly for rendering search
     * results as JSON.
     *
     * Fields prefixed with __ are filtered out as those are internal state
     * variables for the application.
     */
    service.toJson = function (data, pretty) {
        var filtered = _.pick(data, function (value, key) {
            return key.substring(0, 2) != "__";
        });
        return angular.toJson(filtered, pretty);
    };

    /**
     * String formatter.
     *
     * Example: formatString("Numbers {0}, {1}, {2}.", "one", "two", "three");
     *
     * Based on:
     * http://stackoverflow.com/questions/610406/javascript-equivalent-to-printf-string-format/4673436#4673436
     */
    service.formatString = function (format) {
        var args = Array.prototype.slice.call(arguments, 1);
        return format.replace(/{(\d+)}/g, function (match, number) {
            return typeof args[number] != 'undefined' ? args[number] : match;
        });
    };

    /**
     * Convert an alert severity into a Bootstrap class for colorization.
     */
    service.severityToBootstrapClass = function (severity, prefix) {
        if (prefix === undefined) {
            prefix = "";
        }
        switch (severity) {
            case 1:
                return prefix + "danger";
                break;
            case 2:
                return prefix + "warning";
                break;
            default:
                return prefix + "info";
        }
    };

    /**
     * Check if an element is currently within the visible area of the window.
     *
     * From http://stackoverflow.com/questions/487073/check-if-element-is-visible-after-scrolling.
     */
    service.isScrolledIntoView = function (element) {
        var docViewTop = $(window).scrollTop();
        var docViewBottom = docViewTop + $(window).height();
        var elemTop = $(element).offset().top;
        var elemBottom = elemTop + $(element).height();
        return ((elemBottom < docViewBottom) && (elemTop >= docViewTop));
    };

    service.scrollElementIntoView = function (element) {
        if (!service.isScrolledIntoView(element)) {
            $(window).scrollTop(element.position().top - ($(window).height() / 2));
        }
    };

    /**
     * Print an IP address.  Really only used to shorten up IPv6 addresses.
     */
    service.printIpAddress = function (addr) {
        if (addr === undefined) {
            return "";
        }
        addr = addr.replace(/0000/g, "");
        while (addr.indexOf(":0:") > -1) {
            addr = addr.replace(/:0:/g, "::");
        }
        addr = addr.replace(/:::+/g, "::");
        while (addr != (addr = addr.replace(/:0+/g, ":")));
        return addr;
    };

    service.timestampToFloat = function (timestamp) {
        var usecs = timestamp.match(/\.(\d+)/)[1] / 1000000;
        var secs = moment(timestamp).unix();
        return secs + usecs;
    };

    return service;
});

/**
 * Elastic Search operations.
 */
app.factory("ElasticSearch", function ($http, Config) {

    var service = {};

    service.logFailure = function (failure) {
        console.log("elastic search server failure: " + failure);
    };

    /**
     * Search.
     */
    service.search = function (query) {
        var url = Config.elasticSearch.url + "/_all/_search?refresh=true";
        return $http.post(url, query);
    };

    service.bulk = function (request) {
        var url = Config.elasticSearch.url + "/_bulk?refresh=true";
        return $http.post(url, request);
    };

    service.msearch = function (request) {
        var url = Config.elasticSearch.url + "/_msearch?refresh=true";
        return $http.post(url, request);
    };

    service.update = function (index, type, id, request) {
        var url = Config.elasticSearch.url + "/" + index +
            "/" + type +
            "/" + id +
            "/_update?refresh=true";
        return $http.post(url, request);
    };

    service.delete = function (index, type, id) {
        var url = Config.elasticSearch.url + "/" + index + "/" + type + "/" + id + "?refresh=true";
        return $http.delete(url);
    };

    service.deleteByQuery = function (request) {
        var url = Config.elasticSearch.url + "/_all/_query?refresh=true";
        return $http.delete(url, {data: request});
    }

    /**
     * Get/search for a record by ID.
     *
     * Used for getting a single event by ID, but may return multiple results.
     */
    service.searchEventById = function (id) {
        var request = {
            query: {
                filtered: {
                    filter: {
                        term: {
                            "_id": id
                        }
                    }
                }
            }
        };
        return service.search(request);
    };

    /**
     * Bulk delete events.
     *
     * @param events The list of events to delete.
     */
    service.deleteEvents = function (events) {
        var request = events.map(function (event) {
            return angular.toJson({
                delete: {
                    _index: event._index,
                    _type: event._type,
                    _id: event._id
                }
            });
        }).join("\n") + "\n";
        return service.bulk(request);
    };

    service.bulkRemoveTag = function (events, tag) {
        var request = events.map(function (event) {
            return [
                angular.toJson({
                    update: {
                        _index: event._index,
                        _type: event._type,
                        _id: event._id
                    }
                }),
                angular.toJson({
                    script: "ctx._source.tags.remove(tag)",
                    params: {
                        "tag": tag
                    }
                })
            ];
        });
        return service.bulk(_.flatten(request).join("\n") + "\n");
    };

    service.addTag = function (doc, tag) {
        var request = {
            script: "ctx._source.tags.contains(tag) ? (ctx.op = \"none\") : ctx._source.tags += tag",
            params: {
                "tag": tag
            }
        };
        return service.update(doc._index, doc._type, doc._id, request);
    };

    service.removeTag = function (doc, tag) {
        var request = {
            script: "ctx._source.tags.remove(tag)",
            params: {
                "tag": tag
            }
        };
        return service.update(doc._index, doc._type, doc._id, request);
    };

    return service;

});

/**
 * EventRepository service.
 *
 * The idea of this service is provide a level of abstraction over
 * ElasticSearch.
 */
app.factory("EventRepository", function (ElasticSearch, $q) {

    var service = {};

    /**
     * Delete the provided event.
     *
     * @param event The event to delete.
     * @returns HttpPromise.
     */
    service.deleteEvent = function (event) {
        return ElasticSearch.delete(event._index, event._type, event._id);
    };

    /**
     * Remove a tag from an event.
     *
     * @param event Event to remove tag from.
     * @param tag The tag to remove.
     * @returns HttpPromise.
     */
    service.removeTag = function (event, tag) {
        return ElasticSearch.removeTag(event, tag)
            .success(function (response) {
                _.remove(event._source.tags, function (t) {
                    return t === tag;
                });
            });
    };

    /**
     * Toggle a tag on event - remove it if it exists, otherwise add it.
     *
     * @param event Event to toggle tag on.
     * @param tag Tag to toggle.
     * @returns HttpPromise.
     */
    service.toggleTag = function (event, tag) {
        if (_.indexOf(event._source.tags, tag) > -1) {
            return service.removeTag(event, tag);
        }
        else {
            return ElasticSearch.addTag(event, tag)
                .success(function (response) {
                    event._source.tags.push(tag);
                });
        }
    };

    /**
     * Toggle the "starred" tag on an event.
     */
    service.toggleStar = function (event) {
        return service.toggleTag(event, "starred");
    };

    return service;

});

/**
 * A service for keyboard bindings (wrapping Mousetrap) that will track
 * the scope a binding was created in for per scope cleanup.
 */
app.factory("Keyboard", function () {

    var service = {};
    service.scopeBindings = {};

    service.scopeBind = function (scope, key, callback) {
        Mousetrap.unbind(key);
        Mousetrap.bind(key, function (e) {
            callback(e);
        });
        if (!(scope.$id in service.scopeBindings)) {
            service.scopeBindings[scope.$id] = [];
        }
        service.scopeBindings[scope.$id].push({key: key, callback: callback});
    };

    service.resetScope = function (scope) {
        if (scope.$id in service.scopeBindings) {
            _.forEach(service.scopeBindings[scope.$id], function (binding) {
                Mousetrap.unbind(binding.key);
            });
            delete(service.scopeBindings[scope.$id]);
        }

        // Something is up with Mousetrap bindings, rebinding existing
        // bindings seems to fix it.
        for (var scopeId in service.scopeBindings) {
            _.forEach(service.scopeBindings[scopeId], function (binding) {
                Mousetrap.bind(binding.key, binding.callback);
            });
        }
    };

    return service;

});

app.factory("Cache", function () {

    var service = {
        caches: {}
    };

    // Return a cache of the given name.
    service.get = function (name) {
        if (service.caches[name] === undefined) {
            service.caches[name] = {};
        }
        return service.caches[name];
    };

    return service;

});

app.factory("NotificationMessageService", function ($timeout) {

    var service = {};

    service.queue = [];

    service.add = function (level, message) {
        var entry = {
            level: level,
            message: message
        };

        service.queue.push(entry);

        $timeout(function () {
            _.remove(service.queue, function (item) {
                return item === entry;
            })
        }, 1500);
    };

    return service;
});<commit_msg>Unbind a key before rebinding, a double bind shouldn't occur, but it is.<commit_after>/* Copyright (c) 2014 Jason Ish
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

/**
 * Centralized configuration.
 *
 * Merges server provided configuration with local storage configuration.
 */
app.factory("Config", function ($http, $location) {

    var defaultConfig = {
        "elasticSearch": {
            "url": "http://" + window.location.hostname + ":9200",
            "size": 100,
            "timeout": 6000
        }
    };

    var serverConfig = {};
    var localConfig = {};

    try {
        serverConfig = config;
    }
    catch (error) {
        serverConfig = {};
    }

    if ("config" in localStorage) {
        localConfig = angular.fromJson(localStorage.config);
    }

    service = {};
    _.merge(service, defaultConfig);
    _.merge(service, serverConfig);
    _.merge(service, localConfig);

    var pruneConfig = function (config, serverConfig) {
        _.forIn(config, function (value, key) {
            if (!_.isFunction(value)) {
                if (serverConfig[key] != undefined) {
                    if (_.isObject(value)) {
                        pruneConfig(value, serverConfig[key]);
                    }
                    else if (serverConfig[key] == config[key]) {
                        delete(config[key]);
                    }
                }

                if (_.size(value) == 0) {
                    delete(config[key]);
                }
            }
        });
    };

    service.save = function () {
        pruneConfig(service, serverConfig);
        localStorage.config = angular.toJson(service);

        // Force full refresh.
        window.location.reload();
    };

    return service;
});

/**
 * Service containing utility functions.
 */
app.factory("Util", function () {

    var service = {};

    /**
     * Return an object as JSON.  Used in EveBox mainly for rendering search
     * results as JSON.
     *
     * Fields prefixed with __ are filtered out as those are internal state
     * variables for the application.
     */
    service.toJson = function (data, pretty) {
        var filtered = _.pick(data, function (value, key) {
            return key.substring(0, 2) != "__";
        });
        return angular.toJson(filtered, pretty);
    };

    /**
     * String formatter.
     *
     * Example: formatString("Numbers {0}, {1}, {2}.", "one", "two", "three");
     *
     * Based on:
     * http://stackoverflow.com/questions/610406/javascript-equivalent-to-printf-string-format/4673436#4673436
     */
    service.formatString = function (format) {
        var args = Array.prototype.slice.call(arguments, 1);
        return format.replace(/{(\d+)}/g, function (match, number) {
            return typeof args[number] != 'undefined' ? args[number] : match;
        });
    };

    /**
     * Convert an alert severity into a Bootstrap class for colorization.
     */
    service.severityToBootstrapClass = function (severity, prefix) {
        if (prefix === undefined) {
            prefix = "";
        }
        switch (severity) {
            case 1:
                return prefix + "danger";
                break;
            case 2:
                return prefix + "warning";
                break;
            default:
                return prefix + "info";
        }
    };

    /**
     * Check if an element is currently within the visible area of the window.
     *
     * From http://stackoverflow.com/questions/487073/check-if-element-is-visible-after-scrolling.
     */
    service.isScrolledIntoView = function (element) {
        var docViewTop = $(window).scrollTop();
        var docViewBottom = docViewTop + $(window).height();
        var elemTop = $(element).offset().top;
        var elemBottom = elemTop + $(element).height();
        return ((elemBottom < docViewBottom) && (elemTop >= docViewTop));
    };

    service.scrollElementIntoView = function (element) {
        if (!service.isScrolledIntoView(element)) {
            $(window).scrollTop(element.position().top - ($(window).height() / 2));
        }
    };

    /**
     * Print an IP address.  Really only used to shorten up IPv6 addresses.
     */
    service.printIpAddress = function (addr) {
        if (addr === undefined) {
            return "";
        }
        addr = addr.replace(/0000/g, "");
        while (addr.indexOf(":0:") > -1) {
            addr = addr.replace(/:0:/g, "::");
        }
        addr = addr.replace(/:::+/g, "::");
        while (addr != (addr = addr.replace(/:0+/g, ":")));
        return addr;
    };

    service.timestampToFloat = function (timestamp) {
        var usecs = timestamp.match(/\.(\d+)/)[1] / 1000000;
        var secs = moment(timestamp).unix();
        return secs + usecs;
    };

    return service;
});

/**
 * Elastic Search operations.
 */
app.factory("ElasticSearch", function ($http, Config) {

    var service = {};

    service.logFailure = function (failure) {
        console.log("elastic search server failure: " + failure);
    };

    /**
     * Search.
     */
    service.search = function (query) {
        var url = Config.elasticSearch.url + "/_all/_search?refresh=true";
        return $http.post(url, query);
    };

    service.bulk = function (request) {
        var url = Config.elasticSearch.url + "/_bulk?refresh=true";
        return $http.post(url, request);
    };

    service.msearch = function (request) {
        var url = Config.elasticSearch.url + "/_msearch?refresh=true";
        return $http.post(url, request);
    };

    service.update = function (index, type, id, request) {
        var url = Config.elasticSearch.url + "/" + index +
            "/" + type +
            "/" + id +
            "/_update?refresh=true";
        return $http.post(url, request);
    };

    service.delete = function (index, type, id) {
        var url = Config.elasticSearch.url + "/" + index + "/" + type + "/" + id + "?refresh=true";
        return $http.delete(url);
    };

    service.deleteByQuery = function (request) {
        var url = Config.elasticSearch.url + "/_all/_query?refresh=true";
        return $http.delete(url, {data: request});
    }

    /**
     * Get/search for a record by ID.
     *
     * Used for getting a single event by ID, but may return multiple results.
     */
    service.searchEventById = function (id) {
        var request = {
            query: {
                filtered: {
                    filter: {
                        term: {
                            "_id": id
                        }
                    }
                }
            }
        };
        return service.search(request);
    };

    /**
     * Bulk delete events.
     *
     * @param events The list of events to delete.
     */
    service.deleteEvents = function (events) {
        var request = events.map(function (event) {
            return angular.toJson({
                delete: {
                    _index: event._index,
                    _type: event._type,
                    _id: event._id
                }
            });
        }).join("\n") + "\n";
        return service.bulk(request);
    };

    service.bulkRemoveTag = function (events, tag) {
        var request = events.map(function (event) {
            return [
                angular.toJson({
                    update: {
                        _index: event._index,
                        _type: event._type,
                        _id: event._id
                    }
                }),
                angular.toJson({
                    script: "ctx._source.tags.remove(tag)",
                    params: {
                        "tag": tag
                    }
                })
            ];
        });
        return service.bulk(_.flatten(request).join("\n") + "\n");
    };

    service.addTag = function (doc, tag) {
        var request = {
            script: "ctx._source.tags.contains(tag) ? (ctx.op = \"none\") : ctx._source.tags += tag",
            params: {
                "tag": tag
            }
        };
        return service.update(doc._index, doc._type, doc._id, request);
    };

    service.removeTag = function (doc, tag) {
        var request = {
            script: "ctx._source.tags.remove(tag)",
            params: {
                "tag": tag
            }
        };
        return service.update(doc._index, doc._type, doc._id, request);
    };

    return service;

});

/**
 * EventRepository service.
 *
 * The idea of this service is provide a level of abstraction over
 * ElasticSearch.
 */
app.factory("EventRepository", function (ElasticSearch, $q) {

    var service = {};

    /**
     * Delete the provided event.
     *
     * @param event The event to delete.
     * @returns HttpPromise.
     */
    service.deleteEvent = function (event) {
        return ElasticSearch.delete(event._index, event._type, event._id);
    };

    /**
     * Remove a tag from an event.
     *
     * @param event Event to remove tag from.
     * @param tag The tag to remove.
     * @returns HttpPromise.
     */
    service.removeTag = function (event, tag) {
        return ElasticSearch.removeTag(event, tag)
            .success(function (response) {
                _.remove(event._source.tags, function (t) {
                    return t === tag;
                });
            });
    };

    /**
     * Toggle a tag on event - remove it if it exists, otherwise add it.
     *
     * @param event Event to toggle tag on.
     * @param tag Tag to toggle.
     * @returns HttpPromise.
     */
    service.toggleTag = function (event, tag) {
        if (_.indexOf(event._source.tags, tag) > -1) {
            return service.removeTag(event, tag);
        }
        else {
            return ElasticSearch.addTag(event, tag)
                .success(function (response) {
                    event._source.tags.push(tag);
                });
        }
    };

    /**
     * Toggle the "starred" tag on an event.
     */
    service.toggleStar = function (event) {
        return service.toggleTag(event, "starred");
    };

    return service;

});

/**
 * A service for keyboard bindings (wrapping Mousetrap) that will track
 * the scope a binding was created in for per scope cleanup.
 */
app.factory("Keyboard", function () {

    var service = {};
    service.scopeBindings = {};

    service.scopeBind = function (scope, key, callback) {
        Mousetrap.unbind(key);
        Mousetrap.bind(key, function (e) {
            callback(e);
        });
        if (!(scope.$id in service.scopeBindings)) {
            service.scopeBindings[scope.$id] = [];
        }
        service.scopeBindings[scope.$id].push({key: key, callback: callback});
    };

    service.resetScope = function (scope) {
        if (scope.$id in service.scopeBindings) {
            _.forEach(service.scopeBindings[scope.$id], function (binding) {
                Mousetrap.unbind(binding.key);
            });
            delete(service.scopeBindings[scope.$id]);
        }

        // Something is up with Mousetrap bindings, rebinding existing
        // bindings seems to fix it.
        for (var scopeId in service.scopeBindings) {
            _.forEach(service.scopeBindings[scopeId], function (binding) {
                Mousetrap.unbind(binding.key);
                Mousetrap.bind(binding.key, binding.callback);
            });
        }
    };

    return service;

});

app.factory("Cache", function () {

    var service = {
        caches: {}
    };

    // Return a cache of the given name.
    service.get = function (name) {
        if (service.caches[name] === undefined) {
            service.caches[name] = {};
        }
        return service.caches[name];
    };

    return service;

});

app.factory("NotificationMessageService", function ($timeout) {

    var service = {};

    service.queue = [];

    service.add = function (level, message) {
        var entry = {
            level: level,
            message: message
        };

        service.queue.push(entry);

        $timeout(function () {
            _.remove(service.queue, function (item) {
                return item === entry;
            })
        }, 1500);
    };

    return service;
});<|endoftext|>


<commit_before>export default function arrayBuffer() {
  console.group('ArrayBuffer/ArrayBufferView');
  {
    console.group('base');
    {
      const buffer = new ArrayBuffer(8); // 8 bytes
      const view = new Uint8Array(buffer);
      view[0] = 0xFF;
      view[1] = 0x0F;
      view[2] = 0x0A;
      console.log(view);
    }
    console.groupEnd();

    console.group('range error');
    {
      try {
        const buffer = new ArrayBuffer(7); // 7 bytes
        const view = new Uint16Array(buffer);
      } catch (e) {
        console.error(e);
      }
    }
    console.groupEnd();

    console.group('buffer sharing');
    {
      const buffer = new ArrayBuffer(2); // 2 bytes
      {
        const view = new Uint8Array(buffer);
        view[0] = 0xFF;
        view[1] = 0xFF;
        console.log(view);
      }
      {
        const view = new Int16Array(buffer);
        console.log(view); // -1
      }
    }
    console.groupEnd();

    console.group('DataView');
    {
      const buffer = new ArrayBuffer(2); // 2 bytes
      const view = new DataView(buffer);
      view.setUint8(0, 0xFF);
      view.setUint8(1, 0xFF);
      console.log(view.getInt16(0));

    }
    console.groupEnd();
  }
  console.groupEnd();
}
<commit_msg>babel_es2015: add a code of ArrayBuffer/ArrayBufferView<commit_after>export default function arrayBuffer() {
  console.group('ArrayBuffer/TypedArray/DataView');
  {
    console.group('ArrayBuffer');
    {
      console.group('buffer sharing');
      {
        const buffer = new ArrayBuffer(2); // 2 bytes
        {
          const view = new Uint8Array(buffer);
          view[0] = 0xFF;
          view[1] = 0xFF;
          console.log(view);
        }
        {
          const view = new Int16Array(buffer);
          console.log(view); // -1
        }
      }
      console.groupEnd();
    }
    console.groupEnd();

    console.group('TypedArray');
    {
      console.group('base');
      {
        const buffer = new ArrayBuffer(8); // 8 bytes
        const view = new Uint8Array(buffer);
        view[0] = 0xFF;
        view[1] = 0x0F;
        view[2] = 0x0A;
        console.log(view);
      }
      console.groupEnd();

      console.group('range error');
      {
        try {
          const buffer = new ArrayBuffer(7); // 7 bytes
          const view = new Uint16Array(buffer);
        } catch (e) {
          console.error(e);
        }
      }
      console.groupEnd();
    }
    console.groupEnd();

    console.group('DataView');
    {
      console.group('base');
      {
        const buffer = new ArrayBuffer(2); // 2 bytes
        const view = new DataView(buffer);
        view.setUint8(0, 0xFF);
        view.setUint8(1, 0xFF);
        console.log(view.getInt16(0));
      }
      console.groupEnd();

      console.group('endianness');
      {
        const buffer = new ArrayBuffer(2); // 2 bytes
        const view = new DataView(buffer);
        console.log('set 0xFF 0x00');
        view.setUint8(0, 0xFF);
        view.setUint8(1, 0x00);
        console.log('litle endianness =>', view.getInt16(0, false));
        console.log('big endianness =>', view.getInt16(0, true));
      }
      console.groupEnd();
    }
    console.groupEnd();
  }
  console.groupEnd();
}
<|endoftext|>


<commit_before>import R from 'ramda';
import { createSelector } from 'reselect';
import * as EDITOR_MODE from '../constants/editorModes';
import * as ENTITY from '../constants/entities';
import { getProject, getPatchById } from './project';

export const getEditor = R.prop('editor');

export const getCurrentPatchId = R.pipe(
  getEditor,
  R.prop('currentPatchId')
);

export const getSelection = (state) => R.pipe(
  getEditor,
  R.prop('selection')
)(state);

export const getSelectedNodeType = (state) => R.pipe(
  getEditor,
  R.prop('selectedNodeType')
)(state);

export const getSelectionByTypes = createSelector(
  getSelection,
  (selection) => {
    let result = {};
    if (selection.length > 0) {
      result = R.groupBy((s) => s.entity, selection);
    }
    result.Node = result.Node || [];
    result.Pin = result.Pin || [];
    result.Link = result.Link || [];
    result.length = selection.length;

    return result;
  }
);

export const isSelected = (selection, entityName, id) => R.pipe(
  R.filter(R.propEq('entity', entityName)),
  R.find(R.propEq('id', id)),
  R.isNil,
  R.not
)(selection);

export const isNodeSelected = (selection, id) => isSelected(selection, ENTITY.NODE, id);
export const isLinkSelected = (selection, id) => isSelected(selection, ENTITY.LINK, id);

export const hasSelection = (state) => (
  state.editor.selection.length > 0 ||
  state.editor.linkingPin !== null
);

export const getLinkingPin = (state) => R.pipe(
  getEditor,
  R.prop('linkingPin')
)(state);

export const getMode = (state) => R.pipe(
  getEditor,
  R.prop('mode')
)(state);

export const getModeChecks = (state) => {
  const mode = getMode(state);
  return {
    mode,
    isDefault: (mode === EDITOR_MODE.DEFAULT),
    isCreatingNode: (mode === EDITOR_MODE.CREATING_NODE),
    isEditing: (mode === EDITOR_MODE.EDITING),
    isLinking: (mode === EDITOR_MODE.LINKING),
    isPanning: (mode === EDITOR_MODE.PANNING),
  };
};

export const getTabs = (state) => R.pipe(
  getEditor,
  R.prop('tabs')
)(state);

export const getPreparedTabs = (state) => {
  const currentPatchId = getCurrentPatchId(state);
  const projectState = getProject(state);

  return R.pipe(
    getTabs,
    R.values,
    R.reduce(
      (p, cur) => {
        const patch = getPatchById(projectState, cur.patchId);
        const mergedData = R.merge(
          cur,
          {
            name: patch.name,
            isActive: (currentPatchId === cur.patchId),
          }
        );

        return R.assoc(cur.id, mergedData, p);
      },
      {}
    )
  )(state);
};
<commit_msg>fix(selector): add additional checks into selector hasSelection to make sure that editor has props we want to read<commit_after>import R from 'ramda';
import { createSelector } from 'reselect';
import * as EDITOR_MODE from '../constants/editorModes';
import * as ENTITY from '../constants/entities';
import { getProject, getPatchById } from './project';

export const getEditor = R.prop('editor');

export const getCurrentPatchId = R.pipe(
  getEditor,
  R.prop('currentPatchId')
);

export const getSelection = (state) => R.pipe(
  getEditor,
  R.prop('selection')
)(state);

export const getSelectedNodeType = (state) => R.pipe(
  getEditor,
  R.prop('selectedNodeType')
)(state);

export const getSelectionByTypes = createSelector(
  getSelection,
  (selection) => {
    let result = {};
    if (selection.length > 0) {
      result = R.groupBy((s) => s.entity, selection);
    }
    result.Node = result.Node || [];
    result.Pin = result.Pin || [];
    result.Link = result.Link || [];
    result.length = selection.length;

    return result;
  }
);

export const isSelected = (selection, entityName, id) => R.pipe(
  R.filter(R.propEq('entity', entityName)),
  R.find(R.propEq('id', id)),
  R.isNil,
  R.not
)(selection);

export const isNodeSelected = (selection, id) => isSelected(selection, ENTITY.NODE, id);
export const isLinkSelected = (selection, id) => isSelected(selection, ENTITY.LINK, id);

export const hasSelection = (state) => (
  (
    state.editor.selection &&
    state.editor.selection.length > 0
  ) || (
    state.editor.linkingPin &&
    state.editor.linkingPin !== null
  )
);

export const getLinkingPin = (state) => R.pipe(
  getEditor,
  R.prop('linkingPin')
)(state);

export const getMode = (state) => R.pipe(
  getEditor,
  R.prop('mode')
)(state);

export const getModeChecks = (state) => {
  const mode = getMode(state);
  return {
    mode,
    isDefault: (mode === EDITOR_MODE.DEFAULT),
    isCreatingNode: (mode === EDITOR_MODE.CREATING_NODE),
    isEditing: (mode === EDITOR_MODE.EDITING),
    isLinking: (mode === EDITOR_MODE.LINKING),
    isPanning: (mode === EDITOR_MODE.PANNING),
  };
};

export const getTabs = (state) => R.pipe(
  getEditor,
  R.prop('tabs')
)(state);

export const getPreparedTabs = (state) => {
  const currentPatchId = getCurrentPatchId(state);
  const projectState = getProject(state);

  return R.pipe(
    getTabs,
    R.values,
    R.reduce(
      (p, cur) => {
        const patch = getPatchById(projectState, cur.patchId);
        const mergedData = R.merge(
          cur,
          {
            name: patch.name,
            isActive: (currentPatchId === cur.patchId),
          }
        );

        return R.assoc(cur.id, mergedData, p);
      },
      {}
    )
  )(state);
};
<|endoftext|>


<commit_before>import Ember from 'ember';

export default Ember.Service.extend({
  ajax: Ember.inject.service('ajax'),
  session: Ember.inject.service('session'),

  query: function(path, args, method) {
    const eafBasePath = 'http://eaf.smalldata.io/v1';
    const me = this;

    // var myFunc = function() { return new Promise(function(resolve) { libFunc(function() { resolve(1); }); }); };  myFunc().then(callback);
    // 15:30 < jaawerth> diphtherial: so basically, wrap the header-getting bit in a Promise that resolves to the headers object you created,
    // then you can do gotHeaders.then(function(headers) { return me.get('ajax').request(bleh, { method, headers }); })

    return new Ember.RSVP.Promise(function(resolve, reject) {
      me.get('session').authorize('authorizer:eaf-oauth2', function(headerName, headerValue) {
        const headers = {};
        headers[headerName] = headerValue;
        var options = { method: method, data: args, headers };
        console.log("Query to ", path, " with options: ", options);

        return me.get('ajax').request(`${eafBasePath}/${path}`, options)
          .then(function(result) { resolve(result); })
          .catch(function(error) { reject(error); });
      });
    });
  },

  ping: function(source) {
    this.query('ping').catch((error) => {
      console.log("Ping failed: ", error, "invalidating and logging in...");
      var session = this.get('session');
      if (session) { session.invalidate(); }
      source.transitionTo('login');
    });
  }
});
<commit_msg>Removed excessive debug printing that used to occur on every API request<commit_after>import Ember from 'ember';

export default Ember.Service.extend({
  ajax: Ember.inject.service('ajax'),
  session: Ember.inject.service('session'),

  query: function(path, args, method) {
    const eafBasePath = 'http://eaf.smalldata.io/v1';
    const me = this;

    // var myFunc = function() { return new Promise(function(resolve) { libFunc(function() { resolve(1); }); }); };  myFunc().then(callback);
    // 15:30 < jaawerth> diphtherial: so basically, wrap the header-getting bit in a Promise that resolves to the headers object you created,
    // then you can do gotHeaders.then(function(headers) { return me.get('ajax').request(bleh, { method, headers }); })

    return new Ember.RSVP.Promise(function(resolve, reject) {
      me.get('session').authorize('authorizer:eaf-oauth2', function(headerName, headerValue) {
        const headers = {};
        headers[headerName] = headerValue;
        var options = { method: method, data: args, headers };
        // console.log("Query to ", path, " with options: ", options);

        return me.get('ajax').request(`${eafBasePath}/${path}`, options)
          .then(function(result) { resolve(result); })
          .catch(function(error) { reject(error); });
      });
    });
  },

  ping: function(source) {
    this.query('ping').catch((error) => {
      console.log("Ping failed: ", error, "invalidating and logging in...");
      var session = this.get('session');
      if (session) { session.invalidate(); }
      source.transitionTo('login');
    });
  }
});
<|endoftext|>


<commit_before>/**
 * Developer: Stepan Burguchev
 * Date: 6/26/2015
 * Copyright: 2009-2015 Comindware®
 *       All Rights Reserved
 *
 * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF Comindware
 *       The copyright notice above does not evidence any
 *       actual or intended publication of such source code.
 */

/* global define, require, Handlebars, Backbone, Marionette, $, _, Localizer */

define([
        'module/lib',
        'module/moduleConfigs',
        'project/module/moduleConfigs',
        'process/module/moduleConfigs'
    ],
    function (lib, moduleConfigs, projectModuleConfigs, processModuleConfigs) {
        'use strict';

        var moduleConfigs = _.flatten([ moduleConfigs, projectModuleConfigs, processModuleConfigs ]);

        return {
            initialize: function () {

                // Then we start loading default module (after that we can start history)
                // this.__navigateToDefaultModule();
                Backbone.history.start();
                /*new AppRouter({
                 controller:new Controller()
                 });*/
                /*var Controller = Backbone.Marionette.Controller.extend({
                    initialize: function (options) {
                        //App.headerRegion.show(new HeaderView());
                    },
                    //gets mapped to in AppRouter's appRoutes
                    index:function () {
                        //App.mainRegion.show(new WelcomeView());
                    }
                });

                //--
                var AppRouter = Marionette.AppRouter.extend({
                    //"index" must be a method in AppRouter's controller
                    appRoutes: {
                        "": "index"
                    }
                });

                //--*/
            }
        };
    });
<commit_msg>module loading<commit_after>/**
 * Developer: Stepan Burguchev
 * Date: 6/26/2015
 * Copyright: 2009-2015 Comindware®
 *       All Rights Reserved
 *
 * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF Comindware
 *       The copyright notice above does not evidence any
 *       actual or intended publication of such source code.
 */

/* global define, require, Handlebars, Backbone, Marionette, $, _, Localizer */

define([
        'module/lib',
        'module/moduleConfigs',
        'project/module/moduleConfigs',
        'process/module/moduleConfigs'
    ],
    function (lib, moduleConfigs, projectModuleConfigs, processModuleConfigs) {
        'use strict';

        var moduleConfigs = _.flatten([ moduleConfigs, projectModuleConfigs, processModuleConfigs ]);

        return {
            initialize: function () {
                // TODO: moduleConfigs unique id
                _.each(moduleConfigs, function (config) {

                    var ModuleRouter = Marionette.AppRouter.extend({
                        appRoutes: config.routes
                    });

                    var handlerProxy = function () {
                        require([ config.module ], function (Module) {
                            // TODO: if exists and activated?
                            var module = new Module();
                            module.
                        });
                        // load
                        // start
                    };

                    var Module = {
                        handler: null
                    };
                    //config.routes
                    // config
                    routes: {
                        'People/Users': 'showUsers',
                            'People/Users/:uid': 'routePreview',
                            'People/Users/cfid-:id': 'routePreviewClearFilter',
                            'People/Users/id-:id/:name': 'routePreviewAndSearch'
                    }

                    new ModuleRouter();
                });
                // Then we start loading default module (after that we can start history)
                // this.__navigateToDefaultModule();
                Backbone.history.start();
                /*new AppRouter({
                 controller:new Controller()
                 });*/
                /*var Controller = Backbone.Marionette.Controller.extend({
                    initialize: function (options) {
                        //App.headerRegion.show(new HeaderView());
                    },
                    //gets mapped to in AppRouter's appRoutes
                    index:function () {
                        //App.mainRegion.show(new WelcomeView());
                    }
                });

                //--
                var AppRouter = Marionette.AppRouter.extend({
                    //"index" must be a method in AppRouter's controller
                    appRoutes: {
                        "": "index"
                    }
                });

                //--*/
            }
        };
    });
<|endoftext|>


<commit_before>var options = {
  valueNames: [ 'billimage', 'lastaction', 'billsummary' ],
  page: 10,
  plugins: [
    ListPagination({
      innerWindow: 2
    })
  ]
};

var billsList = new List('billsSort', options);

$('#filter-senate').click(function() {
  billsList.filter(function(item) {
    var html = item.values().billimage;
    var div = document.createElement("div");
    div.innerHTML = html;
    var billimage = div.textContent || div.innerText || "";
    if (billimage.substring(0,1) == "S") {
      return true;
    } else {
      return false;
    }
  });
  return false;
});

$('#filter-house').click(function() {
  billsList.filter(function(item) {
    var html = item.values().billimage;
    var div = document.createElement("div");
    div.innerHTML = html;
    var billimage = div.textContent || div.innerText || "";
    if (billimage.substring(0,1) == "H") {
      return true;
    } else {
      return false;
    }
  });
  return false;
});

$('#filter-none').click(function() {
  billsList.filter();
  return false;
 });

$(function() {
  $('.commentForm').submit(function(e) {
    e.preventDefault();
    console.log($(this));

    $.ajax({
      url: '/comment',
      data: $(this).serialize(),
      type: 'POST',
      success: function(response) {
        console.log(response.comment);
        console.log(response.position);
        var $newComment = $('<p>').text(response.comment);
        $('#comment').append($newComment);
      },
      error: function(error) {
        console.log(error);
        console.log("FAILURE");
      }
    });
  });
});

/*
$(function() {
  $('#submitcomment').click(function(e) {
    e.preventDefault();
    $.ajax({
      url: '/comment',
      data: $("#"+(e.toElement.form.id)).serialize(),
      type: 'POST',
      success: function(response) {
      console.log(response.comment);
      /*$("sentiment h3").after("Your latest comment:")response.comment;
        $("#comment").val("");  */
/*      },
      error: function(error) {
        console.log(error);
        console.log("FAILURE");
      }
    });
  });
});

*/

/*
Not sure what this function was for...

$(document).ready(function () {
  $('ul.nav > li').click(function (e) {
   e.preventDefault();
   $('ul.nav > li').removeClass('active');
   $(this).addClass('active');
  });
});

*/<commit_msg>ajax comments now working yay<commit_after>var options = {
  valueNames: [ 'billimage', 'lastaction', 'billsummary' ],
  page: 10,
  plugins: [
    ListPagination({
      innerWindow: 2
    })
  ]
};

var billsList = new List('billsSort', options);

$('#filter-senate').click(function() {
  billsList.filter(function(item) {
    var html = item.values().billimage;
    var div = document.createElement("div");
    div.innerHTML = html;
    var billimage = div.textContent || div.innerText || "";
    if (billimage.substring(0,1) == "S") {
      return true;
    } else {
      return false;
    }
  });
  return false;
});

$('#filter-house').click(function() {
  billsList.filter(function(item) {
    var html = item.values().billimage;
    var div = document.createElement("div");
    div.innerHTML = html;
    var billimage = div.textContent || div.innerText || "";
    if (billimage.substring(0,1) == "H") {
      return true;
    } else {
      return false;
    }
  });
  return false;
});

$('#filter-none').click(function() {
  billsList.filter();
  return false;
 });

$("#submitcomment").click(function (event) {
  if (!$("input:radio[name='position']:checked").val()>0) {
    alert('Please select your position on the bill before submitting comment.');
    event.preventDefault();
  } });

$(function() {
  $('.commentForm').submit(function(e) {
    e.preventDefault();
    //console.log($(this));
    var parent = $(this).parent().parent();

    var input = $(this).find("input[type=radio]:checked").val();
    var position = "." + input;
    var commentBox = parent.find(position);

    $.ajax({
      url: '/comment',
      data: $(this).serialize(),
      type: 'POST',
      success: function(response) {
        var newComment = response.comment;
        console.log(commentBox);
        console.log(newComment);

        commentBox.append('<li>' + newComment + '</li>');
        $('input[type=text], textarea').val('');
      },
      error: function(error) {
        console.log(error);
        console.log("FAILURE");
      }
    });
  });
});

/*
$(function() {
  $('#submitcomment').click(function(e) {
    e.preventDefault();
    $.ajax({
      url: '/comment',
      data: $("#"+(e.toElement.form.id)).serialize(),
      type: 'POST',
      success: function(response) {
      console.log(response.comment);
      /*$("sentiment h3").after("Your latest comment:")response.comment;
        $("#comment").val("");  */
/*      },
      error: function(error) {
        console.log(error);
        console.log("FAILURE");
      }
    });
  });
});

*/

/*
Not sure what this function was for...

$(document).ready(function () {
  $('ul.nav > li').click(function (e) {
   e.preventDefault();
   $('ul.nav > li').removeClass('active');
   $(this).addClass('active');
  });
});

*/<|endoftext|>


<commit_before>mclab = window.mclab || {};
mclab.editor = mclab.editor || {};

mclab.editor.Tab = function (li, label, session, editor) {
  this.li = li;
  this.label = label;
  this.li.data('tab', this);
  this.session = session;
  this.editor = editor;
};

mclab.editor.Tab.prototype.getSiblings = function() {
  return this.li.siblings().map(function (i, li) {
    return $(li).data('tab');
  });
};

mclab.editor.Tab.prototype.getClosestTab = function() {
  var tab = this.li.prev('li');
  if (tab.length === 0) {
    tab = this.li.next('li');
  }
  if (tab.length !== 0) {
    return tab.data('tab') || null;
  }
  return null;
}

mclab.editor.Tab.prototype.isSelected = function() {
  return this.li.hasClass('active');
};

mclab.editor.Tab.prototype.unselect = function() {
  this.li.removeClass('active');
};

mclab.editor.Tab.prototype.select = function() {
  this.li.addClass('active');
  this.getSiblings().each(function (i, tab) { tab.unselect(); });
  this.editor.editor.setSession(this.session);
  this.editor.show();
};

mclab.editor.Tab.prototype.close = function() {
  if (this.isSelected()) {
    var tab = this.getClosestTab();
    if (tab !== null) {
      tab.select();
    }
  }

  this.editor.removeTabLabeled(this.label);
  this.li.remove();

  if (this.editor.getNumTabs() === 0) {
    this.editor.hide();
  }
};

mclab.editor.TabbedEditor = function(id, aceId) {
  this.el = $('#' + id);
  this.editor_el = $('#' + aceId);
  this.editor = ace.edit(aceId);
  this.editor.setTheme('ace/theme/solarized_dark');
  this.editor.setFontSize(14);
  this.editor.setShowPrintMargin(false);
  this.editor.setSession(this.newSession(''));
  this.editor.resize();
  this.editor.focus();

  $(window).resize(this.resizeAce.bind(this));
  this.resizeAce();

  this.tabs = {};

  this.el.find('ul.editor-tabs')
    .on('click', 'li:not(.editor-add-file)', function () {
      $(this).data('tab').select();
    })
    .on('click', 'span.glyphicon-remove', function() {
      $(this).parents('li').first().data('tab').close();
      return false;
    });

  this.newTabButton = this.el.find('.editor-add-file').first();
  this.newTabButton.on('click', (function () {
    var filename = prompt('Name: ');
    if (filename !== null && /[^\s]/.test(filename)) {
      this.createTab(filename).select();
    }
  }).bind(this));

  this.hide();
};

mclab.editor.TabbedEditor.prototype.hide = function() {
  this.editor_el.css('visibility', 'hidden');
};

mclab.editor.TabbedEditor.prototype.show = function() {
  this.editor_el.css('visibility', 'visible');
};

mclab.editor.TabbedEditor.prototype.getNumTabs = function(name) {
  return Object.keys(this.tabs).length;
};

mclab.editor.TabbedEditor.prototype.getTabLabeled = function(name) {
  return this.tabs[name];
};

mclab.editor.TabbedEditor.prototype.hasTabLabeled = function(name) {
  return name in this.tabs;
};

mclab.editor.TabbedEditor.prototype.removeTabLabeled = function(name) {
  delete this.tabs[name];
};

mclab.editor.TabbedEditor.prototype.createTab = function(filename, contents) {
  if (contents === undefined) {
    contents = '';
  }
  var li = $('<li>').append($('<a>').attr('href', '#').append(
    filename, ' ', mclab.utils.makeIcon('remove')));
  li.insertBefore(this.newTabButton);
  this.tabs[filename] = new mclab.editor.Tab(li, filename, this.newSession(contents), this);
  return this.tabs[filename];
};

mclab.editor.TabbedEditor.prototype.newSession = function(text) {
  var session = ace.createEditSession(text, 'ace/mode/matlab');
  session.setUseSoftTabs(true);
  return session;
};

mclab.editor.TabbedEditor.prototype.resizeAce = function() {
    var height = $(window).height();
    this.editor_el.height(3 * height / 4);
    this.editor.resize();
    // TODO(isbadawi): This shouldn't be here
    $('#console').height(height / 4);
    ace.edit('console').resize();
};

mclab.editor.TabbedEditor.prototype.overlayErrors = function(errors) {
  if (errors === undefined) {
    errors = [];
  }
  this.editor.getSession().setAnnotations(
    errors.map(function (err) {
      return {
        row: err.line - 1,
        column: err.col - 1,
        text: err.message,
        type: 'error'
      };
    })
  );
};

mclab.editor.TabbedEditor.prototype.tryParse = function() {
  mclab.ajax.parseCode(this.editor.getValue(), (function (data) {
    this.overlayErrors(data.errors);
  }).bind(this));
};

mclab.editor.TabbedEditor.prototype.startSyntaxChecker = function() {
  var typingTimer = null;
  var doneTypingInterval = 1000;

  var doneTyping = (function() {
    this.tryParse();
    typingTimer = null;
  }).bind(this);

  this.editor.on('change', function() {
    if (typingTimer != null) {
      clearTimeout(typingTimer);
      typingTimer = null;
    }
    typingTimer = setTimeout(doneTyping, doneTypingInterval);
  });
};

mclab.editor.TabbedEditor.prototype.openFile = function(path) {
  if (this.hasTabLabeled(path)) {
    this.getTabLabeled(path).select();
    return;
  }
  var self = this;
  mclab.ajax.readFile(path, function (data) {
    self.createTab(path, data).select();
  });
};
<commit_msg>Add Ctrl+S to save current file.<commit_after>mclab = window.mclab || {};
mclab.editor = mclab.editor || {};

mclab.editor.Tab = function (li, label, session, editor) {
  this.li = li;
  this.label = label;
  this.li.data('tab', this);
  this.session = session;
  this.editor = editor;
};

mclab.editor.Tab.prototype.getSiblings = function() {
  return this.li.siblings().map(function (i, li) {
    return $(li).data('tab');
  });
};

mclab.editor.Tab.prototype.getClosestTab = function() {
  var tab = this.li.prev('li');
  if (tab.length === 0) {
    tab = this.li.next('li');
  }
  if (tab.length !== 0) {
    return tab.data('tab') || null;
  }
  return null;
}

mclab.editor.Tab.prototype.isSelected = function() {
  return this.li.hasClass('active');
};

mclab.editor.Tab.prototype.unselect = function() {
  this.li.removeClass('active');
};

mclab.editor.Tab.prototype.select = function() {
  this.li.addClass('active');
  this.getSiblings().each(function (i, tab) { tab.unselect(); });
  this.editor.editor.setSession(this.session);
  this.editor.show();
};

mclab.editor.Tab.prototype.close = function() {
  if (this.isSelected()) {
    var tab = this.getClosestTab();
    if (tab !== null) {
      tab.select();
    }
  }

  this.editor.removeTabLabeled(this.label);
  this.li.remove();

  if (this.editor.getNumTabs() === 0) {
    this.editor.hide();
  }
};

mclab.editor.TabbedEditor = function(id, aceId) {
  this.el = $('#' + id);
  this.editor_el = $('#' + aceId);
  this.editor = ace.edit(aceId);
  this.editor.setTheme('ace/theme/solarized_dark');
  this.editor.setFontSize(14);
  this.editor.setShowPrintMargin(false);
  this.editor.setSession(this.newSession(''));
  this.editor.resize();
  this.editor.focus();

  this.editor.commands.addCommand({
    name: 'save',
    bindKey: {
      win: 'Ctrl-S',
      mac: 'Command-S',
    },
    exec: (function() {
      var tab = this.getSelectedTab();
      mclab.ajax.writeFile(tab.label, this.editor.getValue());
    }).bind(this),
  });

  $(window).resize(this.resizeAce.bind(this));
  this.resizeAce();

  this.tabs = {};

  this.el.find('ul.editor-tabs')
    .on('click', 'li:not(.editor-add-file)', function() {
      $(this).data('tab').select();
    })
    .on('click', 'span.glyphicon-remove', function() {
      $(this).parents('li').first().data('tab').close();
      return false;
    });

  this.newTabButton = this.el.find('.editor-add-file').first();
  this.newTabButton.on('click', (function () {
    var filename = prompt('Name: ');
    if (filename !== null && /[^\s]/.test(filename)) {
      this.createTab(filename).select();
    }
  }).bind(this));

  this.hide();
};

mclab.editor.TabbedEditor.prototype.hide = function() {
  this.editor_el.css('visibility', 'hidden');
};

mclab.editor.TabbedEditor.prototype.show = function() {
  this.editor_el.css('visibility', 'visible');
};

mclab.editor.TabbedEditor.prototype.getNumTabs = function(name) {
  return Object.keys(this.tabs).length;
};

mclab.editor.TabbedEditor.prototype.getTabLabeled = function(name) {
  return this.tabs[name];
};

mclab.editor.TabbedEditor.prototype.hasTabLabeled = function(name) {
  return name in this.tabs;
};

mclab.editor.TabbedEditor.prototype.removeTabLabeled = function(name) {
  delete this.tabs[name];
};

mclab.editor.TabbedEditor.prototype.getSelectedTab = function() {
  return this.el.find('ul.editor-tabs li.active').data('tab');
};

mclab.editor.TabbedEditor.prototype.createTab = function(filename, contents) {
  if (contents === undefined) {
    contents = '';
  }
  var li = $('<li>').append($('<a>').attr('href', '#').append(
    filename, ' ', mclab.utils.makeIcon('remove')));
  li.insertBefore(this.newTabButton);
  this.tabs[filename] = new mclab.editor.Tab(li, filename, this.newSession(contents), this);
  return this.tabs[filename];
};

mclab.editor.TabbedEditor.prototype.newSession = function(text) {
  var session = ace.createEditSession(text, 'ace/mode/matlab');
  session.setUseSoftTabs(true);
  return session;
};

mclab.editor.TabbedEditor.prototype.resizeAce = function() {
    var height = $(window).height();
    this.editor_el.height(3 * height / 4);
    this.editor.resize();
    // TODO(isbadawi): This shouldn't be here
    $('#console').height(height / 4);
    ace.edit('console').resize();
};

mclab.editor.TabbedEditor.prototype.overlayErrors = function(errors) {
  if (errors === undefined) {
    errors = [];
  }
  this.editor.getSession().setAnnotations(
    errors.map(function (err) {
      return {
        row: err.line - 1,
        column: err.col - 1,
        text: err.message,
        type: 'error'
      };
    })
  );
};

mclab.editor.TabbedEditor.prototype.tryParse = function() {
  mclab.ajax.parseCode(this.editor.getValue(), (function (data) {
    this.overlayErrors(data.errors);
  }).bind(this));
};

mclab.editor.TabbedEditor.prototype.startSyntaxChecker = function() {
  var typingTimer = null;
  var doneTypingInterval = 1000;

  var doneTyping = (function() {
    this.tryParse();
    typingTimer = null;
  }).bind(this);

  this.editor.on('change', function() {
    if (typingTimer != null) {
      clearTimeout(typingTimer);
      typingTimer = null;
    }
    typingTimer = setTimeout(doneTyping, doneTypingInterval);
  });
};

mclab.editor.TabbedEditor.prototype.openFile = function(path) {
  if (this.hasTabLabeled(path)) {
    this.getTabLabeled(path).select();
    return;
  }
  var self = this;
  mclab.ajax.readFile(path, function (data) {
    self.createTab(path, data).select();
  });
};
<|endoftext|>