<commit_before>/*globals $, eventize, _ */

var langcodeTag;

(function () {
    'use strict';

    langcodeTag = {
        LANG_DELIN: "{{[[*LANG*]]}}",
        button_tag: (function () {
            var LangCodeButton = function ($elem, new_lang) {
                this.button = $elem;
                this.button.click(function () {
                    return false;
                });
                this.lang_code = new_lang;
                this.lang(new_lang);
            };
            LangCodeButton.prototype = {
                lang: function (value) {
                    if (value === undefined) {
                        return this.lang_code;
                    } else {
                        this.lang_code = value;
                        this.button.text(this.lang_code);
                        this.button.popover({
                            title: "Using '" + this.lang_code + "' Value",
                            content: "There is no translation available for the currently selected language.

Using text from the [" +
                                this.lang_code + "] language by default. Edit the value and save to override defaults."
                        });
                    }
                }
            };
            return function ($elem, new_lang) {
                return new LangCodeButton($elem, new_lang);
            };
        }()),
        translate_delim: (function () {
            return function (value) {
                var values = value.split(langcodeTag.LANG_DELIN);
                var langcode = null;
                if (values.length > 1)
                    langcode = values[1];
                return {
                    value: values[0],
                    lang: langcode
                };
            };
        }())
    };

}());

var uiElement;
(function () {
    'use strict';

    var Input = function ($elem, getElemValue, setElemValue, setPlaceholderValue) {
        var that = this;
        eventize(this);
        this.ui = $('
');
        this.value = "";
        this.edit = true;
        this.getElemValue = function () {
            return getElemValue($elem);
        };
        this.setElemValue = function (value) {
            setElemValue($elem, value);
        };
        this.setPlaceholderValue = function (value) {
            setPlaceholderValue($elem, value);
        };

        this.$edit_view = $elem.bind('change textchange', function () {
            that.fire('change');
        });
        this.$noedit_view = $('');

        this.on('change', function () {
            this.value = this.getElemValue();
            this.$noedit_view.text(this.value);
        });
        this.setEdit(this.edit);
    };
    Input.prototype = {
        val: function (value) {
            if (value === undefined) {
                return this.value;
            } else {
                this.value = value;
                this.setVisibleValue(this.value);
                return this;
            }
        },
        setVisibleValue: function (value) {
            var translated = langcodeTag.translate_delim(value);
            this.ui.find('.lang-text').remove();
            if (translated.lang) {
                var langcode_button = langcodeTag.button_tag($(''),
                    translated.lang);
                this.ui.append(langcode_button.button);
                this.setPlaceholderValue(translated.value);
                this.$edit_view.change(function () {
                    if ($(this).val() == "")
                        langcode_button.button.show();
                    else
                        langcode_button.button.hide();
                });
            } else
                this.setElemValue(translated.value);
            this.$noedit_view.text(translated.value);
        },
        setEdit: function (edit) {
            this.edit = edit;
            this.$edit_view.detach();
            this.$noedit_view.detach();
            if (this.edit) {
                this.$edit_view.prependTo(this.ui);
            } else {
                this.$noedit_view.prependTo(this.ui);
            }
            return this;
        }
    };

    uiElement = {
        input: (function () {
            return function () {
                return new Input($('<input type="text"/>'), function ($elem) {
                    return $elem.val();
                }, function ($elem, value) {
                    return $elem.val(value);
                }, function ($elem, value){
                    return $elem.attr('placeholder', value);
                });
            };
        }()),
        textarea: function () {
            return new Input($('<textarea/>'), function ($elem) {
                return $elem.val();
            }, function ($elem, value) {
                return $elem.val($elem, value);
            }, function ($elem, value){
                $elem.attr('placeholder', value);
            });
        },
        select: (function () {
            var Select = function (options) {
                var that = this,
                    i,
                    option;
                eventize(this);
                this.ui = $('');
                this.value = "";
                this.edit = true;
                this.options = options;

                this.on('change', function () {
                    this.val(this.ui.find('select').val());
                });

                this.$edit_view = $('<select/>').change(function () {
                    that.fire('change');
                });
                for (i = 0; i < this.options.length; i += 1) {
                    option = this.options[i];
                    $('<option/>').text(option.label).val(option.value).appendTo(this.$edit_view);
                }

                this.$noedit_view = $('');

                this.setEdit(this.edit);
            };
            Select.prototype = {
                val: function (value) {
                    var i, option, label;
                    if (value === undefined) {
                        return this.value;
                    } else {
                        this.value = value;
                        for (i = 0; i < this.options.length; i += 1) {
                            option = this.options[i];
                            if (option.value === value) {
                                label = option.label;
                                break;
                            }
                        }
                        this.$edit_view.val(this.value.toString());
                        this.$noedit_view.text(label);
                        return this;
                    }
                },
                setEdit: function (edit) {
                    this.edit = edit;
                    this.$edit_view.detach();
                    this.$noedit_view.detach();
                    if (this.edit) {
                        this.$edit_view.appendTo(this.ui);
                    } else {
                        this.$noedit_view.appendTo(this.ui);
                    }
                    return this;
                }
            };
            return function (options) {
                return new Select(options);
            };
        }()),
        map_list: (function() {
            var KeyValList = function(guid, modal_title) {
                var that = this;
                eventize(this);
                this.ui = $('
');
                this.value = {};
                this.translated_value = {};
                this.edit = true;
                this.modal_id = 'enumModal-'+guid;
                this.modal_title = modal_title;

                this.$edit_view = $('
');
                this.$noedit_view = $('
');
                this.$formatted_view = $('<input type="hidden" />');
                this.$modal_trigger = $('').html(' Edit');

                // Create new modal controller for this element
                var $enumModal = $('
');
                $enumModal.prepend('
×
Edit Mapping for '+this.modal_title+'

');
                var $modal_form = $('<form class="form-horizontal hq-enum-editor" action="" />'),
                    $modal_body = $('
');
                $modal_body.append($('<fieldset />'));
                $modal_body.append('
 Add Key => Value Mapping
');

                $modal_form.append($modal_body);
                $modal_form.append('
<button class="btn btn-primary" data-dismiss="modal">Done</button>
');
                $enumModal.append($modal_form);

                $('#hq-modal-home').append($enumModal);

                $('#'+this.modal_id).on('hide', function() {
                    var $inputMap = $(this).find('form .hq-input-map'),
                        pairs = {};
                    for (var i=0; i < $inputMap.length; i++) {
                        var key = $($inputMap[i]).find('.enum-key').val(),
                            mapVal = $($inputMap[i]).find('.enum-value').val();
                        if (key !== undefined){
                            pairs[key] = mapVal.toString();
                        }
                    }
                    that.val(pairs);
                    that.fire('change');
                });

                $('#'+this.modal_id+' a').click(function() {
                    if($(this).attr('data-enum-action') == 'add') {
                        $(this).parent().parent().find('fieldset').append(uiElement.input_map(true).ui);
                        $(this).parent().parent().find('fieldset input.enum-key').last().focus();
                    }
                    if (!$(this).attr('data-dismiss'))
                        return false;
                });

                this.setEdit(this.edit);
            };
            KeyValList.prototype = {
                val: function(original_pairs, translated_pairs) {
                    if (original_pairs === undefined) {
                        return this.value;
                    } else {
                        var $modal_fields = $('#'+this.modal_id+' form fieldset');
                        $modal_fields.text('');
                        this.$noedit_view.text('');
                        this.$edit_view.text('');

                        this.value = original_pairs;
                        if (translated_pairs != undefined) {
                            this.translated_value = translated_pairs;
                        }
                        this.$formatted_view.val(JSON.stringify(this.value));
                        for (var key in this.value) {
                            $modal_fields.append(uiElement.input_map(true).val(key, this.value[key], this.translated_value[key]).ui);
                            this.$edit_view.append(uiElement.input_map(true).val(key, this.value[key], this.translated_value[key]).setEdit(false).$noedit_view);
                        }
                    }

                },
                setEdit: function(edit) {
                    this.edit = edit;
                    this.$edit_view.detach();
                    this.$noedit_view.detach();
                    this.$modal_trigger.detach();
                    if (this.edit) {
                        this.$edit_view.appendTo(this.ui);
                        this.$modal_trigger.appendTo(this.ui);
                        this.$formatted_view.appendTo(this.ui);
                    } else {
                        this.$noedit_view.appendTo(this.ui);
                    }
                    return this;
                }
            };
            return function (guid, modal_title) {
                return new KeyValList(guid, modal_title);
            };
        }()),
        input_map: (function() {
            var InputMap = function (show_del_button) {
                var that = this;
                eventize(this);
                this.ui = $('
');
                this.value = {
                    key: "",
                    val: ""
                };
                this.edit = true;
                this.show_delete = show_del_button;
                this.on('change', function() {
                    this.val(this.ui.find(".enum-key").val(), this.ui.find(".enum-value").val())
                });
                this.on('remove', function() {
                    this.ui.remove();
                });

                this.$edit_view = $('
');
                var key_input = $('<input type="text" class="input-small enum-key" placeholder="key" />'),
                    val_input = $('<input type="text" class="input-large enum-value" placeholder="value" />');
                key_input.change(function () {
                    that.fire('change');
                });
                val_input.change(function() {
                    that.fire('change');
                });
                this.$edit_view.append(key_input);
                this.$edit_view.append(' => ')
                this.$edit_view.append(val_input);
                if(this.show_delete) {
                    var $deleteButton = $('');
                    $deleteButton.append(' Delete');
                    $deleteButton.click(function() {
                        that.fire('remove');
                        return false;
                    });
                    this.$edit_view.append(' ');
                    this.$edit_view.append($deleteButton);
                }
                this.$noedit_view = $('
');

                this.setEdit(this.edit);
            };
            InputMap.prototype = {
                val: function(map_key, map_val, translated_map_val) {
                    if (map_key == undefined) {
                        return this.value;
                    } else {
                        this.value = {
                            key: map_key,
                            val: map_val
                        };
                        this.$edit_view.find(".enum-key").val(map_key);
                        this.$edit_view.find(".enum-value").val(map_val);
                        if (map_val == "" && translated_map_val != undefined && translated_map_val != "") {
                            this.$edit_view.find(".enum-value").attr("placeholder", translated_map_val.value);
                            var $langcodeButton = langcodeTag.button_tag($(''),
                                translated_map_val.lang);
                            $langcodeButton.button.attr("style", "margin-left: 3px; margin-right: 10px;");
                            this.$edit_view.find(".enum-value").after($langcodeButton.button);
                            this.on('change', function () {
                                if (this.$edit_view.find(".enum-value").val() == "")
                                    $langcodeButton.button.show();
                                else
                                    $langcodeButton.button.hide();
                            })

                        }
                        if(map_key) {
                            this.$noedit_view.text('"'+map_key+'" => "'+map_val+'"');
                        }else{
                            this.$noedit_view.text("");
                        }
                        return this;
                    }
                },
                setEdit: function(edit) {
                    this.edit = edit;
                    this.$edit_view.detach();
                    this.$noedit_view.detach();
                    if (this.edit) {
                        this.$edit_view.appendTo(this.ui);
                    } else {
                        this.$noedit_view.appendTo(this.ui);
                    }
                    return this;
                }
            };
            return function (show_del_button) {
                return new InputMap(show_del_button);
            };
        }()),
        checkbox: (function () {
            var Checkbox = function () {
                var that = this;
                eventize(this);
                this.ui = $('');
                this.value = true;
                this.edit = true;

                this.$edit_view = $('<input type="checkbox"/>').change(function () {
                    that.fire('change');
                });
                this.$noedit_view = $('
');

                this.on('change', function () {
                    this.val(this.ui.find('input').prop('checked'));
                });
                this.val(this.value);
                this.setEdit(this.edit);
            };
            Checkbox.CHECKED = "icon-ok";
            Checkbox.UNCHECKED = "";
            Checkbox.prototype = {
                val: function (value) {
                    if (value === undefined) {
                        return this.value;
                    } else {
                        this.value = value;
                        this.$edit_view.prop('checked', this.value);
                        this.$noedit_view.removeClass(
                            this.value ? Checkbox.UNCHECKED : Checkbox.CHECKED
                        ).addClass(
                            this.value ? Checkbox.CHECKED : Checkbox.UNCHECKED
                        );
                        return this;
                    }
                },
                setEdit: function (edit) {
                    this.edit = edit;
                    this.$edit_view.detach();
                    this.$noedit_view.detach();
                    if (this.edit) {
                        this.$edit_view.appendTo(this.ui);
                    } else {
                        this.$noedit_view.appendTo(this.ui);
                    }
                    return this;
                }
            };
            return function () {
                return new Checkbox();
            };
        }()),
        serialize: function (obj) {
            var i, cpy;
            if (typeof obj.val === 'function') {
                return obj.val();
            } else if (_.isArray(obj)) {
                return _.map(obj, uiElement.serialize);
            } else if (_.isObject(obj)) {
                cpy = _.clone(obj);
                _.chain(cpy).map(function (value, key) {
                    cpy[key] = uiElement.serialize(value);
                });
                return cpy;
            } else {
                return obj;
            }
        }
    };
}());<commit_msg>fix language bleed-through popover<commit_after>/*globals $, eventize, _ */

var langcodeTag;

(function () {
    'use strict';

    langcodeTag = {
        LANG_DELIN: "{{[[*LANG*]]}}",
        button_tag: (function () {
            var LangCodeButton = function ($elem, new_lang) {
                this.button = $elem;
                this.button.click(function () {
                    return false;
                });
                this.lang_code = new_lang;
                this.lang(new_lang);
            };
            LangCodeButton.prototype = {
                lang: function (value) {
                    if (value === undefined) {
                        return this.lang_code;
                    } else {
                        this.lang_code = value;
                        this.button.text(this.lang_code);
                        this.button.popover({
                            title: "Using '" + this.lang_code + "' Value",
                            content: "There is no translation available for the currently selected language.

Using text from the [" +
                                this.lang_code + "] language by default. Edit the value and save to override defaults.",
                            html: true,
                            trigger: 'hover'
                        });
                    }
                }
            };
            return function ($elem, new_lang) {
                return new LangCodeButton($elem, new_lang);
            };
        }()),
        translate_delim: (function () {
            return function (value) {
                var values = value.split(langcodeTag.LANG_DELIN);
                var langcode = null;
                if (values.length > 1)
                    langcode = values[1];
                return {
                    value: values[0],
                    lang: langcode
                };
            };
        }())
    };

}());

var uiElement;
(function () {
    'use strict';

    var Input = function ($elem, getElemValue, setElemValue, setPlaceholderValue) {
        var that = this;
        eventize(this);
        this.ui = $('
');
        this.value = "";
        this.edit = true;
        this.getElemValue = function () {
            return getElemValue($elem);
        };
        this.setElemValue = function (value) {
            setElemValue($elem, value);
        };
        this.setPlaceholderValue = function (value) {
            setPlaceholderValue($elem, value);
        };

        this.$edit_view = $elem.bind('change textchange', function () {
            that.fire('change');
        });
        this.$noedit_view = $('');

        this.on('change', function () {
            this.value = this.getElemValue();
            this.$noedit_view.text(this.value);
        });
        this.setEdit(this.edit);
    };
    Input.prototype = {
        val: function (value) {
            if (value === undefined) {
                return this.value;
            } else {
                this.value = value;
                this.setVisibleValue(this.value);
                return this;
            }
        },
        setVisibleValue: function (value) {
            var translated = langcodeTag.translate_delim(value);
            this.ui.find('.lang-text').remove();
            if (translated.lang) {
                var langcode_button = langcodeTag.button_tag($(''),
                    translated.lang);
                this.ui.append(langcode_button.button);
                this.setPlaceholderValue(translated.value);
                this.$edit_view.change(function () {
                    if ($(this).val() == "")
                        langcode_button.button.show();
                    else
                        langcode_button.button.hide();
                });
            } else
                this.setElemValue(translated.value);
            this.$noedit_view.text(translated.value);
        },
        setEdit: function (edit) {
            this.edit = edit;
            this.$edit_view.detach();
            this.$noedit_view.detach();
            if (this.edit) {
                this.$edit_view.prependTo(this.ui);
            } else {
                this.$noedit_view.prependTo(this.ui);
            }
            return this;
        }
    };

    uiElement = {
        input: (function () {
            return function () {
                return new Input($('<input type="text"/>'), function ($elem) {
                    return $elem.val();
                }, function ($elem, value) {
                    return $elem.val(value);
                }, function ($elem, value){
                    return $elem.attr('placeholder', value);
                });
            };
        }()),
        textarea: function () {
            return new Input($('<textarea/>'), function ($elem) {
                return $elem.val();
            }, function ($elem, value) {
                return $elem.val($elem, value);
            }, function ($elem, value){
                $elem.attr('placeholder', value);
            });
        },
        select: (function () {
            var Select = function (options) {
                var that = this,
                    i,
                    option;
                eventize(this);
                this.ui = $('');
                this.value = "";
                this.edit = true;
                this.options = options;

                this.on('change', function () {
                    this.val(this.ui.find('select').val());
                });

                this.$edit_view = $('<select/>').change(function () {
                    that.fire('change');
                });
                for (i = 0; i < this.options.length; i += 1) {
                    option = this.options[i];
                    $('<option/>').text(option.label).val(option.value).appendTo(this.$edit_view);
                }

                this.$noedit_view = $('');

                this.setEdit(this.edit);
            };
            Select.prototype = {
                val: function (value) {
                    var i, option, label;
                    if (value === undefined) {
                        return this.value;
                    } else {
                        this.value = value;
                        for (i = 0; i < this.options.length; i += 1) {
                            option = this.options[i];
                            if (option.value === value) {
                                label = option.label;
                                break;
                            }
                        }
                        this.$edit_view.val(this.value.toString());
                        this.$noedit_view.text(label);
                        return this;
                    }
                },
                setEdit: function (edit) {
                    this.edit = edit;
                    this.$edit_view.detach();
                    this.$noedit_view.detach();
                    if (this.edit) {
                        this.$edit_view.appendTo(this.ui);
                    } else {
                        this.$noedit_view.appendTo(this.ui);
                    }
                    return this;
                }
            };
            return function (options) {
                return new Select(options);
            };
        }()),
        map_list: (function() {
            var KeyValList = function(guid, modal_title) {
                var that = this;
                eventize(this);
                this.ui = $('
');
                this.value = {};
                this.translated_value = {};
                this.edit = true;
                this.modal_id = 'enumModal-'+guid;
                this.modal_title = modal_title;

                this.$edit_view = $('
');
                this.$noedit_view = $('
');
                this.$formatted_view = $('<input type="hidden" />');
                this.$modal_trigger = $('').html(' Edit');

                // Create new modal controller for this element
                var $enumModal = $('
');
                $enumModal.prepend('
×
Edit Mapping for '+this.modal_title+'

');
                var $modal_form = $('<form class="form-horizontal hq-enum-editor" action="" />'),
                    $modal_body = $('
');
                $modal_body.append($('<fieldset />'));
                $modal_body.append('
 Add Key => Value Mapping
');

                $modal_form.append($modal_body);
                $modal_form.append('
<button class="btn btn-primary" data-dismiss="modal">Done</button>
');
                $enumModal.append($modal_form);

                $('#hq-modal-home').append($enumModal);

                $('#'+this.modal_id).on('hide', function() {
                    var $inputMap = $(this).find('form .hq-input-map'),
                        pairs = {};
                    for (var i=0; i < $inputMap.length; i++) {
                        var key = $($inputMap[i]).find('.enum-key').val(),
                            mapVal = $($inputMap[i]).find('.enum-value').val();
                        if (key !== undefined){
                            pairs[key] = mapVal.toString();
                        }
                    }
                    that.val(pairs);
                    that.fire('change');
                });

                $('#'+this.modal_id+' a').click(function() {
                    if($(this).attr('data-enum-action') == 'add') {
                        $(this).parent().parent().find('fieldset').append(uiElement.input_map(true).ui);
                        $(this).parent().parent().find('fieldset input.enum-key').last().focus();
                    }
                    if (!$(this).attr('data-dismiss'))
                        return false;
                });

                this.setEdit(this.edit);
            };
            KeyValList.prototype = {
                val: function(original_pairs, translated_pairs) {
                    if (original_pairs === undefined) {
                        return this.value;
                    } else {
                        var $modal_fields = $('#'+this.modal_id+' form fieldset');
                        $modal_fields.text('');
                        this.$noedit_view.text('');
                        this.$edit_view.text('');

                        this.value = original_pairs;
                        if (translated_pairs != undefined) {
                            this.translated_value = translated_pairs;
                        }
                        this.$formatted_view.val(JSON.stringify(this.value));
                        for (var key in this.value) {
                            $modal_fields.append(uiElement.input_map(true).val(key, this.value[key], this.translated_value[key]).ui);
                            this.$edit_view.append(uiElement.input_map(true).val(key, this.value[key], this.translated_value[key]).setEdit(false).$noedit_view);
                        }
                    }

                },
                setEdit: function(edit) {
                    this.edit = edit;
                    this.$edit_view.detach();
                    this.$noedit_view.detach();
                    this.$modal_trigger.detach();
                    if (this.edit) {
                        this.$edit_view.appendTo(this.ui);
                        this.$modal_trigger.appendTo(this.ui);
                        this.$formatted_view.appendTo(this.ui);
                    } else {
                        this.$noedit_view.appendTo(this.ui);
                    }
                    return this;
                }
            };
            return function (guid, modal_title) {
                return new KeyValList(guid, modal_title);
            };
        }()),
        input_map: (function() {
            var InputMap = function (show_del_button) {
                var that = this;
                eventize(this);
                this.ui = $('
');
                this.value = {
                    key: "",
                    val: ""
                };
                this.edit = true;
                this.show_delete = show_del_button;
                this.on('change', function() {
                    this.val(this.ui.find(".enum-key").val(), this.ui.find(".enum-value").val())
                });
                this.on('remove', function() {
                    this.ui.remove();
                });

                this.$edit_view = $('
');
                var key_input = $('<input type="text" class="input-small enum-key" placeholder="key" />'),
                    val_input = $('<input type="text" class="input-large enum-value" placeholder="value" />');
                key_input.change(function () {
                    that.fire('change');
                });
                val_input.change(function() {
                    that.fire('change');
                });
                this.$edit_view.append(key_input);
                this.$edit_view.append(' => ')
                this.$edit_view.append(val_input);
                if(this.show_delete) {
                    var $deleteButton = $('');
                    $deleteButton.append(' Delete');
                    $deleteButton.click(function() {
                        that.fire('remove');
                        return false;
                    });
                    this.$edit_view.append(' ');
                    this.$edit_view.append($deleteButton);
                }
                this.$noedit_view = $('
');

                this.setEdit(this.edit);
            };
            InputMap.prototype = {
                val: function(map_key, map_val, translated_map_val) {
                    if (map_key == undefined) {
                        return this.value;
                    } else {
                        this.value = {
                            key: map_key,
                            val: map_val
                        };
                        this.$edit_view.find(".enum-key").val(map_key);
                        this.$edit_view.find(".enum-value").val(map_val);
                        if (map_val == "" && translated_map_val != undefined && translated_map_val != "") {
                            this.$edit_view.find(".enum-value").attr("placeholder", translated_map_val.value);
                            var $langcodeButton = langcodeTag.button_tag($(''),
                                translated_map_val.lang);
                            $langcodeButton.button.attr("style", "margin-left: 3px; margin-right: 10px;");
                            this.$edit_view.find(".enum-value").after($langcodeButton.button);
                            this.on('change', function () {
                                if (this.$edit_view.find(".enum-value").val() == "")
                                    $langcodeButton.button.show();
                                else
                                    $langcodeButton.button.hide();
                            })

                        }
                        if(map_key) {
                            this.$noedit_view.text('"'+map_key+'" => "'+map_val+'"');
                        }else{
                            this.$noedit_view.text("");
                        }
                        return this;
                    }
                },
                setEdit: function(edit) {
                    this.edit = edit;
                    this.$edit_view.detach();
                    this.$noedit_view.detach();
                    if (this.edit) {
                        this.$edit_view.appendTo(this.ui);
                    } else {
                        this.$noedit_view.appendTo(this.ui);
                    }
                    return this;
                }
            };
            return function (show_del_button) {
                return new InputMap(show_del_button);
            };
        }()),
        checkbox: (function () {
            var Checkbox = function () {
                var that = this;
                eventize(this);
                this.ui = $('');
                this.value = true;
                this.edit = true;

                this.$edit_view = $('<input type="checkbox"/>').change(function () {
                    that.fire('change');
                });
                this.$noedit_view = $('
');

                this.on('change', function () {
                    this.val(this.ui.find('input').prop('checked'));
                });
                this.val(this.value);
                this.setEdit(this.edit);
            };
            Checkbox.CHECKED = "icon-ok";
            Checkbox.UNCHECKED = "";
            Checkbox.prototype = {
                val: function (value) {
                    if (value === undefined) {
                        return this.value;
                    } else {
                        this.value = value;
                        this.$edit_view.prop('checked', this.value);
                        this.$noedit_view.removeClass(
                            this.value ? Checkbox.UNCHECKED : Checkbox.CHECKED
                        ).addClass(
                            this.value ? Checkbox.CHECKED : Checkbox.UNCHECKED
                        );
                        return this;
                    }
                },
                setEdit: function (edit) {
                    this.edit = edit;
                    this.$edit_view.detach();
                    this.$noedit_view.detach();
                    if (this.edit) {
                        this.$edit_view.appendTo(this.ui);
                    } else {
                        this.$noedit_view.appendTo(this.ui);
                    }
                    return this;
                }
            };
            return function () {
                return new Checkbox();
            };
        }()),
        serialize: function (obj) {
            var i, cpy;
            if (typeof obj.val === 'function') {
                return obj.val();
            } else if (_.isArray(obj)) {
                return _.map(obj, uiElement.serialize);
            } else if (_.isObject(obj)) {
                cpy = _.clone(obj);
                _.chain(cpy).map(function (value, key) {
                    cpy[key] = uiElement.serialize(value);
                });
                return cpy;
            } else {
                return obj;
            }
        }
    };
}());<|endoftext|>


<commit_before>const fs = require('fs');
const path = require('path');
const checkIfCoreVariation = require('./core-utils');

function getPuppeteerChromiumVersion() {
  const puppeteerLibrary = checkIfCoreVariation() ? 'puppeteer-core' : 'puppeteer';
  const puppeteerPath = path.dirname(require.resolve(puppeteerLibrary));
  const puppeteerPackagePath = path.join(puppeteerPath, 'package.json');
  // eslint-disable-next-line import/no-dynamic-require,global-require
  const puppeteerJson = require(puppeteerPackagePath);
  return puppeteerJson.puppeteer.chromium_revision;
}

(function updatePuppeteerConfiguration() {
  console.log('extract puppeteer chromium version from module \'puppeteer|pupetter-core\'');

  const chromiumRevision = getPuppeteerChromiumVersion();
  const configPath = path.join(__dirname, '../puppeteer-config.json');
  // eslint-disable-next-line global-require,import/no-dynamic-require
  const configJson = require(configPath);
  configJson.chromiumRevision = chromiumRevision;

  fs.writeFileSync(configPath, JSON.stringify(configJson, null, '  '));

  console.log(`update 'src/puppeteer-config.json' file with puppeteer chroumium revision '${chromiumRevision}'`);
}());
<commit_msg>update puppeteer util file<commit_after>const fs = require('fs');
const path = require('path');
const checkIfCoreVariation = require('./core-utils');

function getPuppeteerChromiumVersion() {
  const puppeteerLibrary = checkIfCoreVariation() ? 'puppeteer-core' : 'puppeteer';
  const puppeteerPath = path.dirname(require.resolve(puppeteerLibrary));
  const puppeteerPackagePath = path.join(puppeteerPath, 'package.json');
  // eslint-disable-next-line import/no-dynamic-require,global-require
  const puppeteerJson = require(puppeteerPackagePath);
  return puppeteerJson.puppeteer.chromium_revision;
}

(function updatePuppeteerConfiguration() {
  console.log('extract puppeteer chromium version from module \'puppeteer|pupetter-core\'');

  const chromiumRevision = getPuppeteerChromiumVersion();
  const configPath = path.join(__dirname, '../src/puppeteer-config.json');
  // eslint-disable-next-line global-require,import/no-dynamic-require
  const configJson = require(configPath);
  configJson.chromiumRevision = chromiumRevision;

  fs.writeFileSync(configPath, JSON.stringify(configJson, null, '  '));

  console.log(`update 'src/puppeteer-config.json' file with puppeteer chroumium revision '${chromiumRevision}'`);
}());
<|endoftext|>


<commit_before>// Copyright (c) 2015 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

'use strict';

var errors = require('./errors.js');

var TOMBSTONE_TTL_OFFSET = 500;

module.exports = Operations;

function Operations(opts) {
    var self = this;

    self.timers = opts.timers;
    self.logger = opts.logger;
    self.random = opts.random;
    self.connectionStalePeriod = opts.connectionStalePeriod;

    self.connection = opts.connection;
    self.destroyed = false; // TODO need this?

    self.requests = {
        in: Object.create(null),
        out: Object.create(null)
    };
    self.pending = {
        in: 0,
        out: 0
    };
    self.lastTimeoutTime = 0;
}

function OperationTombstone(operations, id, time, timeout) {
    var self = this;

    self.isTombstone = true;
    self.operations = operations;
    self.id = id;
    self.time = time;
    self.timeout = timeout;
}

OperationTombstone.prototype.onTimeout = function onTimeout(now) {
    var self = this;

    if (self.operations.requests.out[self.id] === self) {
        delete self.operations.requests.out[self.id];
    }
};

Operations.prototype.checkLastTimeoutTime = function checkLastTimeoutTime(now) {
    var self = this;

    if (self.lastTimeoutTime &&
        now > self.lastTimeoutTime + self.connectionStalePeriod) {
        var err = errors.ConnectionStaleTimeoutError({
            lastTimeoutTime: self.lastTimeoutTime
        });
        self.connection.timedOutEvent.emit(self.connection, err);
        // TODO: y u no:
        // self.lastTimeoutTime = now;
    } else if (!self.lastTimeoutTime) {
        self.lastTimeoutTime = now;
    }
};

Operations.prototype.getRequests = function getRequests() {
    var self = this;

    return self.requests;
};

Operations.prototype.getPending = function getPending() {
    var self = this;

    return self.pending;
};

Operations.prototype.getOutReq = function getOutReq(id) {
    var self = this;

    var req = self.requests.out[id] || null;
    if (req && req.isTombstone) {
        return null;
    } else {
        return req;
    }
};

Operations.prototype.getInReq = function getInReq(id) {
    var self = this;

    return self.requests.in[id];
};

Operations.prototype.addOutReq = function addOutReq(req) {
    var self = this;

    req.operations = self;
    self.requests.out[req.id] = req;
    self.pending.out++;

    req.timeHeapHandle = self.connection.channel.timeHeap.update(req);

    return req;
};

Operations.prototype.addInReq = function addInReq(req) {
    var self = this;

    req.operations = self;
    self.requests.in[req.id] = req;
    self.pending.in++;

    req.timeHeapHandle = self.connection.channel.timeHeap.update(req);

    return req;
};

Operations.prototype.popOutReq = function popOutReq(id, context) {
    var self = this;

    var req = self.requests.out[id];
    if (!req) {
        self.logMissingOutRequest(id, context);
        return null;
    } else if (req.isTombstone) {
        return null;
    }

    if (req.timeHeapHandle) {
        req.timeHeapHandle.cancel();
        req.timeHeapHandle = null;
    }

    var now = self.timers.now();
    var timeout = TOMBSTONE_TTL_OFFSET + req.timeout;
    var tombstone = new OperationTombstone(self, req.id, now, timeout);
    req.operations = null;
    self.requests.out[id] = tombstone;
    self.pending.out--;

    self.connection.channel.timeHeap.update(tombstone, now);

    return req;
};

Operations.prototype.logMissingOutRequest =
function logMissingOutRequest(id, context) {
    var self = this;

    // context is err or res
    if (context && context.originalId) {
        context = {
            error: context,
            id: context.originalId,
            info: 'got error frame for unknown id'
        };
    } else if (context && context.id) {
        context = {
            responseId: context.id,
            code: context.code,
            arg1: Buffer.isBuffer(context.arg1) ?
                String(context.arg1) : 'streamed-arg1',
            info: 'got call response for unknown id'
        };
    }

    // This could be because of a confused / corrupted server.
    self.logger.info('popOutReq received for unknown or lost id', {
        context: context,
        socketRemoteAddr: self.connection.socketRemoteAddr,
        direction: self.connection.direction
    });
};

Operations.prototype.popInReq = function popInReq(id) {
    var self = this;

    var req = self.requests.in[id];
    if (!req) {
        // TODO warn ?
        return null;
    }

    if (req.timeHeapHandle) {
        req.timeHeapHandle.cancel();
        req.timeHeapHandle = null;
    }

    delete self.requests.in[id];
    self.pending.in--;

    return req;
};

Operations.prototype.clear = function clear() {
    var self = this;

    self.pending.in = 0;
    self.pending.out = 0;
};

Operations.prototype.destroy = function destroy() {
    var self = this;

    self.destroyed = true;
};

Operations.prototype.sanitySweep = function sanitySweep() {
    var self = this;

    self._sweepOps(self.requests.in, 'in');
    self._sweepOps(self.requests.out, 'out');
};

Operations.prototype._sweepOps = function _sweepOps(ops, direction) {
    var self = this;

    var opKeys = Object.keys(ops);
    for (var i = 0; i < opKeys.length; i++) {
        var id = opKeys[i];
        var op = ops[id];
        if (op === undefined) {
            self.logger.warn('unexpected undefined operation', {
                direction: direction,
                id: id
            });
        } else if (op.timedOut) {
            self.logger.warn('lingering timed-out operation', {
                direction: direction,
                id: id
            });

            if (direction === 'in') {
                self.popInReq(id);
            } else if (direction === 'out') {
                self.popOutReq(id);
            }
        }
    }
};
<commit_msg>Operations: defer connection timed out emit out of check<commit_after>// Copyright (c) 2015 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

'use strict';

var errors = require('./errors.js');

var TOMBSTONE_TTL_OFFSET = 500;

module.exports = Operations;

function Operations(opts) {
    var self = this;

    self.timers = opts.timers;
    self.logger = opts.logger;
    self.random = opts.random;
    self.connectionStalePeriod = opts.connectionStalePeriod;

    self.connection = opts.connection;
    self.destroyed = false; // TODO need this?

    self.requests = {
        in: Object.create(null),
        out: Object.create(null)
    };
    self.pending = {
        in: 0,
        out: 0
    };
    self.lastTimeoutTime = 0;
}

function OperationTombstone(operations, id, time, timeout) {
    var self = this;

    self.isTombstone = true;
    self.operations = operations;
    self.id = id;
    self.time = time;
    self.timeout = timeout;
}

OperationTombstone.prototype.onTimeout = function onTimeout(now) {
    var self = this;

    if (self.operations.requests.out[self.id] === self) {
        delete self.operations.requests.out[self.id];
    }
};

Operations.prototype.checkLastTimeoutTime = function checkLastTimeoutTime(now) {
    var self = this;

    if (self.lastTimeoutTime &&
        now > self.lastTimeoutTime + self.connectionStalePeriod) {
        var err = errors.ConnectionStaleTimeoutError({
            lastTimeoutTime: self.lastTimeoutTime
        });
        process.nextTick(function opCheckLastTimedout() {
            self.connection.timedOutEvent.emit(self.connection, err);
        });
    } else if (!self.lastTimeoutTime) {
        self.lastTimeoutTime = now;
    }
};

Operations.prototype.getRequests = function getRequests() {
    var self = this;

    return self.requests;
};

Operations.prototype.getPending = function getPending() {
    var self = this;

    return self.pending;
};

Operations.prototype.getOutReq = function getOutReq(id) {
    var self = this;

    var req = self.requests.out[id] || null;
    if (req && req.isTombstone) {
        return null;
    } else {
        return req;
    }
};

Operations.prototype.getInReq = function getInReq(id) {
    var self = this;

    return self.requests.in[id];
};

Operations.prototype.addOutReq = function addOutReq(req) {
    var self = this;

    req.operations = self;
    self.requests.out[req.id] = req;
    self.pending.out++;

    req.timeHeapHandle = self.connection.channel.timeHeap.update(req);

    return req;
};

Operations.prototype.addInReq = function addInReq(req) {
    var self = this;

    req.operations = self;
    self.requests.in[req.id] = req;
    self.pending.in++;

    req.timeHeapHandle = self.connection.channel.timeHeap.update(req);

    return req;
};

Operations.prototype.popOutReq = function popOutReq(id, context) {
    var self = this;

    var req = self.requests.out[id];
    if (!req) {
        self.logMissingOutRequest(id, context);
        return null;
    } else if (req.isTombstone) {
        return null;
    }

    if (req.timeHeapHandle) {
        req.timeHeapHandle.cancel();
        req.timeHeapHandle = null;
    }

    var now = self.timers.now();
    var timeout = TOMBSTONE_TTL_OFFSET + req.timeout;
    var tombstone = new OperationTombstone(self, req.id, now, timeout);
    req.operations = null;
    self.requests.out[id] = tombstone;
    self.pending.out--;

    self.connection.channel.timeHeap.update(tombstone, now);

    return req;
};

Operations.prototype.logMissingOutRequest =
function logMissingOutRequest(id, context) {
    var self = this;

    // context is err or res
    if (context && context.originalId) {
        context = {
            error: context,
            id: context.originalId,
            info: 'got error frame for unknown id'
        };
    } else if (context && context.id) {
        context = {
            responseId: context.id,
            code: context.code,
            arg1: Buffer.isBuffer(context.arg1) ?
                String(context.arg1) : 'streamed-arg1',
            info: 'got call response for unknown id'
        };
    }

    // This could be because of a confused / corrupted server.
    self.logger.info('popOutReq received for unknown or lost id', {
        context: context,
        socketRemoteAddr: self.connection.socketRemoteAddr,
        direction: self.connection.direction
    });
};

Operations.prototype.popInReq = function popInReq(id) {
    var self = this;

    var req = self.requests.in[id];
    if (!req) {
        // TODO warn ?
        return null;
    }

    if (req.timeHeapHandle) {
        req.timeHeapHandle.cancel();
        req.timeHeapHandle = null;
    }

    delete self.requests.in[id];
    self.pending.in--;

    return req;
};

Operations.prototype.clear = function clear() {
    var self = this;

    self.pending.in = 0;
    self.pending.out = 0;
};

Operations.prototype.destroy = function destroy() {
    var self = this;

    self.destroyed = true;
};

Operations.prototype.sanitySweep = function sanitySweep() {
    var self = this;

    self._sweepOps(self.requests.in, 'in');
    self._sweepOps(self.requests.out, 'out');
};

Operations.prototype._sweepOps = function _sweepOps(ops, direction) {
    var self = this;

    var opKeys = Object.keys(ops);
    for (var i = 0; i < opKeys.length; i++) {
        var id = opKeys[i];
        var op = ops[id];
        if (op === undefined) {
            self.logger.warn('unexpected undefined operation', {
                direction: direction,
                id: id
            });
        } else if (op.timedOut) {
            self.logger.warn('lingering timed-out operation', {
                direction: direction,
                id: id
            });

            if (direction === 'in') {
                self.popInReq(id);
            } else if (direction === 'out') {
                self.popOutReq(id);
            }
        }
    }
};
<|endoftext|>


<commit_before>#!/usr/bin/env node

var fs = require('fs')
    , notifier = require('node-notifier')
    , path = require('path')
    , prettyjson = require('prettyjson')
    , request = require('request');

/**
 * Function to decide if all outlets
 * or a specific one should be triggered
 * @param  {Array} config
 * @param  {String} command
 * @param  {Outlet} outlet  (optional)
 * @return {Bool}
 */
function controlHomeServer(config, command, outlet){
  // If outlet exists, only control a single one
  if (outlet) {
    sendStateToHomeServer(config, command, outlet);
  } else {
    // Otherwise, control all configured
    for(var outlet in config.outlets){
      outlet = config.outlets[outlet];
      sendStateToHomeServer(config, command, outlet);
    }
  }

  return true;
}

/**
 * Function to send a specifc state to a
 * specific outlet
 * @param  {Array} config
 * @param  {String} command
 * @param  {Outlet} outlet  (optional)
 * @return {Bool}
 */
function sendStateToHomeServer(config, command, outlet){
  // Translate state into "mother tounge" of home server
  var state = (command == 'on' ? 'ein' : 'aus');
  // Construct URL
  var url = config.server + '/' + config.office + 'licht0' + outlet + state;

  // Fire actual request
  request
    .get(url)
    .on('error', function(err) {
      var notifierObject = {
        'title': 'giraCLI'
      };

      // Make sure to ignore the "socket hang up" messages, since their HTTP implemention sucks
      if (err.code === 'ECONNRESET') {
        notifierObject.message = 'Successfully trigger outlet "' + config.office + ':' + outlet + '"';
        notifierObject.icon = path.join(__dirname, 'assets', 'success.png');
        notifier.notify(notifierObject);
        console.log(notifierObject.message);
        return true;
      } else {
        notifierObject.message = 'Failed to trigger outlet "' + config.office + ':' + outlet + '"';
        notifierObject.icon = path.join(__dirname, 'assets', 'error.png');
        notifier.notify(notifierObject);
        console.log(notifierObject.message);
        return false;
      }
    });
}

// Check if configuration file exists
if (!fs.existsSync(path.join(process.env.HOME, '.gira.json'))) {
  console.log('Error')
} else {
  // Load configuration into variable
  var config = require(path.join(process.env.HOME, '.gira.json'));
}

// Initiate argument parser
var yargs = require('yargs')
  .usage('Usage: $0 <command> [options]')
  .command('config', 'Print configuration')
  .command('on [outlet]', 'Power on outlets')
  .command('off [outlet]', 'Power off outlets')
  .demandCommand(1, 'No argument given. Make sure to provide a valid sub-command!')
  .alias('v', 'version')
  .version(function() { return require('./package').version; })
  .describe('v', 'show version information'),
  argv = yargs.argv,
  command = argv._[0];

// Process sub commands
if (command === 'config') {
  yargs.reset()
    .usage('$0 config')
    .help('h')
    .example('$0 config', 'Print loaded configuration')
    .argv;

  // Print current configuration
  console.log(prettyjson.render(config));
} else if (command === 'on') {
  yargs.reset()
    .usage('$0 on')
    .help('h')
    .example('$0 on', 'Turn on all the configured outlets')
    .example('$0 on 13', 'Turn on only outlet #13')
    .argv;

    // Store possible outlet in variable
    var outlet = yargs.argv._[1];
    // Call function to control the home server
    controlHomeServer(config, command, outlet);
} else if (command === 'off'){
  yargs.reset()
    .usage('$0 world')
    .help('h')
    .example('$0 off', 'Turn off all the configured outlets')
    .example('$0 off 13', 'Turn off only outlet #13')
    .argv;

    // Store possible outlet in variable
    var outlet = yargs.argv._[1];
    // Call function to control the home server
    controlHomeServer(config, command, outlet);
} else {
  yargs.showHelp();
}
<commit_msg>Old school function<commit_after>#!/usr/bin/env node

var fs = require('fs')
    , notifier = require('node-notifier')
    , path = require('path')
    , prettyjson = require('prettyjson')
    , request = require('request');

/**
 * Function to decide if all outlets
 * or a specific one should be triggered
 * @param  {Array} config
 * @param  {String} command
 * @param  {Outlet} outlet  (optional)
 * @return {Bool}
 */
function controlHomeServer(config, command, outlet){
  // If outlet exists, only control a single one
  if (outlet) {
    sendStateToHomeServer(config, command, outlet);
  } else {
    // Otherwise, control all configured
    for(var outlet in config.outlets){
      outlet = config.outlets[outlet];
      sendStateToHomeServer(config, command, outlet);
    }
  }

  return true;
}

/**
 * Function to send a specifc state to a
 * specific outlet
 * @param  {Array} config
 * @param  {String} command
 * @param  {Outlet} outlet  (optional)
 * @return {Bool}
 */
function sendStateToHomeServer(config, command, outlet){
  // Translate state into "mother tounge" of home server
  var state = (command == 'on' ? 'ein' : 'aus');
  // Construct URL
  var url = config.server + '/' + config.office + 'licht0' + outlet + state;

  var notifierObject = {
    'title': 'giraCLI'
  };

  request(url, function (error, response, body) {
    if (error.code === 'ECONNRESET') {
      notifierObject.message = 'Successfully trigger outlet "' + config.office + ':' + outlet + '"';
      notifierObject.icon = path.join(__dirname, 'assets', 'success.png');
      notifier.notify(notifierObject);
      console.log(notifierObject.message);
      return true;
    } else {
      notifierObject.message = 'Failed to trigger outlet "' + config.office + ':' + outlet + '"';
      notifierObject.icon = path.join(__dirname, 'assets', 'error.png');
      notifier.notify(notifierObject);
      console.log(notifierObject.message);
      return false;
    }
  })
}

// Check if configuration file exists
if (!fs.existsSync(path.join(process.env.HOME, '.gira.json'))) {
  console.log('Error')
} else {
  // Load configuration into variable
  var config = require(path.join(process.env.HOME, '.gira.json'));
}

// Initiate argument parser
var yargs = require('yargs')
  .usage('Usage: $0 <command> [options]')
  .command('config', 'Print configuration')
  .command('on [outlet]', 'Power on outlets')
  .command('off [outlet]', 'Power off outlets')
  .demandCommand(1, 'No argument given. Make sure to provide a valid sub-command!')
  .alias('v', 'version')
  .version(function() { return require('./package').version; })
  .describe('v', 'show version information'),
  argv = yargs.argv,
  command = argv._[0];

// Process sub commands
if (command === 'config') {
  yargs.reset()
    .usage('$0 config')
    .help('h')
    .example('$0 config', 'Print loaded configuration')
    .argv;

  // Print current configuration
  console.log(prettyjson.render(config));
} else if (command === 'on') {
  yargs.reset()
    .usage('$0 on')
    .help('h')
    .example('$0 on', 'Turn on all the configured outlets')
    .example('$0 on 13', 'Turn on only outlet #13')
    .argv;

    // Store possible outlet in variable
    var outlet = yargs.argv._[1];
    // Call function to control the home server
    controlHomeServer(config, command, outlet);
} else if (command === 'off'){
  yargs.reset()
    .usage('$0 world')
    .help('h')
    .example('$0 off', 'Turn off all the configured outlets')
    .example('$0 off 13', 'Turn off only outlet #13')
    .argv;

    // Store possible outlet in variable
    var outlet = yargs.argv._[1];
    // Call function to control the home server
    controlHomeServer(config, command, outlet);
} else {
  yargs.showHelp();
}
<|endoftext|>


<commit_before>var controllers = angular.module('mesos-es-ui.controllers', []);

controllers.controller('MainController', function($scope, $interval, $route, config, Cluster, Tasks) {
    $scope.$route = $route;

    /** Responsiveness helpers **/
    var mobileView = 992;
    $scope.getWidth = function() {
        return window.innerWidth;
    };
    $scope.$watch($scope.getWidth, function(newValue, oldValue) {
        if (newValue >= mobileView) {
            $scope.toggle = true;
        } else {
            $scope.toggle = false;
        }
    });
    $scope.toggleSidebar = function() {
        $scope.toggle = !$scope.toggle;
    };
    window.onresize = function() {
        $scope.$apply();
    };

    /** Cluster info **/
    var fetchClusterConfiguration = function() {
        Cluster.get(function (data) {
            $scope.name = data.name;
            $scope.configuration = data.configuration;
        });
    };
    fetchClusterConfiguration();

    /** Tasks monitoring **/
    $scope.tasks = [];
    $scope.nodes = [];
    $scope.statesPercentage = [];
    var fetchInterval = 5000; // ms

    $scope.taskStatesMapping = {
        TASK_RUNNING: {
            progressBarType: "success"
        },
        TASK_FAILED: {
            progressBarType: "warning"
        },
        TASK_ERROR: {
            progressBarType: "danger"
        },
        TASK_STARTING: {
            progressBarType: "primary"
        },
        TASK_FINISHED: {
            progressBarType: "info"
        },
        TASK_LOST: {
            progressBarType: "danger"
        }
    };

    var updateStatesPercentage = function(states, tasksData) {
        var statesPercentage = [];
        angular.forEach(states, function(value, key) {
            if ($scope.taskStatesMapping[key]) {
                statesPercentage.push({
                    state: key,
                    type: $scope.taskStatesMapping[key].progressBarType,
                    percentage: Math.round(value.length / tasksData.length * 100)
                });
            }
        });
        statesPercentage.sort(function(a, b) {
            return (a.state < b.state) ? 1 : -1;
        });
        $scope.statesPercentage = statesPercentage;
    };
    var updateTasks = function(data) {
        $scope.tasks = data;
        var nodes = [];
        var states = {};
        angular.forEach(data, function(value, key) {
            nodes.push(value.hostname + ":" + value.http_address.split(":")[1]);
            states.hasOwnProperty(value.state) || (states[value.state] = []);
            states[value.state].push(value.http_address);
        });
        $scope.nodes = nodes;
        updateStatesPercentage(states, data);
    };
    var fetchTasks = function() {
        Tasks.query(function (data) {
            updateTasks(data);
        });
    };
    fetchTasks();
    $interval(fetchTasks, fetchInterval);
});

controllers.controller('ClusterController', function($scope, $http, $location, config, Cluster) {
    $scope.query = {
        error: '',
        string: '',
        node: '',
        results: null,
    };

    $scope.$parent.$watch('nodes', function(value) {
        if (value.length && $scope.query.node == '') {
            $scope.query.node = value[0];
        }
    });

    $scope.querySubmit = function() {
        if ($scope.query.node && $scope.query.string) {
            $http.defaults.headers.common['X-ElasticSearch-Host'] = $scope.query.node;
            var URL = $location.protocol() + '://' + $location.host() + ':' + $location.port() + "/es/_search?q=" + $scope.query.string;
            $http.get(URL).success(function(data, status, headers) {
                $scope.query.results = data;
            }).error(function(data, status, headers) {
                if (data.hasOwnProperty('error')) {
                    $scope.query.error = data.error;
                } else {
                    $scope.query.error = "Unknown error"
                }
            });
        }
    };

    $scope.resetQuery = function() {
        $scope.query.error = '';
        $scope.query.string = '';
        $scope.query.results = null;
    };
});

controllers.controller('TasksController', function ($scope, $interval, config, Tasks) {

});
<commit_msg>Fixed GUI task states mapping.<commit_after>var controllers = angular.module('mesos-es-ui.controllers', []);

controllers.controller('MainController', function($scope, $interval, $route, config, Cluster, Tasks) {
    $scope.$route = $route;

    /** Responsiveness helpers **/
    var mobileView = 992;
    $scope.getWidth = function() {
        return window.innerWidth;
    };
    $scope.$watch($scope.getWidth, function(newValue, oldValue) {
        if (newValue >= mobileView) {
            $scope.toggle = true;
        } else {
            $scope.toggle = false;
        }
    });
    $scope.toggleSidebar = function() {
        $scope.toggle = !$scope.toggle;
    };
    window.onresize = function() {
        $scope.$apply();
    };

    /** Cluster info **/
    var fetchClusterConfiguration = function() {
        Cluster.get(function (data) {
            $scope.name = data.name;
            $scope.configuration = data.configuration;
        });
    };
    fetchClusterConfiguration();

    /** Tasks monitoring **/
    $scope.tasks = [];
    $scope.nodes = [];
    $scope.statesPercentage = [];
    var fetchInterval = 5000; // ms

    $scope.taskStatesMapping = {
        TASK_STAGING: {
            progressBarType: "warning"
        },
        TASK_RUNNING: {
            progressBarType: "success"
        },
        TASK_FAILED: {
            progressBarType: "warning"
        },
        TASK_ERROR: {
            progressBarType: "danger"
        },
        TASK_STARTING: {
            progressBarType: "primary"
        },
        TASK_FINISHED: {
            progressBarType: "info"
        },
        TASK_LOST: {
            progressBarType: "danger"
        }
    };

    var updateStatesPercentage = function(states, tasksData) {
        var statesPercentage = [];
        angular.forEach(states, function(value, key) {
            if ($scope.taskStatesMapping[key]) {
                statesPercentage.push({
                    state: key,
                    type: $scope.taskStatesMapping[key].progressBarType,
                    percentage: Math.round(value.length / tasksData.length * 100)
                });
            }
        });
        statesPercentage.sort(function(a, b) {
            return (a.state < b.state) ? 1 : -1;
        });
        $scope.statesPercentage = statesPercentage;
    };
    var updateTasks = function(data) {
        $scope.tasks = data;
        var nodes = [];
        var states = {};
        angular.forEach(data, function(value, key) {
            nodes.push(value.hostname + ":" + value.http_address.split(":")[1]);
            states.hasOwnProperty(value.state) || (states[value.state] = []);
            states[value.state].push(value.http_address);
        });
        $scope.nodes = nodes;
        updateStatesPercentage(states, data);
    };
    var fetchTasks = function() {
        Tasks.query(function (data) {
            updateTasks(data);
        });
    };
    fetchTasks();
    $interval(fetchTasks, fetchInterval);
});

controllers.controller('ClusterController', function($scope, $http, $location, config, Cluster) {
    $scope.query = {
        error: '',
        string: '',
        node: '',
        results: null,
    };

    $scope.$parent.$watch('nodes', function(value) {
        if (value.length && $scope.query.node == '') {
            $scope.query.node = value[0];
        }
    });

    $scope.querySubmit = function() {
        if ($scope.query.node && $scope.query.string) {
            $http.defaults.headers.common['X-ElasticSearch-Host'] = $scope.query.node;
            var URL = $location.protocol() + '://' + $location.host() + ':' + $location.port() + "/es/_search?q=" + $scope.query.string;
            $http.get(URL).success(function(data, status, headers) {
                $scope.query.results = data;
            }).error(function(data, status, headers) {
                if (data.hasOwnProperty('error')) {
                    $scope.query.error = data.error;
                } else {
                    $scope.query.error = "Unknown error"
                }
            });
        }
    };

    $scope.resetQuery = function() {
        $scope.query.error = '';
        $scope.query.string = '';
        $scope.query.results = null;
    };
});

controllers.controller('TasksController', function ($scope, $interval, config, Tasks) {

});
<|endoftext|>


<commit_before>import Layer from './layer/layer'
import MarkerClusterer from '@googlemaps/markerclustererplus'
import _ from 'lodash'
import styles from './markerClustererLayer.module.css'

const DEFAULT_COLOR = '#FFFFFF'
const DEFAULT_STROKE_COLOR = '#000000'
const SELECTED_STROKE_COLOR = '#000000'
const DEFAULT_STROKE_WIDTH = 2
const SELECTED_STROKE_WIDTH = 3
const DEFAULT_SCALE = 0.5
const SELECTED_SCALE = 0.6

export default class MarkerClustererLayer extends Layer {

    constructor({map, id, label, description}) {
        super()
        const {google, googleMap} = map.getGoogle()
        this.type = 'MarkerClustererLayer'
        this.toggleable = true
        this.google = google
        this.googleMap = googleMap
        this.id = id
        this.label = label
        this.description = description
        this.mapMarkers = {}
        this.clickable = false

        // Path from https://github.com/scottdejonge/map-icons
        this.icon = {
            path: 'M25.015 2.4c-7.8 0-14.121 6.204-14.121 13.854 0 7.652 14.121 32.746 14.121 32.746s14.122-25.094 14.122-32.746c0-7.65-6.325-13.854-14.122-13.854z',
            fillOpacity: 1,
            anchor: new this.google.maps.Point(25, 50),
            strokeWeight: DEFAULT_STROKE_WIDTH,
            strokeColor: DEFAULT_STROKE_COLOR,
            scale: DEFAULT_SCALE
        }

        this.markerCluster = new MarkerClusterer(null, [], {
            clusterClass: styles.cluster,
            maxZoom: 14
        })
        this.markerCluster.setStyles(
            this.markerCluster.getStyles().map(style => _.omit({...style, textColor: 'white'}, 'url'))
        )
    }

    setMarkers(markers) {
        this.mapMarkers = {}
        this.markers = markers
            .forEach(marker => {
                const {x, y} = marker
                this.mapMarkers[markerKey({x, y})] = this.toMapMarker(marker)
            })
        this.markerCluster.clearMarkers()
        this.markerCluster.addMarkers(Object.values(this.mapMarkers))
    }

    selectMarker(marker) {
        this.updateIcon(marker, {
            strokeWeight: SELECTED_STROKE_WIDTH,
            strokeColor: SELECTED_STROKE_COLOR,
            scale: SELECTED_SCALE
        })
    }

    deselectMarker(marker) {
        if (_.isFinite(marker['class'])) {
            this.updateIcon(marker, {
                strokeWeight: DEFAULT_STROKE_WIDTH,
                strokeColor: DEFAULT_STROKE_COLOR,
                scale: DEFAULT_SCALE
            })
        } else {
            this.removeMarker(marker)
        }
    }

    addMarker(marker) {
        const mapMarker = this.toMapMarker(marker)
        mapMarker.setIcon({
            ...mapMarker.getIcon(),
            strokeWeight: SELECTED_STROKE_WIDTH,
            strokeColor: SELECTED_STROKE_COLOR,
            scale: SELECTED_SCALE
        })
        this.mapMarkers[markerKey(marker)] = mapMarker
        this.markerCluster.addMarker(mapMarker)
        return mapMarker
    }

    updateMarker(marker) {
        const mapMarker = this.findMapMarker(marker)
        if (mapMarker) {
            mapMarker.data = marker
            this.updateIcon(marker, {fillColor: marker.color})
        }
    }

    removeMarker(marker) {
        const mapMarker = this.findMapMarker(marker)
        if (mapMarker) {
            this.markerCluster.removeMarker(mapMarker)
        }
        delete this.mapMarkers[markerKey(marker)]
    }

    updateIcon(marker, iconUpdate) {
        const mapMarker = this.findMapMarker(marker)
        if (mapMarker) {
            mapMarker.setIcon({...mapMarker.getIcon(), ...iconUpdate})
        }
    }

    findMapMarker(marker) {
        return this.mapMarkers[markerKey(marker)]
    }

    equals(o) {
        return _.isEqual(o && o.type, this.type)
    }

    addToMap() {
        this.markerCluster.clearMarkers()
        this.markerCluster.addMarkers(Object.values(this.mapMarkers))
        this.markerCluster.setMap(this.googleMap)
    }

    removeFromMap() {
        this.markerCluster.clearMarkers()
        this.markerCluster.setMap(null)
    }

    hide(hidden) {
        hidden
            ? this.removeFromMap()
            : this.addToMap()
    }

    toMapMarker(marker) {
        const {x, y, color = DEFAULT_COLOR, onClick} = marker
        const mapMarker = new this.google.maps.Marker({
            position: new this.google.maps.LatLng(y, x),
            draggable: false,
            icon: {...this.icon, fillColor: color},
            clickable: this.clickable
        })
        mapMarker.data = marker
        mapMarker.addListener('click', () => {
            const m = this.findMapMarker({x, y})
            m && onClick && onClick(m.data)
        })
        return mapMarker
    }

    setClickable(flag) {
        this.clickable = flag
        Object.values(this.mapMarkers || {}).forEach(marker => marker.setClickable(flag))
    }
}

const markerKey = ({x, y}) => `${x},${y}`
<commit_msg>Provided map to super class.<commit_after>import Layer from './layer/layer'
import MarkerClusterer from '@googlemaps/markerclustererplus'
import _ from 'lodash'
import styles from './markerClustererLayer.module.css'

const DEFAULT_COLOR = '#FFFFFF'
const DEFAULT_STROKE_COLOR = '#000000'
const SELECTED_STROKE_COLOR = '#000000'
const DEFAULT_STROKE_WIDTH = 2
const SELECTED_STROKE_WIDTH = 3
const DEFAULT_SCALE = 0.5
const SELECTED_SCALE = 0.6

export default class MarkerClustererLayer extends Layer {

    constructor({map, id, label, description}) {
        super({map})
        const {google, googleMap} = map.getGoogle()
        this.type = 'MarkerClustererLayer'
        this.toggleable = true
        this.google = google
        this.googleMap = googleMap
        this.id = id
        this.label = label
        this.description = description
        this.mapMarkers = {}
        this.clickable = false

        // Path from https://github.com/scottdejonge/map-icons
        this.icon = {
            path: 'M25.015 2.4c-7.8 0-14.121 6.204-14.121 13.854 0 7.652 14.121 32.746 14.121 32.746s14.122-25.094 14.122-32.746c0-7.65-6.325-13.854-14.122-13.854z',
            fillOpacity: 1,
            anchor: new this.google.maps.Point(25, 50),
            strokeWeight: DEFAULT_STROKE_WIDTH,
            strokeColor: DEFAULT_STROKE_COLOR,
            scale: DEFAULT_SCALE
        }

        this.markerCluster = new MarkerClusterer(null, [], {
            clusterClass: styles.cluster,
            maxZoom: 14
        })
        this.markerCluster.setStyles(
            this.markerCluster.getStyles().map(style => _.omit({...style, textColor: 'white'}, 'url'))
        )
    }

    setMarkers(markers) {
        this.mapMarkers = {}
        this.markers = markers
            .forEach(marker => {
                const {x, y} = marker
                this.mapMarkers[markerKey({x, y})] = this.toMapMarker(marker)
            })
        this.markerCluster.clearMarkers()
        this.markerCluster.addMarkers(Object.values(this.mapMarkers))
    }

    selectMarker(marker) {
        this.updateIcon(marker, {
            strokeWeight: SELECTED_STROKE_WIDTH,
            strokeColor: SELECTED_STROKE_COLOR,
            scale: SELECTED_SCALE
        })
    }

    deselectMarker(marker) {
        if (_.isFinite(marker['class'])) {
            this.updateIcon(marker, {
                strokeWeight: DEFAULT_STROKE_WIDTH,
                strokeColor: DEFAULT_STROKE_COLOR,
                scale: DEFAULT_SCALE
            })
        } else {
            this.removeMarker(marker)
        }
    }

    addMarker(marker) {
        const mapMarker = this.toMapMarker(marker)
        mapMarker.setIcon({
            ...mapMarker.getIcon(),
            strokeWeight: SELECTED_STROKE_WIDTH,
            strokeColor: SELECTED_STROKE_COLOR,
            scale: SELECTED_SCALE
        })
        this.mapMarkers[markerKey(marker)] = mapMarker
        this.markerCluster.addMarker(mapMarker)
        return mapMarker
    }

    updateMarker(marker) {
        const mapMarker = this.findMapMarker(marker)
        if (mapMarker) {
            mapMarker.data = marker
            this.updateIcon(marker, {fillColor: marker.color})
        }
    }

    removeMarker(marker) {
        const mapMarker = this.findMapMarker(marker)
        if (mapMarker) {
            this.markerCluster.removeMarker(mapMarker)
        }
        delete this.mapMarkers[markerKey(marker)]
    }

    updateIcon(marker, iconUpdate) {
        const mapMarker = this.findMapMarker(marker)
        if (mapMarker) {
            mapMarker.setIcon({...mapMarker.getIcon(), ...iconUpdate})
        }
    }

    findMapMarker(marker) {
        return this.mapMarkers[markerKey(marker)]
    }

    equals(o) {
        return _.isEqual(o && o.type, this.type)
    }

    addToMap() {
        this.markerCluster.clearMarkers()
        this.markerCluster.addMarkers(Object.values(this.mapMarkers))
        this.markerCluster.setMap(this.googleMap)
    }

    removeFromMap() {
        this.markerCluster.clearMarkers()
        this.markerCluster.setMap(null)
    }

    hide(hidden) {
        hidden
            ? this.removeFromMap()
            : this.addToMap()
    }

    toMapMarker(marker) {
        const {x, y, color = DEFAULT_COLOR, onClick} = marker
        const mapMarker = new this.google.maps.Marker({
            position: new this.google.maps.LatLng(y, x),
            draggable: false,
            icon: {...this.icon, fillColor: color},
            clickable: this.clickable
        })
        mapMarker.data = marker
        mapMarker.addListener('click', () => {
            const m = this.findMapMarker({x, y})
            m && onClick && onClick(m.data)
        })
        return mapMarker
    }

    setClickable(flag) {
        this.clickable = flag
        Object.values(this.mapMarkers || {}).forEach(marker => marker.setClickable(flag))
    }
}

const markerKey = ({x, y}) => `${x},${y}`
<|endoftext|>


<commit_before>// TODO FIX JSON.stringify dependency

(function($) {

  $.mite = (function() {
    // Private
    var prepare, get_url_for, set_API_key, get_ajax_options, log,
        _get,
        not_allowed,
        User;

    // prepare CORS calls to mite account
    prepare = function(options) {
      if (!options.account || !options.api_key) throw "account & api_key need to be set";

      $.mite.protocol = options.protocol || $.mite.defaults.protocol;
      $.mite.domain   = options.domain   || $.mite.defaults.domain;

      $.mite.account  = options.account;
      $.mite.api_key  = options.api_key;
    };

    // build URL for API request
    get_url_for = function(path) {
      return $.mite.protocol + '://' + $.mite.account + '.' + $.mite.domain + '/' + path + '.json';
    };

    // sets MiteApiKey header before requests gets sent
    set_API_key = function(xhr) {
      xhr.setRequestHeader("X-MiteApiKey", "715f11d946bfe4e");
      xhr.setRequestHeader("Content-Type", "application/json");
    };

    // simple logger
    error = function(xhr, textStatus, errorThrown) {
      alert(errorThrown);
    };

    // enhance options with callbacks
    get_ajax_options = function(options, callback) {
      options.dataFilter = function(data, type) {
        return (/^\s+$/.test(data)) ? '{}' : data;
      };

      if (typeof callback == 'undefined') {
        options.error = error;
        return options;
      }
      if (typeof callback == 'function') {
        options.success = callback;
        options.error = error;
        return options;
      }
      for(event in callback) {
        options[event] = callback;
        return options;
      }
    };

    // GET request
    _get = function(path, params, callback) {
      if (typeof params == 'function') {
        callback = params;
        params = {};
      }
      $.ajax(get_ajax_options({url: get_url_for(path), data: params, beforeSend: set_API_key}, callback));
    };

    // POST request
    _post = function(path, params, callback) {
      if (typeof params == 'function') {
        callback = params;
        params = {};
      }
      $.ajax(get_ajax_options({type: 'POST', url: get_url_for(path), data: JSON.stringify(params), beforeSend: set_API_key}, callback));
    };

    // PUT request
    _put = function(path, params, callback) {
      if (typeof params == 'function') {
        callback = params;
        params = {};
      }
      $.ajax(get_ajax_options({type: 'PUT', url: get_url_for(path), data: JSON.stringify(params), beforeSend: set_API_key}, callback));
    };

    // DELETE request
    _delete = function(path, callback) {
      $.ajax(get_ajax_options({type: 'DELETE', url: get_url_for(path), beforeSend: set_API_key}, callback));
    };

    // through Errors for operations that are not allowed over the mite.API
    not_allowed = function() {
      throw new Error('not allowed over API');
    };

    // http://mite.yo.lk/en/api/users.html
    User = {
      active            : function(params, callback) { _get('users',          params, callback); },
      archived          : function(params, callback) { _get('users/archived', params, callback); },
      find              : function(id, callback)     { _get('users/'+id,      callback); },
      time_entries_for  : function(ids, callback)    { _get('time_entries',   {user_id: ids}, callback); },

      create            : not_allowed,
      update            : not_allowed,
      delete            : not_allowed
    }

    // http://mite.yo.lk/en/api/customers.html
    Customer = {
      active            : function(params, callback)      {    _get('customers',          params, callback); },
      archived          : function(params, callback)      {    _get('customers/archived', params, callback); },
      find              : function(id, callback)          {    _get('customers/'+id,      callback); },
      create            : function(params, callback)      {   _post('customers',          {customer: params}, callback); },
      update            : function(id, params, callback)  {    _put('customers/'+id,      {customer: params}, callback); },
      delete            : function(id, callback)          { _delete('customers/'+id,      callback); },
      projects_for      : function(ids, callback)         {    _get('projects',           {customer_id: ids}, callback); },
      time_entries_for  : function(ids, callback)         {    _get('time_entries',       {customer_id: ids}, callback); }
    }

    // Public
    return {
      defaults : { protocol : 'http'
                 , domain   : 'mite.yo.lk'
                 },
      prepare  : prepare,
      User     : User,
      Customer : Customer
    };
  }());
}(jQuery));<commit_msg>added all resources<commit_after>(function($) {

  $.mite = (function() {
    // Private
    var prepare, get_url_for, set_API_key, get_ajax_options, log,
        _get, _post, _put, _delete,
        not_allowed,
        account, myself, TimeEntry, Tracker, Bookmark, Customer, Project, Service, User;

    // prepare CORS calls to mite account
    prepare = function(options) {
      if (!options.account || !options.api_key) throw "account & api_key need to be set";

      $.mite.config   = {}
      $.mite.config.protocol = options.protocol || $.mite.defaults.protocol;
      $.mite.config.domain   = options.domain   || $.mite.defaults.domain;

      $.mite.config.account  = options.account;
      $.mite.config.api_key  = options.api_key;
    };

    // build URL for API request
    get_url_for = function(path) {
      return $.mite.config.protocol + '://' + $.mite.config.account + '.' + $.mite.config.domain + '/' + path + '.json';
    };

    // sets MiteApiKey header before requests gets sent
    set_API_key = function(xhr) {
      xhr.setRequestHeader("X-MiteApiKey", $.mite.config.api_key);
      xhr.setRequestHeader("Content-Type", "application/json");
    };

    // simple logger
    error = function(xhr, textStatus, errorThrown) {
      alert(errorThrown);
    };

    // enhance options with callbacks
    get_ajax_options = function(options, callback) {
      options.dataFilter = function(data, type) {
        return (/^\s+$/.test(data)) ? '{}' : data;
      };

      if (typeof callback == 'undefined') {
        options.error = error;
        return options;
      }
      if (typeof callback == 'function') {
        options.success = callback;
        options.error = error;
        return options;
      }
      for(event in callback) {
        options[event] = callback;
        return options;
      }
    };

    // GET request
    _get = function(path, params, callback) {
      if (typeof params == 'function') {
        callback = params;
        params = {};
      }
      $.ajax(get_ajax_options({url: get_url_for(path), data: params, beforeSend: set_API_key}, callback));
    };

    // POST request
    _post = function(path, params, callback) {
      if (typeof params == 'function') {
        callback = params;
        params = {};
      }
      $.ajax(get_ajax_options({type: 'POST', url: get_url_for(path), data: JSON.stringify(params), beforeSend: set_API_key}, callback));
    };

    // PUT request
    _put = function(path, params, callback) {
      if (typeof params == 'function') {
        callback = params;
        params = {};
      }
      $.ajax(get_ajax_options({type: 'PUT', url: get_url_for(path), data: JSON.stringify(params), beforeSend: set_API_key}, callback));
    };

    // DELETE request
    _delete = function(path, callback) {
      $.ajax(get_ajax_options({type: 'DELETE', url: get_url_for(path), beforeSend: set_API_key}, callback));
    };

    // through Errors for operations that are not allowed over the mite.API
    not_allowed = function() {
      throw new Error('not allowed over API');
    };

    // http://mite.yo.lk/en/api/account.html
    account             = function(params, callback)      {    _get('account',            params, callback); };
    myself              = function(params, callback)      {    _get('myself',             params, callback); };

    // http://mite.yo.lk/en/api/time-entries.html
    // see also: http://mite.yo.lk/en/api/grouped-time-entries.html
    TimeEntry = {
      all               : function(params, callback)      {    _get('time_entries',       params, callback); },
      find              : function(id, callback)          {    _get('time_entries/'+id,   callback); },
      create            : function(params, callback)      {   _post('time_entries',       {time_entry: params}, callback); },
      update            : function(id, params, callback)  {    _put('time_entries/'+id,   {time_entry: params}, callback); },
      delete            : function(id, callback)          { _delete('time_entries/'+id,   callback); }
    }

    // http://mite.yo.lk/en/api/tracker.html
    Tracker = {
      find              : function(callback)              {    _get('tracker',            callback); },
      start             : function(id, callback)          {    _put('tracker/'+id,        callback); },
      stop              : function(id, callback)          { _delete('tracker/'+id,        callback); }
    }

    // http://mite.yo.lk/en/api/bookmarks.html
    Bookmark = {
      all               : function(params, callback)      {    _get('time_entries/bookmarks',               params, callback); },
      find              : function(id, callback)          {    _get('time_entries/bookmarks/'+id,           callback); },

      // TODO fix me (I guess it relates to the redirect)
      time_entries_for  : function(id, callback)          {    _get('time_entries/bookmarks/'+id+'/follow', callback); },

      create            : not_allowed,
      update            : not_allowed,
      delete            : not_allowed
    }

    // http://mite.yo.lk/en/api/customers.html
    Customer = {
      active            : function(params, callback)      {    _get('customers',          params, callback); },
      archived          : function(params, callback)      {    _get('customers/archived', params, callback); },
      find              : function(id, callback)          {    _get('customers/'+id,      callback); },
      create            : function(params, callback)      {   _post('customers',          {customer: params}, callback); },
      update            : function(id, params, callback)  {    _put('customers/'+id,      {customer: params}, callback); },
      delete            : function(id, callback)          { _delete('customers/'+id,      callback); },
      projects_for      : function(ids, callback)         {    _get('projects',           {customer_id: ids}, callback); },
      time_entries_for  : function(ids, callback)         {    _get('time_entries',       {customer_id: ids}, callback); }
    }

    // http://mite.yo.lk/en/api/projects.html
    Project = {
      active            : function(params, callback)      {    _get('projects',           params, callback); },
      archived          : function(params, callback)      {    _get('projects/archived',  params, callback); },
      find              : function(id, callback)          {    _get('projects/'+id,       callback); },
      create            : function(params, callback)      {   _post('projects',           {project: params}, callback); },
      update            : function(id, params, callback)  {    _put('projects/'+id,       {project: params}, callback); },
      delete            : function(id, callback)          { _delete('projects/'+id,       callback); },
      time_entries_for  : function(ids, callback)         {    _get('time_entries',       {project_id: ids}, callback); }
    }

    // http://mite.yo.lk/en/api/services.html
    Service = {
      active            : function(params, callback)      {    _get('services',           params, callback); },
      archived          : function(params, callback)      {    _get('services/archived',  params, callback); },
      find              : function(id, callback)          {    _get('services/'+id,       callback); },
      create            : function(params, callback)      {   _post('services',           {service: params}, callback); },
      update            : function(id, params, callback)  {    _put('services/'+id,       {service: params}, callback); },
      delete            : function(id, callback)          { _delete('services/'+id,       callback); },
      time_entries_for  : function(ids, callback)         {    _get('time_entries',       {service_id: ids}, callback); }
    }

    // http://mite.yo.lk/en/api/users.html
    User = {
      active            : function(params, callback)      {    _get('users',              params, callback); },
      archived          : function(params, callback)      {    _get('users/archived',     params, callback); },
      find              : function(id, callback)          {    _get('users/'+id,          callback); },
      time_entries_for  : function(ids, callback)         {    _get('time_entries',       {user_id: ids}, callback); },

      create            : not_allowed,
      update            : not_allowed,
      delete            : not_allowed
    }

    // Public
    return {
      defaults  : { protocol : 'http'
                  , domain   : 'mite.yo.lk'
                  },
      prepare   : prepare,

      // resources
      account   : account,
      myself    : myself,
      TimeEntry : TimeEntry,
      Tracker   : Tracker,
      Bookmark  : Bookmark,
      Customer  : Customer,
      Project   : Project,
      Service   : Service,
      User      : User
    };
  }());
}(jQuery));<|endoftext|>


<commit_before><commit_msg>performance details<commit_after><|endoftext|>