<commit_before>;(function (define) {
    'use strict';
    define([
            'jquery',
            'underscore',
            'js/student_account/views/FormView'
        ],
        function($, _, FormView) {

        return FormView.extend({
            el: '#register-form',

            tpl: '#register-tpl',

            events: {
                'click .js-register': 'submitForm',
                'click .login-provider': 'thirdPartyAuth'
            },

            formType: 'register',

            submitButton: '.js-register',

            preRender: function( data ) {
                this.providers = data.thirdPartyAuth.providers || [];
                this.hasSecondaryProviders = (
                    data.thirdPartyAuth.secondaryProviders && data.thirdPartyAuth.secondaryProviders.length
                );
                this.currentProvider = data.thirdPartyAuth.currentProvider || '';
                this.errorMessage = data.thirdPartyAuth.errorMessage || '';
                this.platformName = data.platformName;
                this.autoSubmit = data.thirdPartyAuth.autoSubmitRegForm;

                this.listenTo( this.model, 'sync', this.saveSuccess );
            },

            render: function( html ) {
                var fields = html || '';

                $(this.el).html(_.template(this.tpl)({
                    /* We pass the context object to the template so that
                     * we can perform variable interpolation using sprintf
                     */
                    context: {
                        fields: fields,
                        currentProvider: this.currentProvider,
                        errorMessage: this.errorMessage,
                        providers: this.providers,
                        hasSecondaryProviders: this.hasSecondaryProviders,
                        platformName: this.platformName
                    }
                }));

                this.postRender();

                if (this.autoSubmit) {
                    $(this.el).hide();
                    $('#register-honor_code').prop('checked', true);
                    this.submitForm();
                }

                return this;
            },

            thirdPartyAuth: function( event ) {
                var providerUrl = $(event.currentTarget).data('provider-url') || '';

                if ( providerUrl ) {
                    window.location.href = providerUrl;
                }
            },

            saveSuccess: function() {
                this.trigger('auth-complete');
            },

            saveError: function( error ) {
                $(this.el).show(); // Show in case the form was hidden for auto-submission
                this.errors = _.flatten(
                    _.map(
                        // Something is passing this 'undefined'. Protect against this.
                        JSON.parse(error.responseText || "[]"),
                        function(error_list) {
                            return _.map(
                                error_list,
                                function(error) { return '
' + error.user_message + '
'; }
                            );
                        }
                    )
                );
                this.setErrors();
                this.toggleDisableButton(false);
            },

            postFormSubmission: function() {
                if (_.compact(this.errors).length) {
                    // The form did not get submitted due to validation errors.
                    $(this.el).show(); // Show in case the form was hidden for auto-submission
                }
            }
        });
    });
}).call(this, define || RequireJS.define);
<commit_msg>testing ga registerview<commit_after>;(function (define) {
    'use strict';
    define([
            'jquery',
            'underscore',
            'js/student_account/views/FormView'
        ],
        function($, _, FormView) {

        return FormView.extend({
            el: '#register-form',

            tpl: '#register-tpl',

            events: {
                'click .js-register': 'submitForm',
                'click .login-provider': 'thirdPartyAuth'
            },

            formType: 'register',

            submitButton: '.js-register',

            preRender: function( data ) {
                this.providers = data.thirdPartyAuth.providers || [];
                this.hasSecondaryProviders = (
                    data.thirdPartyAuth.secondaryProviders && data.thirdPartyAuth.secondaryProviders.length
                );
                this.currentProvider = data.thirdPartyAuth.currentProvider || '';
                this.errorMessage = data.thirdPartyAuth.errorMessage || '';
                this.platformName = data.platformName;
                this.autoSubmit = data.thirdPartyAuth.autoSubmitRegForm;

                this.listenTo( this.model, 'sync', this.saveSuccess );
            },

            render: function( html ) {
                var fields = html || '';

                $(this.el).html(_.template(this.tpl)({
                    /* We pass the context object to the template so that
                     * we can perform variable interpolation using sprintf
                     */
                    context: {
                        fields: fields,
                        currentProvider: this.currentProvider,
                        errorMessage: this.errorMessage,
                        providers: this.providers,
                        hasSecondaryProviders: this.hasSecondaryProviders,
                        platformName: this.platformName
                    }
                }));

                this.postRender();

                if (this.autoSubmit) {
                    $(this.el).hide();
                    $('#register-honor_code').prop('checked', true);
                    this.submitForm();
                }

                return this;
            },

            thirdPartyAuth: function( event ) {
                var providerUrl = $(event.currentTarget).data('provider-url') || '';

                if ( providerUrl ) {
                    window.location.href = providerUrl;
                }
            },

            saveSuccess: function() {
                ga('send', 'event', 'Registration form', 'Click', 'Registration attempt');
                this.trigger('auth-complete');
            },

            saveError: function( error ) {
                $(this.el).show(); // Show in case the form was hidden for auto-submission
                this.errors = _.flatten(
                    _.map(
                        // Something is passing this 'undefined'. Protect against this.
                        JSON.parse(error.responseText || "[]"),
                        function(error_list) {
                            return _.map(
                                error_list,
                                function(error) { return '
' + error.user_message + '
'; }
                            );
                        }
                    )
                );
                this.setErrors();
                this.toggleDisableButton(false);
            },

            postFormSubmission: function() {
                if (_.compact(this.errors).length) {
                    // The form did not get submitted due to validation errors.
                    $(this.el).show(); // Show in case the form was hidden for auto-submission
                }
            }
        });
    });
}).call(this, define || RequireJS.define);
<|endoftext|>


<commit_before>var getRandomInt = function(min, max) {
  return Math.floor(Math.random() * (max - min + 1)) + min;
}

module.exports = {

	get: function(basepath, content_type, request_options, callback) {
		var self = this;
		var response_options = { "header": {} };

		if (basepath === "/index") {
			response_options.header["Set-Cookie"] = "bg=" + getRandomInt(0, 1);
			return callback(null, { "index": true }, {}, response_options);
		} else {
			return callback(null, { "index": false }, {}, response_options);
		}
	}

}
<commit_msg>Updated the helper to use the newer API<commit_after>var getRandomInt = function(min, max) {
  return Math.floor(Math.random() * (max - min + 1)) + min;
}

module.exports = {

	get: function(basepath, content_type, request_options, callback) {
		var self = this;
		var response_options = { "header": {} };

		if (basepath === "/index") {
			response_options.header["Set-Cookie"] = "bg=" + getRandomInt(0, 1);
			return callback(null, { "tag": { "index": true } }, response_options, new Date());
		} else {
			return callback(null, { "tag": {  "index": false } }, {}, response_options, new Date());
		}
	}

}
<|endoftext|>


<commit_before>/**
 * public script for all pages
 *
 *  -- namespaces --
 *  $ : jQuery
 *  l : message resource
 *  Hbs : handlebars
 *
 */
(function ($, l, hbs, window) {
    hbs.registerHelper('l', function (name) {
        return name && eval(["window", "l"].concat(name).join('.'));
    });
    hbs.registerHelper('t', function () {
        return new Date().getTime();
    });
    hbs.registerHelper('ctx', function () {
        var ctx = window['ctx'];
        return ctx ? '/' + ctx : '';
    });

    $.confirmRemove = (function (confirmRemove) {
        return function () {
            return confirmRemove.apply(this, arguments);
        };
    })($.confirmRemove);
    $.extend({
        errAlert: function (text) {
            $('#err-alert').text(text).show();
        }
    });
    $.fn.extend({
        /**
         * list with appendable items
         * @param tmpl
         * @param addBtn
         * @param callback
         * @returns {*|HTMLElement}
         */
        appendableList: function (tmpl, addBtn, callback) {
            var ul = $(this);
            addBtn.click(function () {
                var li = ul.appendHandlebars(tmpl, {})
                    .find('li')
                    .last();
                callback && callback(li);
            });
            return ul;
        },
        /**
         * list item which is editable
         * @returns {*}
         */
        editableListItem: function (trigger) {
            return this.each(function () {
                var li = $(this),
                    detailLink = li.find('.detail-link');
                var editableTxt = li.findByRole('editable-text')
                    .editableText(trigger)
                    .change(function () {
                        $(this).submit();
                    })
                    .first()
                    .focus();
                li.findByName('edit-form')
                    .ajaxForm(function (data) {
                        var form = $(this);
                        if (data.valid) {
                            form.setFormValue(data.model);
                            form.trigger('edit-done');
                            li.addClass('editable-list-item-fixed');
                            detailLink.show();
                        } else {
                            var errors = data['errors'];
                            if (errors && errors.length) {
                                alert(errors[0]); //TODO
                            }
                        }
                    });
                li.findByRole('edit-btn').off('click').click(function (e) {
                    detailLink.hide();
                    var onEdit = editableTxt.filter(':visible');
                    if (onEdit.length) {
                        //noinspection JSCheckFunctionSignatures
                        editableTxt.trigger('tk-editable-text-fix');
                        li.addClass('editable-list-item-fixed');
                    } else {
                        //noinspection JSCheckFunctionSignatures
                        editableTxt.trigger('tk-editable-text-edit');
                        li.removeClass('editable-list-item-fixed');
                    }
                    e.stopPropagation();
                });
            });
        },
        destroyableListItem: function (showDialog) {
            return this.each(function () {
                var li = $(this);
                li.findByName('destroy-form')
                    .ajaxForm(function () {
                        li.closeDown();
                    })
                    .findByRole('submit-btn')
                    .click(function () {
                        var btn = $(this);
                        if (showDialog) {
                            var name = li.findByName('name').val();
                            $.confirmRemove(name, function () {
                                btn.submit();
                            });
                        } else {
                            var sure = confirm(l.alt.sure);
                            if (sure) btn.submit();
                        }
                    });
            });
        },
        /**
         * form for searching
         * @param callback
         * @returns {*|HTMLElement}
         */
        searchForm: function (callback) {
            var form = $(this);
            form.ajaxForm(function (data) {
                callback && callback(data);
            });
            form.find('input[type="search"]').textchange(function () {
                form.submit();
            });
            $(':submit', form).hide();
            return form;
        },

        /**
         * form with validation
         * @param schema
         * @returns {*|HTMLElement}
         */
        validationForm: function (schema) {
            var form = $(this);
            if (!form.data('validation-form')) {
                form.data('validation-form', true);
                form.submit(function (e) {
                    var schema = form.data('schema');
                    if (!schema) return;
                    form.find('.err-input').removeClass('err');
                    var values = form.getFormValue().toObj();
                    var result = schema.validate(values);
                    if (!result.valid) {
                        e.preventDefault();
                        e.stopImmediatePropagation();
                        form.errForm(result.errors);
                    }
                });
            }
            form.data('schema', schema);
            return form;
        },
        validatableAjaxForm: function (callback) {
            var form = $(this);
            return form.ajaxForm(function (data) {
                var errors = data.errors || [];
                form.errForm(errors);
                var valid = !errors.length;
                callback.call(form, data, valid);
            })
        },
        errForm: function (err) {
            var form = $(this);
            if (!err) return form;
            var tmpl = hbs.templates['input-err-msg'];
            form.find('.err-input').removeClass('err-input');
            form.find('.input-err-msg').remove();
            var joiner = ' '; //TODO when japanese, joiner should be empty
            err.forEach(function (err) {
                var input = form.findByName(err.property).addClass('err-input');
                var label = err.label || err.property,
                    msg = [
                        label,
                        err.message
                    ].join(joiner);
                input.parent()
                    .find('.input-err-msg').remove();
                input.before(tmpl(msg));
            });
            form.find('.err-input').first().focus();
            return form;
        },
        editableForm: function (mode) {
            var form = $(this);
            var editableText = form.findByRole('editable-text')
                .editableText('dblclick')
                .off('change');

            form.find('.checkable-label').each(function () {
                var label = $(this),
                    checkable = label.find(':checkbox,:radio');
                checkable.change(function () {
                    var checked = checkable.is(':checked');
                    label.addClass('checked')
                        .siblings('.checked')
                        .removeClass('checked');
                });
                var checked = checkable.is(':checked');
                if (checked) label.addClass('checked');
            });
            var $checkable = $('.checkable-label', form);
            switch (mode) {
                case 'view':
                    $checkable.each(function () {
                        var label = $(this),
                            input = $('#' + label.attr('for'));
                        if (!input.size()) return;
                        var checked = input.is(':checked');
                        if (checked) {
                            label.show();
                        } else {
                            label.hide();
                        }
                    });
                    editableText.trigger('tk-editable-text-fix');
                    $(':text,textarea,[type="number"],[type="email"]', form).filter(':visible').hide();
                    break;
                case 'edit':
                    $checkable.show();
                    editableText.trigger('tk-editable-text-edit');
                    break;
            }

            form.attr('data-mode', mode);
        },
        detailForm: function (mode, saveBtn, editBtn, callback) {
            var form = $(this).addClass('editable-form');

            form.validatableAjaxForm(function (data, valid) {
                if (!valid) return;
                editBtn.show();
                saveBtn.hide();
                form.editableForm('view');
                form.setFormValue(data.model);
                $.confirmLeave(false);
                callback && callback(data);
            });
            editBtn.click(function () {
                form.editableForm('edit');
                editBtn.hide();
                saveBtn.show();
            });

            form.find(':text,[type="number"]')
                .keydown(function (e) {
                    switch (e.which) {
                        case $.ui.keyCode.ENTER:
                            e.preventDefault();
                            break;
                    }
                });
            form.editableForm(mode || 'view');

            form
                .change(function () {
                    $.confirmLeave(l.msg.leave_with_unsaved);
                });

            switch (mode) {
                case 'edit':
                    editBtn.hide();
                    break;
                default:
                    saveBtn.hide();
                    break;
            }

            return form;
        },
        dropdownBtn: function () {
            return $(this).each(function () {
                var btn = $(this),
                    ul = $('#' + btn.attr('for'));
                btn.click(function () {
                    ul.show();
                });
            });
        },
        headNav: function () {
            var nav = $(this);
            nav.findByRole('dropdown-btn').dropdownBtn();
            return nav;
        },
        book: function () {
            var book = $(this),
                leftPage = $('#left-page', book),
                rightPage = $('#right-page', book);
            var both = leftPage.is(':visible') && rightPage.is(':visible');
            if (both) {
                book.on('resize-book',function () {
                    var h1 = leftPage.height('auto').height(),
                        h2 = rightPage.height('auto').height();
                    var h = h1 && h2 && (h1 > h2 ? h1 : h2);
                    if (h) {
                        leftPage.height(h);
                        rightPage.height(h);
                    }
                }).trigger('resize-book');
            }
            return book;
        },
        subNav: function (key) {
            var nav = $(this);
            nav.findByAttr('data-key', key).addClass('active');
            return nav;
        },
        slideshowContainer: function (callback) {
            var container = $(this),
                slide = container.children().addClass('slideshow-slide');

            slide.each(function () {
                var slide = $(this);
                slide.findByRole('slideshow-link').click(function (e) {
                    e.preventDefault();
                    var link = $(this),
                        current = link.parents('.slideshow-slide');

                    var href = link.attr('href');
                    location.href = href;

                    var next = $(href).removeAttr('style').show();
                    var hMove = current.width() + 80;

                    if (link.data('reverse')) hMove *= -1;
                    var top = current.offset().top;
                    current.css({
                        left: hMove * -1,
                        width: current.width(),
                        position: 'absolute'
                    });
                    container
                        .css({
                            position: 'relative',
                            left: hMove
                        });
                    var vMove = current.offset().top - top;
                    current.css({top: vMove * -1});
                    callback && callback();
                    container
                        .animate({
                            left: 0
                        }, function () {
                            current
                                .add(container)
                                .add(next)
                                .removeAttr('style');
                            current.hide();
                            callback && callback();
                        })
                });
            }).hide();

            var first = slide.filter(location.hash);
            if (!first.length) first = slide.first();
            first.show();

            return container;
        },
        slideinMenu: function () {
            var menu = $(this),
                inner = $('.slidein-menu-inner', menu),
                btn = $('.slidein-menu-btn', menu),
                content = $('.slidein-menu-content', menu);

            function slide(from, to, duration) {
                inner
                    .css({
                        left: from
                    })
                    .animate({
                        left: to
                    }, duration);
            }

            menu.open = function (duration) {
                slide(content.width(), 0, duration);
                menu.addClass('opened');
            };
            menu.close = function (duration) {
                slide(0, content.width(), duration);
                menu.removeClass('opened');
            };
            btn.click(function () {
                var duration = 300;
                if (menu.hasClass('opened')) {
                    menu.close(duration);
                } else {
                    menu.open(duration);
                }
            });
            menu.close(0);
            return menu;
        },
        mainNav: function () {
            return $(this).slideinMenu();
        },
        tab: function (callback) {
            return $(this).click(function (e) {
                var clicked = $(this);
                clicked.addClass('tab-active')
                    .siblings('.tab-active')
                    .removeClass('tab-active');
                callback && callback.apply(this, e);
            });
        }
    });
    $(function () {

        var body = $(document.body);

        $(document)
            .ajaxError(function (e, req, setting, err) {
                if (req.status) {
                    var statusCode = req.statusCode();
                    console.error('[ajax err]', statusCode, err);
                    $.errAlert(l.err.something_worng);
                }
            })
            .ajaxComplete(function (e, xhr, settings) {
                var json = xhr['responseJSON'];
                var error_alert = json && json['error_alert'];
                if (error_alert) {
                    $.errAlert(error_alert);
                }
            });

        $('#main-nav', body).mainNav();

        $('.alert-close-btn', body).click(function () {
            var alertDiv = $(this).parent('.alert');
            alertDiv.closeDown(function () {
                alertDiv.remove();
            });
        });

        var book = $('#book').book();

        $(window).resize(function () {
            book.trigger('resize-book');
        });
    });
})(jQuery, window['l'], Handlebars, window);

<commit_msg>add browswer uppoert<commit_after>/**
 * public script for all pages
 *
 *  -- namespaces --
 *  $ : jQuery
 *  l : message resource
 *  Hbs : handlebars
 *
 */
(function ($, l, hbs, window) {
    hbs.registerHelper('l', function (name) {
        return name && eval(["window", "l"].concat(name).join('.'));
    });
    hbs.registerHelper('t', function () {
        return new Date().getTime();
    });
    hbs.registerHelper('ctx', function () {
        var ctx = window['ctx'];
        return ctx ? '/' + ctx : '';
    });

    var supported = (function (detected) {
        if (!detected) return true;
        switch (detected.browser) {
            case 'IE':
                return 9.0 <= detected.version;
        }
        return true;
    })(tek.detectBrowser(window));

    if (!supported) {
        $(function () {
            $.sorryNoSupport();
        });
    }

    $.confirmRemove = (function (confirmRemove) {
        return function () {
            return confirmRemove.apply(this, arguments);
        };
    })($.confirmRemove);
    $.extend({
        errAlert: function (text) {
            $('#err-alert').text(text).show();
        }
    });
    $.fn.extend({
        /**
         * list with appendable items
         * @param tmpl
         * @param addBtn
         * @param callback
         * @returns {*|HTMLElement}
         */
        appendableList: function (tmpl, addBtn, callback) {
            var ul = $(this);
            addBtn.click(function () {
                var li = ul.appendHandlebars(tmpl, {})
                    .find('li')
                    .last();
                callback && callback(li);
            });
            return ul;
        },
        /**
         * list item which is editable
         * @returns {*}
         */
        editableListItem: function (trigger) {
            return this.each(function () {
                var li = $(this),
                    detailLink = li.find('.detail-link');
                var editableTxt = li.findByRole('editable-text')
                    .editableText(trigger)
                    .change(function () {
                        $(this).submit();
                    })
                    .first()
                    .focus();
                li.findByName('edit-form')
                    .ajaxForm(function (data) {
                        var form = $(this);
                        if (data.valid) {
                            form.setFormValue(data.model);
                            form.trigger('edit-done');
                            li.addClass('editable-list-item-fixed');
                            detailLink.show();
                        } else {
                            var errors = data['errors'];
                            if (errors && errors.length) {
                                alert(errors[0]); //TODO
                            }
                        }
                    });
                li.findByRole('edit-btn').off('click').click(function (e) {
                    detailLink.hide();
                    var onEdit = editableTxt.filter(':visible');
                    if (onEdit.length) {
                        //noinspection JSCheckFunctionSignatures
                        editableTxt.trigger('tk-editable-text-fix');
                        li.addClass('editable-list-item-fixed');
                    } else {
                        //noinspection JSCheckFunctionSignatures
                        editableTxt.trigger('tk-editable-text-edit');
                        li.removeClass('editable-list-item-fixed');
                    }
                    e.stopPropagation();
                });
            });
        },
        destroyableListItem: function (showDialog) {
            return this.each(function () {
                var li = $(this);
                li.findByName('destroy-form')
                    .ajaxForm(function () {
                        li.closeDown();
                    })
                    .findByRole('submit-btn')
                    .click(function () {
                        var btn = $(this);
                        if (showDialog) {
                            var name = li.findByName('name').val();
                            $.confirmRemove(name, function () {
                                btn.submit();
                            });
                        } else {
                            var sure = confirm(l.alt.sure);
                            if (sure) btn.submit();
                        }
                    });
            });
        },
        /**
         * form for searching
         * @param callback
         * @returns {*|HTMLElement}
         */
        searchForm: function (callback) {
            var form = $(this);
            form.ajaxForm(function (data) {
                callback && callback(data);
            });
            form.find('input[type="search"]').textchange(function () {
                form.submit();
            });
            $(':submit', form).hide();
            return form;
        },

        /**
         * form with validation
         * @param schema
         * @returns {*|HTMLElement}
         */
        validationForm: function (schema) {
            var form = $(this);
            if (!form.data('validation-form')) {
                form.data('validation-form', true);
                form.submit(function (e) {
                    var schema = form.data('schema');
                    if (!schema) return;
                    form.find('.err-input').removeClass('err');
                    var values = form.getFormValue().toObj();
                    var result = schema.validate(values);
                    if (!result.valid) {
                        e.preventDefault();
                        e.stopImmediatePropagation();
                        form.errForm(result.errors);
                    }
                });
            }
            form.data('schema', schema);
            return form;
        },
        validatableAjaxForm: function (callback) {
            var form = $(this);
            return form.ajaxForm(function (data) {
                var errors = data.errors || [];
                form.errForm(errors);
                var valid = !errors.length;
                callback.call(form, data, valid);
            })
        },
        errForm: function (err) {
            var form = $(this);
            if (!err) return form;
            var tmpl = hbs.templates['input-err-msg'];
            form.find('.err-input').removeClass('err-input');
            form.find('.input-err-msg').remove();
            var joiner = ' '; //TODO when japanese, joiner should be empty
            err.forEach(function (err) {
                var input = form.findByName(err.property).addClass('err-input');
                var label = err.label || err.property,
                    msg = [
                        label,
                        err.message
                    ].join(joiner);
                input.parent()
                    .find('.input-err-msg').remove();
                input.before(tmpl(msg));
            });
            form.find('.err-input').first().focus();
            return form;
        },
        editableForm: function (mode) {
            var form = $(this);
            var editableText = form.findByRole('editable-text')
                .editableText('dblclick')
                .off('change');

            form.find('.checkable-label').each(function () {
                var label = $(this),
                    checkable = label.find(':checkbox,:radio');
                checkable.change(function () {
                    var checked = checkable.is(':checked');
                    label.addClass('checked')
                        .siblings('.checked')
                        .removeClass('checked');
                });
                var checked = checkable.is(':checked');
                if (checked) label.addClass('checked');
            });
            var $checkable = $('.checkable-label', form);
            switch (mode) {
                case 'view':
                    $checkable.each(function () {
                        var label = $(this),
                            input = $('#' + label.attr('for'));
                        if (!input.size()) return;
                        var checked = input.is(':checked');
                        if (checked) {
                            label.show();
                        } else {
                            label.hide();
                        }
                    });
                    editableText.trigger('tk-editable-text-fix');
                    $(':text,textarea,[type="number"],[type="email"]', form).filter(':visible').hide();
                    break;
                case 'edit':
                    $checkable.show();
                    editableText.trigger('tk-editable-text-edit');
                    break;
            }

            form.attr('data-mode', mode);
        },
        detailForm: function (mode, saveBtn, editBtn, callback) {
            var form = $(this).addClass('editable-form');

            form.validatableAjaxForm(function (data, valid) {
                if (!valid) return;
                editBtn.show();
                saveBtn.hide();
                form.editableForm('view');
                form.setFormValue(data.model);
                $.confirmLeave(false);
                callback && callback(data);
            });
            editBtn.click(function () {
                form.editableForm('edit');
                editBtn.hide();
                saveBtn.show();
            });

            form.find(':text,[type="number"]')
                .keydown(function (e) {
                    switch (e.which) {
                        case $.ui.keyCode.ENTER:
                            e.preventDefault();
                            break;
                    }
                });
            form.editableForm(mode || 'view');

            form
                .change(function () {
                    $.confirmLeave(l.msg.leave_with_unsaved);
                });

            switch (mode) {
                case 'edit':
                    editBtn.hide();
                    break;
                default:
                    saveBtn.hide();
                    break;
            }

            return form;
        },
        dropdownBtn: function () {
            return $(this).each(function () {
                var btn = $(this),
                    ul = $('#' + btn.attr('for'));
                btn.click(function () {
                    ul.show();
                });
            });
        },
        headNav: function () {
            var nav = $(this);
            nav.findByRole('dropdown-btn').dropdownBtn();
            return nav;
        },
        book: function () {
            var book = $(this),
                leftPage = $('#left-page', book),
                rightPage = $('#right-page', book);
            var both = leftPage.is(':visible') && rightPage.is(':visible');
            if (both) {
                book.on('resize-book',function () {
                    var h1 = leftPage.height('auto').height(),
                        h2 = rightPage.height('auto').height();
                    var h = h1 && h2 && (h1 > h2 ? h1 : h2);
                    if (h) {
                        leftPage.height(h);
                        rightPage.height(h);
                    }
                }).trigger('resize-book');
            }
            return book;
        },
        subNav: function (key) {
            var nav = $(this);
            nav.findByAttr('data-key', key).addClass('active');
            return nav;
        },
        slideshowContainer: function (callback) {
            var container = $(this),
                slide = container.children().addClass('slideshow-slide');

            slide.each(function () {
                var slide = $(this);
                slide.findByRole('slideshow-link').click(function (e) {
                    e.preventDefault();
                    var link = $(this),
                        current = link.parents('.slideshow-slide');

                    var href = link.attr('href');
                    location.href = href;

                    var next = $(href).removeAttr('style').show();
                    var hMove = current.width() + 80;

                    if (link.data('reverse')) hMove *= -1;
                    var top = current.offset().top;
                    current.css({
                        left: hMove * -1,
                        width: current.width(),
                        position: 'absolute'
                    });
                    container
                        .css({
                            position: 'relative',
                            left: hMove
                        });
                    var vMove = current.offset().top - top;
                    current.css({top: vMove * -1});
                    callback && callback();
                    container
                        .animate({
                            left: 0
                        }, function () {
                            current
                                .add(container)
                                .add(next)
                                .removeAttr('style');
                            current.hide();
                            callback && callback();
                        })
                });
            }).hide();

            var first = slide.filter(location.hash);
            if (!first.length) first = slide.first();
            first.show();

            return container;
        },
        slideinMenu: function () {
            var menu = $(this),
                inner = $('.slidein-menu-inner', menu),
                btn = $('.slidein-menu-btn', menu),
                content = $('.slidein-menu-content', menu);

            function slide(from, to, duration) {
                inner
                    .css({
                        left: from
                    })
                    .animate({
                        left: to
                    }, duration);
            }

            menu.open = function (duration) {
                slide(content.width(), 0, duration);
                menu.addClass('opened');
            };
            menu.close = function (duration) {
                slide(0, content.width(), duration);
                menu.removeClass('opened');
            };
            btn.click(function () {
                var duration = 300;
                if (menu.hasClass('opened')) {
                    menu.close(duration);
                } else {
                    menu.open(duration);
                }
            });
            menu.close(0);
            return menu;
        },
        mainNav: function () {
            return $(this).slideinMenu();
        },
        tab: function (callback) {
            return $(this).click(function (e) {
                var clicked = $(this);
                clicked.addClass('tab-active')
                    .siblings('.tab-active')
                    .removeClass('tab-active');
                callback && callback.apply(this, e);
            });
        }
    });
    $(function () {

        var body = $(document.body);

        $(document)
            .ajaxError(function (e, req, setting, err) {
                if (req.status) {
                    var statusCode = req.statusCode();
                    console.error('[ajax err]', statusCode, err);
                    $.errAlert(l.err.something_worng);
                }
            })
            .ajaxComplete(function (e, xhr, settings) {
                var json = xhr['responseJSON'];
                var error_alert = json && json['error_alert'];
                if (error_alert) {
                    $.errAlert(error_alert);
                }
            });

        $('#main-nav', body).mainNav();

        $('.alert-close-btn', body).click(function () {
            var alertDiv = $(this).parent('.alert');
            alertDiv.closeDown(function () {
                alertDiv.remove();
            });
        });

        var book = $('#book').book();

        $(window).resize(function () {
            book.trigger('resize-book');
        });
    });
})(jQuery, window['l'], Handlebars, window);

<|endoftext|>


<commit_before>/**!
 *
 *  Copyright 2016 Netflix, Inc.
 *
 *     Licensed under the Apache License, Version 2.0 (the "License");
 *     you may not use this file except in compliance with the License.
 *     You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 *     Unless required by applicable law or agreed to in writing, software
 *     distributed under the License is distributed on an "AS IS" BASIS,
 *     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *     See the License for the specific language governing permissions and
 *     limitations under the License.
 *
 */

/*global _*/

 (function () {
     'use strict';

     /**
     * @name ContainerMetadataService
     */
     function ContainerMetadataService($http, $rootScope, $q, $interval, $routeParams, $location, $injector, $log, config, MetricListService) {

        var containerParsedFromQuerystring = false,
            containerNameResolver;

        // loading containerNameResolver if it was defined
        try {
            containerNameResolver = $injector.get('containerNameResolver');
        } catch(e) {
            $log.debug("No external container name resolver defined.");
        }

        /**
        * @name idDictionary
        * @desc
        */
        var idMap = {};
        function idDictionary(key) {
            return idMap[parseId(key)];
        }

        /**
        * @name parseId
        * @desc parses different types of docker ID
        */
        function parseId(id) {
            //handle regular docker
            if (id === null){
                return false;
            }
            if (id.indexOf('docker/') !==-1){
                id = id.split('/')[2];
            //handle systemd
            } else if (id.indexOf('/docker-') !==-1){
                id = id.split('-')[1].split('.')[0];
            }
            return id;
        }

        /**
        * @name clearIdDictionary
        * @desc
        */
        function clearIdDictionary() {
            idMap = {};
        }

        /**
        * @name containerIdExist
        * @desc returns true if id exists in the idMap
        */
        function containerIdExist(id) {
            return (angular.isDefined(idMap[parseId(id)]) && idMap[parseId(id)] !== '');
        }

        /**
        * @name updateMetrics
        * @desc
        */
        function updateMetrics() {
            updateIdDictionary();
            $rootScope.properties.containerList = getContainerList();

            //TODO: find a better way for parsing the container name from the query string just once.
            if (containerParsedFromQuerystring) {
                if($rootScope.properties.containerList.indexOf($routeParams.container) === -1) { // can't find the selected container in the list
                    $rootScope.properties.selectedContainer = '';
                }
            } else {
                if (angular.isDefined($routeParams.container)) {
                    if ($rootScope.properties.containerList.indexOf($routeParams.container) !== -1) {
                        $rootScope.properties.selectedContainer = $routeParams.container;
                        $rootScope.flags.disableContainerSelectNone = true;
                        containerParsedFromQuerystring = true;
                    }
                } else {
                    containerParsedFromQuerystring = true;
                }
            }
        }

        /**;
        * @name initialize
        * @desc
        */
        /*eslint-disable no-unused-vars*/
        var containerCgroups,
            containerNames,
            updateMetricsListener;
        function initialize() {
            containerCgroups = MetricListService.getOrCreateMetric('containers.cgroup');
            containerNames = MetricListService.getOrCreateMetric('containers.name');

            updateMetricsListener = $rootScope.$on('updateMetrics', updateMetrics);
        }
        /*eslint-enable no-unused-vars*/

        /**
        * @name resolveId
        * @desc
        */
        function resolveId(instanceKey) {
            var instanceName = _.find(containerNames.data, function (el) {
                return el.key === instanceKey;
            });
            if(typeof containerNameResolver === 'undefined') {
                if (!config.useCgroupId) {
                    if (instanceName) {
                        return instanceName.values[instanceName.values.length - 1].y;
                    }
                }
                return instanceKey.substring(0,12);
            } else {
                return containerNameResolver.resolve(instanceKey, instanceName);
            }
        }

        /**;
        * @name updateIdDictionary
        * @desc
        */
        function updateIdDictionary(){
            //TODO: implement better logic to add and remove items from idMap. Always creating a new object and resolving all names is expensive.
            idMap = containerCgroups.data.reduce(function(obj, item) {
                obj[item.key] = resolveId(item.key);
                return obj;
            },{});
        }

        /**
        * @name getContainerList
        * @desc
        */
        function getContainerList() {
          return containerCgroups.data.reduce(function(obj, item) {
              obj.push(resolveId(item.key));
              return obj;
          },[]);
        }

        /**
        * @name checkContainerFilter
        * @desc
        */
        function checkContainerFilter(name){
            return ($rootScope.properties.containerFilter === '' || name.indexOf($rootScope.properties.containerFilter) !==-1);
        }

        /**
        * @name checkContainerName
        * @desc
        */
        function checkContainerName(name){
            return ($rootScope.properties.selectedContainer === '' || name.indexOf($rootScope.properties.selectedContainer) !== -1);
        }

        /**
        * @name updateContainer
        * @desc
        */
        function updateContainer(){
            $location.search('container', $rootScope.properties.selectedContainer);
            if ($rootScope.properties.selectedContainer !== '') {
                $rootScope.flags.disableContainerSelectNone = true;
            } else {
                $rootScope.flags.disableContainerSelectNone = false;
            }
        }

        /**
        * @name updateContainerFilter
        * @desc
        */
        function updateContainerFilter() {
            $location.search('containerFilter', $rootScope.properties.containerFilter);
        }

        return {
            idDictionary: idDictionary,
            getContainerList: getContainerList,
            updateIdDictionary: updateIdDictionary,
            clearIdDictionary: clearIdDictionary,
            checkContainerFilter: checkContainerFilter,
            containerIdExist: containerIdExist,
            checkContainerName: checkContainerName,
            updateContainer: updateContainer,
            updateContainerFilter: updateContainerFilter,
            initialize: initialize
        };
    }

    angular
        .module('containermetadata', [
            'metriclist'
        ])
        .factory('ContainerMetadataService', ContainerMetadataService);

 })();
<commit_msg>refactored to only display defined id/instances<commit_after>/**!
 *
 *  Copyright 2016 Netflix, Inc.
 *
 *     Licensed under the Apache License, Version 2.0 (the "License");
 *     you may not use this file except in compliance with the License.
 *     You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 *     Unless required by applicable law or agreed to in writing, software
 *     distributed under the License is distributed on an "AS IS" BASIS,
 *     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *     See the License for the specific language governing permissions and
 *     limitations under the License.
 *
 */

/*global _*/

 (function () {
     'use strict';

     /**
     * @name ContainerMetadataService
     */
     function ContainerMetadataService($http, $rootScope, $q, $interval, $routeParams, $location, $injector, $log, config, MetricListService) {

        var containerParsedFromQuerystring = false,
            containerNameResolver;

        // loading containerNameResolver if it was defined
        try {
            containerNameResolver = $injector.get('containerNameResolver');
        } catch(e) {
            $log.debug("No external container name resolver defined.");
        }

        /**
        * @name idDictionary
        * @desc
        */
        var idMap = {};
        function idDictionary(key) {
            return idMap[parseId(key)];
        }

        /**
        * @name parseId
        * @desc parses different types of docker ID
        */
        function parseId(id) {
            //handle regular docker
            if (id === null){
                return false;
            }
            if (id.indexOf('docker/') !==-1){
                id = id.split('/')[2];
            //handle systemd
            } else if (id.indexOf('/docker-') !==-1){
                id = id.split('-')[1].split('.')[0];
            }
            return id;
        }

        /**
        * @name clearIdDictionary
        * @desc
        */
        function clearIdDictionary() {
            idMap = {};
        }

        /**
        * @name containerIdExist
        * @desc returns true if id exists in the idMap
        */
        function containerIdExist(id) {
            return (angular.isDefined(idMap[parseId(id)]) && idMap[parseId(id)] !== '');
        }

        /**
        * @name updateMetrics
        * @desc
        */
        function updateMetrics() {
            updateIdDictionary();
            $rootScope.properties.containerList = getContainerList();

            //TODO: find a better way for parsing the container name from the query string just once.
            if (containerParsedFromQuerystring) {
                if($rootScope.properties.containerList.indexOf($routeParams.container) === -1) { // can't find the selected container in the list
                    $rootScope.properties.selectedContainer = '';
                }
            } else {
                if (angular.isDefined($routeParams.container)) {
                    if ($rootScope.properties.containerList.indexOf($routeParams.container) !== -1) {
                        $rootScope.properties.selectedContainer = $routeParams.container;
                        $rootScope.flags.disableContainerSelectNone = true;
                        containerParsedFromQuerystring = true;
                    }
                } else {
                    containerParsedFromQuerystring = true;
                }
            }
        }

        /**;
        * @name initialize
        * @desc
        */
        /*eslint-disable no-unused-vars*/
        var containerCgroups,
            containerNames,
            updateMetricsListener;
        function initialize() {
            containerCgroups = MetricListService.getOrCreateMetric('containers.cgroup');
            containerNames = MetricListService.getOrCreateMetric('containers.name');

            updateMetricsListener = $rootScope.$on('updateMetrics', updateMetrics);
        }
        /*eslint-enable no-unused-vars*/

        /**
        * @name resolveId
        * @desc
        */
        function resolveId(instanceKey) {
            var instanceName = _.find(containerNames.data, function (el) {
                return el.key === instanceKey;
            });
            if(typeof containerNameResolver === 'undefined') {
                if (!config.useCgroupId) {
                    if (instanceName) {
                        return instanceName.values[instanceName.values.length - 1].y;
                    }
                }
                return instanceKey.substring(0,12);
            } else {
                return containerNameResolver.resolve(instanceKey, instanceName);
            }
        }

        /**;
        * @name updateIdDictionary
        * @desc
        */
        function updateIdDictionary(){
            //TODO: implement better logic to add and remove items from idMap. Always creating a new object and resolving all names is expensive.
            idMap = containerCgroups.data.reduce(function(obj, item) {
                obj[item.key] = resolveId(item.key);
                return obj;
            },{});
        }

        /**
        * @name getContainerList
        * @desc
        */
        function getContainerList() {
            return containerCgroups.data.reduce(function(obj, item) {
                var resolved = resolveId(item.key);
                if (angular.isDefined(resolved)){
                    obj.push(resolved);
                }
                return obj;
            },[]);
        }

        /**
        * @name checkContainerFilter
        * @desc
        */
        function checkContainerFilter(name){
            return ($rootScope.properties.containerFilter === '' || name.indexOf($rootScope.properties.containerFilter) !==-1);
        }

        /**
        * @name checkContainerName
        * @desc
        */
        function checkContainerName(name){
            return ($rootScope.properties.selectedContainer === '' || name.indexOf($rootScope.properties.selectedContainer) !== -1);
        }

        /**
        * @name updateContainer
        * @desc
        */
        function updateContainer(){
            $location.search('container', $rootScope.properties.selectedContainer);
            if ($rootScope.properties.selectedContainer !== '') {
                $rootScope.flags.disableContainerSelectNone = true;
            } else {
                $rootScope.flags.disableContainerSelectNone = false;
            }
        }

        /**
        * @name updateContainerFilter
        * @desc
        */
        function updateContainerFilter() {
            $location.search('containerFilter', $rootScope.properties.containerFilter);
        }

        return {
            idDictionary: idDictionary,
            getContainerList: getContainerList,
            updateIdDictionary: updateIdDictionary,
            clearIdDictionary: clearIdDictionary,
            checkContainerFilter: checkContainerFilter,
            containerIdExist: containerIdExist,
            checkContainerName: checkContainerName,
            updateContainer: updateContainer,
            updateContainerFilter: updateContainerFilter,
            initialize: initialize
        };
    }

    angular
        .module('containermetadata', [
            'metriclist'
        ])
        .factory('ContainerMetadataService', ContainerMetadataService);

 })();
<|endoftext|>


<commit_before>import { doGetRequest, doPutRequest, doDeleteRequest } from './RestRequests';

export const setProductFavouriteOn = project => doPutRequest(`/favourites/${project}/`, null, 'rest.error.favourite');

export const setProductFavouriteOff = project => doDeleteRequest(`/favourites/${project}/`, 'rest.error.unfavourite');

export const pinABuild = (project, major, minor, servicePack, build) =>
  doPutRequest(`/favourites/pin/${project}/${major}.${minor}.${servicePack}/${build}`, null, 'rest.error.pin');

export const unPinABuild = (project, major, minor, servicePack, build) =>
  doDeleteRequest(`/favourites/pin/${project}/${major}.${minor}.${servicePack}/${build}`, 'rest.error.unpin');

export const getFeatureListByTagData = (product, version, build) =>
  doGetRequest(`/tagview/featureTagIndex/${product}/${version}/${build}`, 'rest.error.featuresByTag');

export const getSimpleFeatureListData = (product, version, build) => doGetRequest(`/reports/featureIndex/${product}/${version}/${build}`);

export const getFeatureReport = id => doGetRequest(`/feature/${id}`);

export const getRollUpData = (product, version, feature) => doGetRequest(`/feature/rollup/${product}/${version}/${feature}`);

// path should be of type StepStatusPatch
export const updateStepPatch = (featureId, patch) => doPutRequest(`/feature/step/${featureId}`, patch);

// path should be of type StepStatusPatch
export const updateAllStepPatch = (featureId, patch) => doPutRequest(`/feature/steps/${featureId}`, patch);

// patch should be of type InputFieldPatch
export const updateComments = (featureId, patch) => doPutRequest(`/feature/comments/${featureId}`, patch);

export const getTagAssignmentData = (product, version, build) => doGetRequest(`/user/tagAssignment/${product}/${version}/${build}`);

// patch should be of type TagAssignment
export const setTagAssignmentData = (restId, patch) => doPutRequest(`/user/tagAssignment/${restId}`, patch);

export const getIgnoredTags = product => doGetRequest(`/user/ignoredTags/${product}`);

export const setIgnoredTag = (product, patch) => doPutRequest(`/user/ignoredTags/${product}`, patch);
<commit_msg>Reintroduced the old legacy rest call methods temporarily while we move out the other methods into services.<commit_after>import { doRequest, Method } from './RestRequests';

const { GET, PUT, DELETE } = Method;
const doGetRequest = (path, errorMessage) => doRequest(GET, path, errorMessage);
const doPutRequest = (path, data, errorMessage) => doRequest(PUT, path, errorMessage, data);
const doDeleteRequest = (path, errorMessage) => doRequest(DELETE, path, errorMessage);

export const setProductFavouriteOn = project => doPutRequest(`/favourites/${project}/`, null, 'rest.error.favourite');

export const setProductFavouriteOff = project => doDeleteRequest(`/favourites/${project}/`, 'rest.error.unfavourite');

export const pinABuild = (project, major, minor, servicePack, build) =>
  doPutRequest(`/favourites/pin/${project}/${major}.${minor}.${servicePack}/${build}`, null, 'rest.error.pin');

export const unPinABuild = (project, major, minor, servicePack, build) =>
  doDeleteRequest(`/favourites/pin/${project}/${major}.${minor}.${servicePack}/${build}`, 'rest.error.unpin');

export const getFeatureListByTagData = (product, version, build) =>
  doGetRequest(`/tagview/featureTagIndex/${product}/${version}/${build}`, 'rest.error.featuresByTag');

export const getSimpleFeatureListData = (product, version, build) => doGetRequest(`/reports/featureIndex/${product}/${version}/${build}`);

export const getFeatureReport = id => doGetRequest(`/feature/${id}`);

export const getRollUpData = (product, version, feature) => doGetRequest(`/feature/rollup/${product}/${version}/${feature}`);

// path should be of type StepStatusPatch
export const updateStepPatch = (featureId, patch) => doPutRequest(`/feature/step/${featureId}`, patch);

// path should be of type StepStatusPatch
export const updateAllStepPatch = (featureId, patch) => doPutRequest(`/feature/steps/${featureId}`, patch);

// patch should be of type InputFieldPatch
export const updateComments = (featureId, patch) => doPutRequest(`/feature/comments/${featureId}`, patch);

export const getTagAssignmentData = (product, version, build) => doGetRequest(`/user/tagAssignment/${product}/${version}/${build}`);

// patch should be of type TagAssignment
export const setTagAssignmentData = (restId, patch) => doPutRequest(`/user/tagAssignment/${restId}`, patch);

export const getIgnoredTags = product => doGetRequest(`/user/ignoredTags/${product}`);

export const setIgnoredTag = (product, patch) => doPutRequest(`/user/ignoredTags/${product}`, patch);
<|endoftext|>


<commit_before>const { Extra, Markup } = require('telegraf');
const axios = require('axios');
const { sendToAdmin, GLOBAL_KEYBOARD } = require('./utils');
const { findUserByIdAndUpdate, findOrCreateUserById } = require('./dbmanager');
const { LASTFM_URL, LASTFM_KEY } = require('../../config');

async function start(ctx, next) {
  const res = await findOrCreateUserById(ctx.from.id);

  if (res.created) {
    await ctx.reply(`Hello, ${ctx.from.first_name}!

This bot allows you to scrobble songs, albums and tracklists in text mode. \
To take advantage of these opportunities you have to grant access to your Last.fm account...`, GLOBAL_KEYBOARD);
    ctx.enterScene('auth');
    return sendToAdmin(ctx, `We've got a new user! @${ctx.from.username}`);
  }

  return next();
}

function help(ctx) {
  ctx.reply(`To scrobble a track you can simply type its info in this format:

Artist\nTrack Name\nAlbum Title

Use the keyboard below for album and tracklist scrobbling.

/auth — grant access or change account
/recent — see recent scrobbled tracks from your account

If you have any ideas or improvements for the bot please tell us about them via /wish command`, GLOBAL_KEYBOARD);
}

async function whoami(ctx) {
  return ctx.reply(`You are logged in as <a href="http://www.last.fm/user/${ctx.user.account}">${ctx.user.account}</a>`,
    Extra.HTML().webPreview(false));
}

async function nextAlbum(ctx, which = 'NEXT') {
  let i = null;
  let id = null;
  const pages = ctx.callbackQuery.message.text.slice(ctx.callbackQuery.message.text.search(/\d?\d of \d\d/)).split(' of ');

  switch (which) {
    case 'NEXT':
      i = +pages[0] + 1 > +pages[1] ? 1 : +pages[0] + 1;
      break;
    case 'PREV':
      i = +pages[0] - 1 < 1 ? +pages[1] : +pages[0] - 1;
      break;
    default:
      return;
  }

  if (ctx.user.discogs_results[i]) {
    id = ctx.user.discogs_results[i].id;
  } else {
    return ctx.answerCallbackQuery('No more results');
  }

  const res = await axios(`https://api.discogs.com/releases/${id}`);

  if (res.data.tracklist.length) {
    const tracks = res.data.tracklist
      .map((track) => {
        const dur = track.duration.split(':');
        return { name: track.title, duration: (dur[0] * 60) + +dur[1] };
      });

    ctx.user = await findUserByIdAndUpdate(ctx.from.id, { 'album.tracks': tracks }, { new: true });
  } else {
    ctx.user = await findUserByIdAndUpdate(ctx.from.id, {
      'album.tracks': ['There are no any tracks in this result'],
    }, { new: true });
  }

  const title = ctx.user.album.title;
  const artist = ctx.user.album.artist;

  return ctx.editMessageText(
    `You are about to scrobble [${title}](${encodeURI(
    `http://www.last.fm/music/${artist}/${title}`)}) by [${artist}](${encodeURI(
    `http://www.last.fm/music/${artist}`)}). The following tracks have been found on Discogs.com and will be scrobbled:

${ctx.user.album.tracks.map(track => track.name).join('\n')}

Results: ${i} of ${ctx.user.discogs_results.length - 1}`,
    Extra.markdown().webPreview(false).markup(Markup.inlineKeyboard([[
      Markup.callbackButton('Edit', 'EDIT'),
      Markup.callbackButton('⬅', 'PREV'),
      Markup.callbackButton('➡', 'NEXT'),
      Markup.callbackButton('Cancel', 'CANCEL'),
    ], [Markup.callbackButton('OK', 'OK')],
    ])));
}

async function searchFromLastfmAndAnswerInlineQuery(ctx, type = 'track') {
  if (!ctx.inlineQuery.query) {
    return ctx.answerInlineQuery([{
      type: 'article',
      title: 'Type your query below...',
      id: ctx.inlineQuery.id,
      input_message_content: {
        message_text: 'Type your query below...',
      },
    }]);
  }

  const query = ctx.inlineQuery.query;
  const res = await axios(encodeURI(
    `${LASTFM_URL}?method=${type}.search&${type}=${query}&api_key=${LASTFM_KEY}&format=json`));
  const results = res.data.results[`${type}matches`][`${type}`];
  const inlineResults = results
    .filter(item => item.name !== '(null)')
    .map((item, i) => {
      const photoUrl = item.image[2]['#text'] || 'http://img2-ak.lst.fm/i/u/174s/c6f59c1e5e7240a4c0d427abd71f3dbb.png';

      return {
        type: 'article',
        id: String(i),
        thumb_url: photoUrl,
        photo_width: 174,
        photo_height: 174,
        title: item.name,
        description: `${item.artist}`,
        input_message_content: {
          message_text: `${item.artist}\n${item.name}`,
        },
      };
    });

  return ctx.answerInlineQuery(inlineResults);
}

async function recentTracks(ctx) {
  const res = await axios(`${LASTFM_URL}?method=user.getrecenttracks&user=${ctx.user.account}&limit=15&api_key=${LASTFM_KEY}&format=json`);
  const tracks = res.data.recenttracks.track
    .filter((track) => {
      if (track['@attr']) {
        return !track['@attr'].nowplaying;
      }

      return true;
    })
    .map(track => ({
      artist: track.artist['#text'],
      name: track.name,
      album: track.album['#text'],
      url: track.url,
    }));

  return ctx.reply(`Here are the very last 15 scrobbled tracks from your account:

${(tracks.map(track => `<a href="${encodeURI(`http://www.last.fm/music/${track.artist}`)}">${track.artist} — \
${track.name}`)
    .join('\n'))}`,
      Extra.HTML().webPreview(false));
}

module.exports = {
  start,
  help,
  whoami,
  nextAlbum,
  searchFromLastfmAndAnswerInlineQuery,
  recentTracks,
};
<commit_msg>Throw an error when unexpected value at nextAlbum action<commit_after>const { Extra, Markup } = require('telegraf');
const axios = require('axios');
const { sendToAdmin, GLOBAL_KEYBOARD } = require('./utils');
const { findUserByIdAndUpdate, findOrCreateUserById } = require('./dbmanager');
const { LASTFM_URL, LASTFM_KEY } = require('../../config');

async function start(ctx, next) {
  const res = await findOrCreateUserById(ctx.from.id);

  if (res.created) {
    await ctx.reply(`Hello, ${ctx.from.first_name}!

This bot allows you to scrobble songs, albums and tracklists in text mode. \
To take advantage of these opportunities you have to grant access to your Last.fm account...`, GLOBAL_KEYBOARD);
    ctx.enterScene('auth');
    return sendToAdmin(ctx, `We've got a new user! @${ctx.from.username}`);
  }

  return next();
}

function help(ctx) {
  ctx.reply(`To scrobble a track you can simply type its info in this format:

Artist\nTrack Name\nAlbum Title

Use the keyboard below for album and tracklist scrobbling.

/auth — grant access or change account
/recent — see recent scrobbled tracks from your account

If you have any ideas or improvements for the bot please tell us about them via /wish command`, GLOBAL_KEYBOARD);
}

async function whoami(ctx) {
  return ctx.reply(`You are logged in as <a href="http://www.last.fm/user/${ctx.user.account}">${ctx.user.account}</a>`,
    Extra.HTML().webPreview(false));
}

async function nextAlbum(ctx, which = 'NEXT') {
  let i = null;
  let id = null;
  const pages = ctx.callbackQuery.message.text.slice(ctx.callbackQuery.message.text.search(/\d?\d of \d\d/)).split(' of ');

  switch (which) {
    case 'NEXT':
      i = +pages[0] + 1 > +pages[1] ? 1 : +pages[0] + 1;
      break;
    case 'PREV':
      i = +pages[0] - 1 < 1 ? +pages[1] : +pages[0] - 1;
      break;
    default:
      throw new Error(`Unexpected value: ${which}`);
  }

  if (ctx.user.discogs_results[i]) {
    id = ctx.user.discogs_results[i].id;
  } else {
    return ctx.answerCallbackQuery('No more results');
  }

  const res = await axios(`https://api.discogs.com/releases/${id}`);

  if (res.data.tracklist.length) {
    const tracks = res.data.tracklist
      .map((track) => {
        const dur = track.duration.split(':');
        return { name: track.title, duration: (dur[0] * 60) + +dur[1] };
      });

    ctx.user = await findUserByIdAndUpdate(ctx.from.id, { 'album.tracks': tracks }, { new: true });
  } else {
    ctx.user = await findUserByIdAndUpdate(ctx.from.id, {
      'album.tracks': ['There are no any tracks in this result'],
    }, { new: true });
  }

  const title = ctx.user.album.title;
  const artist = ctx.user.album.artist;

  return ctx.editMessageText(
    `You are about to scrobble [${title}](${encodeURI(
    `http://www.last.fm/music/${artist}/${title}`)}) by [${artist}](${encodeURI(
    `http://www.last.fm/music/${artist}`)}). The following tracks have been found on Discogs.com and will be scrobbled:

${ctx.user.album.tracks.map(track => track.name).join('\n')}

Results: ${i} of ${ctx.user.discogs_results.length - 1}`,
    Extra.markdown().webPreview(false).markup(Markup.inlineKeyboard([[
      Markup.callbackButton('Edit', 'EDIT'),
      Markup.callbackButton('⬅', 'PREV'),
      Markup.callbackButton('➡', 'NEXT'),
      Markup.callbackButton('Cancel', 'CANCEL'),
    ], [Markup.callbackButton('OK', 'OK')],
    ])));
}

async function searchFromLastfmAndAnswerInlineQuery(ctx, type = 'track') {
  if (!ctx.inlineQuery.query) {
    return ctx.answerInlineQuery([{
      type: 'article',
      title: 'Type your query below...',
      id: ctx.inlineQuery.id,
      input_message_content: {
        message_text: 'Type your query below...',
      },
    }]);
  }

  const query = ctx.inlineQuery.query;
  const res = await axios(encodeURI(
    `${LASTFM_URL}?method=${type}.search&${type}=${query}&api_key=${LASTFM_KEY}&format=json`));
  const results = res.data.results[`${type}matches`][`${type}`];
  const inlineResults = results
    .filter(item => item.name !== '(null)')
    .map((item, i) => {
      const photoUrl = item.image[2]['#text'] || 'http://img2-ak.lst.fm/i/u/174s/c6f59c1e5e7240a4c0d427abd71f3dbb.png';

      return {
        type: 'article',
        id: String(i),
        thumb_url: photoUrl,
        photo_width: 174,
        photo_height: 174,
        title: item.name,
        description: `${item.artist}`,
        input_message_content: {
          message_text: `${item.artist}\n${item.name}`,
        },
      };
    });

  return ctx.answerInlineQuery(inlineResults);
}

async function recentTracks(ctx) {
  const res = await axios(`${LASTFM_URL}?method=user.getrecenttracks&user=${ctx.user.account}&limit=15&api_key=${LASTFM_KEY}&format=json`);
  const tracks = res.data.recenttracks.track
    .filter((track) => {
      if (track['@attr']) {
        return !track['@attr'].nowplaying;
      }

      return true;
    })
    .map(track => ({
      artist: track.artist['#text'],
      name: track.name,
      album: track.album['#text'],
      url: track.url,
    }));

  return ctx.reply(`Here are the very last 15 scrobbled tracks from your account:

${(tracks.map(track => `<a href="${encodeURI(`http://www.last.fm/music/${track.artist}`)}">${track.artist} — \
${track.name}`)
    .join('\n'))}`,
      Extra.HTML().webPreview(false));
}

module.exports = {
  start,
  help,
  whoami,
  nextAlbum,
  searchFromLastfmAndAnswerInlineQuery,
  recentTracks,
};
<|endoftext|>


<commit_before>// Main application initializer. Executed as the most first step of the
// `cli/server.js` and does following:
//
//  - fetches all bin files of all packages
//  - compiles styles client trees for all packages
//  - find and read all viewws
//  - find and prepare all server methods
//  - prepares bundles client js files for all packages containing:
//    - i18n of the package
//    - client methods
//    - server methods wrapers
//    - views
//  - output bundled files into the `public/assets` dir
//  - initialize router

'use strict';

// stdlib
var fs = require('fs');

// 3rd-party
var _       = require('lodash');
var async   = require('async');
var fstools = require('fs-tools');

// internal
var stopwatch     = require('./utils/stopwatch');
var readPkgConfig = require('./bundle/utils/read_pkg_config');

////////////////////////////////////////////////////////////////////////////////

var PROCESSING_QUEUE = [
  './bundle/mincer'
, './bundle/bin'
, './bundle/styles'
, './bundle/i18n'
, './bundle/views'
, './bundle/server'
, './bundle/router'
  // client depends on router, because we are bundling routes into N
, './bundle/client'
, './bundle/bundles'
, './bundle/manifest'
];

////////////////////////////////////////////////////////////////////////////////

function prepareProcessingQueue(sandbox) {
  return _.map(PROCESSING_QUEUE, function (modulePath) {
    var processor = require(modulePath);

    switch (processor.length) {
    case 1: // Sync processor.
      return function syncProcessorWrapper(next) {
        try {
          processor(sandbox);
          next();
        } catch (err) {
          next(err);
        }
      };

    case 2: // Async processor.
      return async.apply(processor, sandbox);

    default:
      throw new Error('Bundle processor function must accept exactly 1 (sync) ' +
                      'or 2 (async) arguments.');
    }
  });
}

module.exports = function (N) {
  var timer = stopwatch();

  N.wire.on('init:bundle', function bundle_all(N, callback) {
    var sandbox = { N: N }, tmpdir;

    N.logger.info('Bundler: started');

    // schedule files cleanup upon normal exit
    process.on('exit', function (code) {
      if (0 !== +code) {
        console.warn('Unclean exit. Bundled files left in \'' + tmpdir + '\'');
        return;
      }

      try {
        N.logger.debug('Removing %s ...', tmpdir);
        fstools.removeSync(tmpdir);
      } catch (err) {
        N.logger.error('Failed to remove %s, %s ', tmpdir, String(err));
      }
    });

    try {
      sandbox.tmpdir = tmpdir = fstools.tmpdir();
      sandbox.config = readPkgConfig(N.runtime.apps);
      fs.mkdirSync(tmpdir);
    } catch (err) {
      callback(err);
      return;
    }

    N.logger.info('Packages configs loaded %s', timer.elapsed);

    async.series(prepareProcessingQueue(sandbox), function (err) {
      if (err) {
        callback(err);
        return;
      }

      N.logger.info('Bundler: finished %s', timer.elapsed);
      callback();
    });
  });
};
<commit_msg>bundler queue is now sync<commit_after>// Main application initializer. Executed as the most first step of the
// `cli/server.js` and does following:
//
//  - fetches all bin files of all packages
//  - compiles styles client trees for all packages
//  - find and read all viewws
//  - find and prepare all server methods
//  - prepares bundles client js files for all packages containing:
//    - i18n of the package
//    - client methods
//    - server methods wrapers
//    - views
//  - output bundled files into the `public/assets` dir
//  - initialize router

'use strict';

// stdlib
var fs = require('fs');

// 3rd-party
//var _       = require('lodash');
//var async   = require('async');
var fstools = require('fs-tools');

// internal
var stopwatch     = require('./utils/stopwatch');
var readPkgConfig = require('./bundle/utils/read_pkg_config');

////////////////////////////////////////////////////////////////////////////////

var PROCESSING_QUEUE = [
  './bundle/mincer'
, './bundle/bin'
, './bundle/styles'
, './bundle/i18n'
, './bundle/views'
, './bundle/server'
, './bundle/router'
  // client depends on router, because we are bundling routes into N
, './bundle/client'
, './bundle/bundles'
, './bundle/manifest'
];

////////////////////////////////////////////////////////////////////////////////

/*function prepareProcessingQueue(sandbox) {
  return _.map(PROCESSING_QUEUE, function (modulePath) {
    var processor = require(modulePath);

    switch (processor.length) {
    case 1: // Sync processor.
      return function syncProcessorWrapper(next) {
        try {
          processor(sandbox);
          next();
        } catch (err) {
          next(err);
        }
      };

    case 2: // Async processor.
      return async.apply(processor, sandbox);

    default:
      throw new Error('Bundle processor function must accept exactly 1 (sync) ' +
                      'or 2 (async) arguments.');
    }
  });
}*/

module.exports = function (N) {
  var timer = stopwatch();

  N.wire.on('init:bundle', function bundle_all(N, callback) {
    var sandbox = { N: N }, tmpdir, err;

    N.logger.info('Bundler: started');

    // schedule files cleanup upon normal exit
    process.on('exit', function (code) {
      if (0 !== +code) {
        console.warn('Unclean exit. Bundled files left in \'' + tmpdir + '\'');
        return;
      }

      try {
        N.logger.debug('Removing %s ...', tmpdir);
        fstools.removeSync(tmpdir);
      } catch (err) {
        N.logger.error('Failed to remove %s, %s ', tmpdir, String(err));
      }
    });

    try {
      sandbox.tmpdir = tmpdir = fstools.tmpdir();
      sandbox.config = readPkgConfig(N.runtime.apps);
      fs.mkdirSync(tmpdir);
    } catch (e) {
      err = e;
    }

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

    N.logger.info('Packages configs loaded %s', timer.elapsed);

    /*async.series(prepareProcessingQueue(sandbox), function (err) {
      if (err) {
        callback(err);
        return;
      }

      N.logger.info('Bundler: finished %s', timer.elapsed);
      callback();
    });*/

    // Sync calls simplify profiling. Old code is commented for
    // rollback possibility, if one of processor become async.
    try {
      PROCESSING_QUEUE.forEach(function(processor) {
        require(processor)(sandbox);
      });
    } catch (e) {
      err = e;
    }

    callback(err);
  });
};
<|endoftext|>


<commit_before>var keyboardNavigation = (function () {
    var getPosition = function ($release) {
        var releasePosition = $release.position().top;
        var navbarHeight = $('.navbar').outerHeight();
        var spacer = 10;
        return Math.floor(releasePosition - navbarHeight - spacer);
    };

    var goToPreviousRelease = function () {
        var $previousRelease = $('.release').filter(function (index) {
            return $(window).scrollTop() > getPosition($(this));
        }).last();

        if ($previousRelease.length) {
            $(window).scrollTop(getPosition($previousRelease));
        } else {
            $(window).scrollTop(0);
        }
    };

    var goToNextRelease = function () {
        var $nextRelease = $('.release').filter(function (index) {
            return $(window).scrollTop() < getPosition($(this));
        }).first();

        if ($nextRelease.length) {
            $(window).scrollTop(getPosition($nextRelease));
        }
    };

    var goToPreviousPage = function () {
        var prev_url = $('#prev').attr('href');
        if (prev_url) {
            window.location = prev_url;
        }
    };

    var goToNextPage = function () {
        var next_url = $('#next').attr('href');
        if (next_url) {
            window.location = next_url;
        }
    };

    return function (event) {
        if (event.ctrlKey || event.altKey || event.metaKey) {
            return;
        }
        if ($('#releases').length) {
            if (event.which === 63) { // ?
                event.preventDefault();
                $('.keyboard-shortcuts.modal').modal();
            } else if (event.which === 72 || event.which === 104) { // H or h
                event.preventDefault();
                goToPreviousPage();
            } else if (event.which === 74 || event.which === 106) { // J or j
                event.preventDefault();
                goToNextRelease();
            } else if (event.which === 75 || event.which === 107) { // K or k
                event.preventDefault();
                goToPreviousRelease();
            } else if (event.which === 76 || event.which === 108) { // L or l
                event.preventDefault();
                goToNextPage();
            }
        }
    };
})();

var mycomicsToggler = (function () {
    var showConfirmation = function ($button) {
        $button.css('opacity', 1);
        $button.find('.action').hide();
        $button.find('.confirmation').show();
        $button.addClass('btn-danger');
    };

    var showSuccess = function ($button) {
        $button.css('opacity', 1);
        $button.find('.action').hide();
        $button.find('.confirmation').hide();
        $button.find('.success').show();
        $button
            .removeClass('btn-danger')
            .addClass('btn-success');
    };

    var isMyComicsPage = function () {
        return (window.location + '').match(/\/my\//);
    };

    return {
        addComic: function (event) {
            event.preventDefault();
            var $button = $(this);
            $button.attr('disabled', 'disabled');
            var $form = $button.parent('form');
            var data = $form.serialize() + '&add_comic=1';
            $.post($form.attr('action'), data, function () {
                showSuccess($button);
            });
        },
        removeComic: function (event) {
            event.preventDefault();
            var $button = $(this);
            if ($button.find('.action:visible').length) {
                showConfirmation($button);
            } else {
                $button.attr('disabled', 'disabled');
                var $form = $button.parent('form');
                var data = $form.serialize() + '&remove_comic=1';
                $.post($form.attr('action'), data, function () {
                    showSuccess($button);
                    if (isMyComicsPage()) {
                        var comic = $button.parents('.release').data('comic');
                        $('.release[data-comic="' + comic + '"]')
                            .slideUp('slow')
                            .children().fadeOut('slow');
                    }
                });
            }
        }
    };
})();

var mycomicsEditor = (function () {
    return {
        edit: function (event) {
            event.preventDefault();
            $('#cloud .edit-view').show();
            $('#cloud .show-view').hide();
        },
        cancel: function (event) {
            $('#cloud .show-view').show();
            $('#cloud .edit-view').hide();
        }
    };
})();

var fullSizeToggler = function (event) {
    event.preventDefault();
    if ($('img', this).css('max-width') !== 'none') {
        $('img', this).css('max-width', 'none');
    } else {
        $('img', this).css('max-width', '100%');
    }
};

var newReleaseCheck = (function () {
    var secondsBeforeFirstCheck = 60;

    var getLastReleaseId = function () {
        return $('.release').first().data('release-id');
    };

    var checkForNewReleases = function () {
        var lastReleaseId = getLastReleaseId();
        if (lastReleaseId) {
            $.get('/my/num-releases-since/' + lastReleaseId + '/')
                .done(onSuccess)
                .fail(onFailure);
        }
    };

    var showNewReleaseNotification = function (numReleases) {
        var $el = $('.new-releases-alert');
        $el.find('.new-release-count').html(numReleases);
        $el.slideDown();
    };

    var onSuccess = function (data) {
        if (data.num_releases > 0) {
            showNewReleaseNotification(data.num_releases);
        }
        if (data.seconds_to_next_check !== null) {
            setTimeout(checkForNewReleases, data.seconds_to_next_check * 1000);
        }
    };

    var onFailure = function () {
        setTimeout(checkForNewReleases, secondsBeforeFirstCheck * 1000);
    };

    var isPageOneOfMyComicsLatest = function () {
        return (window.location + '').match(/\/my\/(page1\/)?$/);
    };

    return function () {
        if (isPageOneOfMyComicsLatest()) {
            setTimeout(checkForNewReleases, secondsBeforeFirstCheck * 1000);
        }
    };
})();

$(function () {
    $(document).keypress(keyboardNavigation);
    $('.mycomics-add').click(mycomicsToggler.addComic);
    $('.mycomics-remove').click(mycomicsToggler.removeComic);
    $('.mycomics-edit').click(mycomicsEditor.edit);
    $('.mycomics-cancel').click(mycomicsEditor.cancel);
    $('.release .image a').click(fullSizeToggler);
    newReleaseCheck();
});
<commit_msg>Make j/k navigation work better when the menu isn't fixed<commit_after>var keyboardNavigation = (function () {
    var getPosition = function ($release) {
        var releasePosition = $release.position().top;
        var navbarHeight = 0;
        if ($('.navbar').css('position') === 'fixed') {
          navbarHeight = $('.navbar').outerHeight();
        }
        var spacer = 10;
        return Math.floor(releasePosition - navbarHeight - spacer);
    };

    var goToPreviousRelease = function () {
        var $previousRelease = $('.release').filter(function (index) {
            return $(window).scrollTop() > getPosition($(this));
        }).last();

        if ($previousRelease.length) {
            $(window).scrollTop(getPosition($previousRelease));
        } else {
            $(window).scrollTop(0);
        }
    };

    var goToNextRelease = function () {
        var $nextRelease = $('.release').filter(function (index) {
            return $(window).scrollTop() < getPosition($(this));
        }).first();

        if ($nextRelease.length) {
            $(window).scrollTop(getPosition($nextRelease));
        }
    };

    var goToPreviousPage = function () {
        var prev_url = $('#prev').attr('href');
        if (prev_url) {
            window.location = prev_url;
        }
    };

    var goToNextPage = function () {
        var next_url = $('#next').attr('href');
        if (next_url) {
            window.location = next_url;
        }
    };

    return function (event) {
        if (event.ctrlKey || event.altKey || event.metaKey) {
            return;
        }
        if ($('#releases').length) {
            if (event.which === 63) { // ?
                event.preventDefault();
                $('.keyboard-shortcuts.modal').modal();
            } else if (event.which === 72 || event.which === 104) { // H or h
                event.preventDefault();
                goToPreviousPage();
            } else if (event.which === 74 || event.which === 106) { // J or j
                event.preventDefault();
                goToNextRelease();
            } else if (event.which === 75 || event.which === 107) { // K or k
                event.preventDefault();
                goToPreviousRelease();
            } else if (event.which === 76 || event.which === 108) { // L or l
                event.preventDefault();
                goToNextPage();
            }
        }
    };
})();

var mycomicsToggler = (function () {
    var showConfirmation = function ($button) {
        $button.css('opacity', 1);
        $button.find('.action').hide();
        $button.find('.confirmation').show();
        $button.addClass('btn-danger');
    };

    var showSuccess = function ($button) {
        $button.css('opacity', 1);
        $button.find('.action').hide();
        $button.find('.confirmation').hide();
        $button.find('.success').show();
        $button
            .removeClass('btn-danger')
            .addClass('btn-success');
    };

    var isMyComicsPage = function () {
        return (window.location + '').match(/\/my\//);
    };

    return {
        addComic: function (event) {
            event.preventDefault();
            var $button = $(this);
            $button.attr('disabled', 'disabled');
            var $form = $button.parent('form');
            var data = $form.serialize() + '&add_comic=1';
            $.post($form.attr('action'), data, function () {
                showSuccess($button);
            });
        },
        removeComic: function (event) {
            event.preventDefault();
            var $button = $(this);
            if ($button.find('.action:visible').length) {
                showConfirmation($button);
            } else {
                $button.attr('disabled', 'disabled');
                var $form = $button.parent('form');
                var data = $form.serialize() + '&remove_comic=1';
                $.post($form.attr('action'), data, function () {
                    showSuccess($button);
                    if (isMyComicsPage()) {
                        var comic = $button.parents('.release').data('comic');
                        $('.release[data-comic="' + comic + '"]')
                            .slideUp('slow')
                            .children().fadeOut('slow');
                    }
                });
            }
        }
    };
})();

var mycomicsEditor = (function () {
    return {
        edit: function (event) {
            event.preventDefault();
            $('#cloud .edit-view').show();
            $('#cloud .show-view').hide();
        },
        cancel: function (event) {
            $('#cloud .show-view').show();
            $('#cloud .edit-view').hide();
        }
    };
})();

var fullSizeToggler = function (event) {
    event.preventDefault();
    if ($('img', this).css('max-width') !== 'none') {
        $('img', this).css('max-width', 'none');
    } else {
        $('img', this).css('max-width', '100%');
    }
};

var newReleaseCheck = (function () {
    var secondsBeforeFirstCheck = 60;

    var getLastReleaseId = function () {
        return $('.release').first().data('release-id');
    };

    var checkForNewReleases = function () {
        var lastReleaseId = getLastReleaseId();
        if (lastReleaseId) {
            $.get('/my/num-releases-since/' + lastReleaseId + '/')
                .done(onSuccess)
                .fail(onFailure);
        }
    };

    var showNewReleaseNotification = function (numReleases) {
        var $el = $('.new-releases-alert');
        $el.find('.new-release-count').html(numReleases);
        $el.slideDown();
    };

    var onSuccess = function (data) {
        if (data.num_releases > 0) {
            showNewReleaseNotification(data.num_releases);
        }
        if (data.seconds_to_next_check !== null) {
            setTimeout(checkForNewReleases, data.seconds_to_next_check * 1000);
        }
    };

    var onFailure = function () {
        setTimeout(checkForNewReleases, secondsBeforeFirstCheck * 1000);
    };

    var isPageOneOfMyComicsLatest = function () {
        return (window.location + '').match(/\/my\/(page1\/)?$/);
    };

    return function () {
        if (isPageOneOfMyComicsLatest()) {
            setTimeout(checkForNewReleases, secondsBeforeFirstCheck * 1000);
        }
    };
})();

$(function () {
    $(document).keypress(keyboardNavigation);
    $('.mycomics-add').click(mycomicsToggler.addComic);
    $('.mycomics-remove').click(mycomicsToggler.removeComic);
    $('.mycomics-edit').click(mycomicsEditor.edit);
    $('.mycomics-cancel').click(mycomicsEditor.cancel);
    $('.release .image a').click(fullSizeToggler);
    newReleaseCheck();
});
<|endoftext|>


<commit_before>module.exports = function(grunt) {

    // Project configuration.
    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),

        copy: {
                main: {
                    expand: true,
                    src: 'app/*.html',
                    dest: 'production/',
                    flatten: true
                }
            },
        sass: {
            dist: {
                options: {
                    style: 'compressed'
                },
                files: {
                    'production/css/style.css': 'app/scss/style.scss'
                }
            }
        },
        watch: {
            options: {
                livereload: true
            },
            html: {
                files: ['app/*.html'],
                tasks: ['copy:main']
            },
            style: {
                files: ['app/scss/*.scss'],
                tasks: ['sass'],
                options: {
                    spawn: false
                }
            }
        }
    });

    // Load the plugins that provides the tasks.
    grunt.loadNpmTasks('grunt-contrib-copy');
    grunt.loadNpmTasks('grunt-contrib-sass');
    grunt.loadNpmTasks('grunt-contrib-watch');

    // Default tasks.
    grunt.registerTask('default', ['copy', 'sass']);
};<commit_msg>Improved gruntfile<commit_after>module.exports = function(grunt) {

    // Project configuration.
    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),

        copy: {
            main: {
                expand: true,
                src: 'app/*.html',
                dest: 'production/',
                flatten: true
            }
        },
        sass: {
            dist: {
                options: {
                    style: 'compressed'
                },
                files: {
                    'production/css/style.css': 'app/scss/style.scss'
                }
            }
        },
        watch: {
            options: {
                livereload: true
            },
            html: {
                files: ['app/*.html'],
                tasks: ['copy:main']
            },
            style: {
                files: ['app/scss/*.scss'],
                tasks: ['sass'],
                options: {
                    spawn: false
                }
            }
        }
    });

    // Load the plugins that provides the tasks.
    grunt.loadNpmTasks('grunt-contrib-copy');
    grunt.loadNpmTasks('grunt-contrib-sass');
    grunt.loadNpmTasks('grunt-contrib-watch');

    // Default tasks.
    grunt.registerTask('default', ['copy', 'sass']);
};<|endoftext|>


<commit_before>'use strict';

import React from "react";
import ReactTooltip from "./react-tooltip.js";

const Test = React.createClass({

  getInitialState() {
    return {
      place: "top",
      type: "dark",
      effect: "float"
    }
  },

  changePlace(place) {
    this.setState({
      place: place
    })
  },

  changeType(type) {
    this.setState({
      type: type
    })
  },

  changeEffect(effect) {
    this.setState({
      effect: effect
    })
  },

  render() {
    let { place, type, effect } = this.state;
    return (

React Tooltip

            ( ◕‿‿◕ )

akjlshfkjahlskjdfhjadsfjasdfhjkahdsjf

            jksadhfklaskjdhfjk

Place

              Top(default)
              Right
              Bottom
              Left

Type

              Dark(default)
              Success
              Warning
              Error
              Info
              Light

Effect

              Float(default)
              Solid

Code

{"( ◕‿‿◕ )"}

{"<ReactTooltip place={"+place+"} type={"+type+"} effect={"+effect+"}/>"}

        <ReactTooltip place={place} type={type} effect={effect}/>

    )
  }
});

React.render(<Test />, document.body);
<commit_msg>Change curly brackets to quotes (single)<commit_after>'use strict';

import React from "react";
import ReactTooltip from "./react-tooltip.js";

const Test = React.createClass({

  getInitialState() {
    return {
      place: "top",
      type: "dark",
      effect: "float"
    }
  },

  changePlace(place) {
    this.setState({
      place: place
    })
  },

  changeType(type) {
    this.setState({
      type: type
    })
  },

  changeEffect(effect) {
    this.setState({
      effect: effect
    })
  },

  render() {
    let { place, type, effect } = this.state;
    return (

React Tooltip

            ( ◕‿‿◕ )

akjlshfkjahlskjdfhjadsfjasdfhjkahdsjf

            jksadhfklaskjdhfjk

Place

              Top(default)
              Right
              Bottom
              Left

Type

              Dark(default)
              Success
              Warning
              Error
              Info
              Light

Effect

              Float(default)
              Solid

Code

{"( ◕‿‿◕ )"}

{"<ReactTooltip place='"+place+"' type='"+type+"' effect='"+effect+"'/>"}

        <ReactTooltip place={place} type={type} effect={effect}/>

    )
  }
});

React.render(<Test />, document.body);
<|endoftext|>