<commit_before>openerp.web_dashboard = function(instance) {
var QWeb = instance.web.qweb,
    _t = instance.web._t;

if (!instance.web_dashboard) {
    /** @namespace */
    instance.web_dashboard = {};
}

instance.web.form.DashBoard = instance.web.form.FormWidget.extend({
    init: function(view, node) {
        this._super(view, node);
        this.form_template = 'DashBoard';
        this.actions_attrs = {};
        this.action_managers = [];
    },
    start: function() {
        var self = this;
        this._super.apply(this, arguments);

        this.$element.find('.oe_dashboard_column').sortable({
            connectWith: '.oe_dashboard_column',
            handle: '.oe_dashboard_action_header',
            scroll: false
        }).disableSelection().bind('sortstop', self.do_save_dashboard);

        // Events
        this.$element.find('.oe_dashboard_link_reset').click(this.on_reset);
        this.$element.find('.oe_dashboard_link_change_layout').click(this.on_change_layout);

        this.$element.delegate('.oe_dashboard_column .oe_dashboard_fold', 'click', this.on_fold_action);
        this.$element.delegate('.oe_dashboard_column .ui-icon-closethick', 'click', this.on_close_action);

        // Init actions
        _.each(this.node.children, function(column, column_index) {
            _.each(column.children, function(action, action_index) {
                delete(action.attrs.width);
                delete(action.attrs.height);
                delete(action.attrs.colspan);
                self.rpc('/web/action/load', {
                    action_id: parseInt(action.attrs.name, 10)
                }, function(result) {
                    self.on_load_action(result, column_index + '_' + action_index, action.attrs);
                });
            });
        });
    },
    on_reset: function() {
        this.rpc('/web/view/undo_custom', {
            view_id: this.view.fields_view.view_id,
            reset: true
        }, this.do_reload);
    },
    on_change_layout: function() {
        var self = this;
        var qdict = {
            current_layout : this.$element.find('.oe_dashboard').attr('data-layout')
        };
        var $dialog = instance.web.dialog($('<div>'), {
                            modal: true,
                            title: _t("Edit Layout"),
                            width: 'auto',
                            height: 'auto'
                        }).html(QWeb.render('DashBoard.layouts', qdict));
        $dialog.find('li').click(function() {
            var layout = $(this).attr('data-layout');
            $dialog.dialog('destroy');
            self.do_change_layout(layout);
        });
    },
    do_change_layout: function(new_layout) {
        var $dashboard = this.$element.find('.oe_dashboard');
        var current_layout = $dashboard.attr('data-layout');
        if (current_layout != new_layout) {
            var clayout = current_layout.split('-').length,
                nlayout = new_layout.split('-').length,
                column_diff = clayout - nlayout;
            if (column_diff > 0) {
                var $last_column = $();
                $dashboard.find('.oe_dashboard_column').each(function(k, v) {
                    if (k >= nlayout) {
                        $(v).find('.oe_dashboard_action').appendTo($last_column);
                    } else {
                        $last_column = $(v);
                    }
                });
            }
            $dashboard.toggleClass('oe_dashboard_layout_' + current_layout + ' oe_dashboard_layout_' + new_layout);
            $dashboard.attr('data-layout', new_layout);
            this.do_save_dashboard();
        }
    },
    on_fold_action: function(e) {
        var $e = $(e.currentTarget),
            $action = $e.parents('.oe_dashboard_action:first'),
            id = parseInt($action.attr('data-id'), 10);
        if ($e.is('.ui-icon-minusthick')) {
            $action.data('action_attrs').fold = '1';
        } else {
            delete($action.data('action_attrs').fold);
        }
        $e.toggleClass('ui-icon-minusthick ui-icon-plusthick');
        $action.find('.oe_dashboard_action_content').toggle();
        this.do_save_dashboard();
    },
    on_close_action: function(e) {
        if (confirm(_t("Are you sure you want to remove this item ?"))) {
            $(e.currentTarget).parents('.oe_dashboard_action:first').remove();
            this.do_save_dashboard();
        }
    },
    do_save_dashboard: function() {
        var self = this;
        var board = {
                form_title : this.view.fields_view.arch.attrs.string,
                style : this.$element.find('.oe_dashboard').attr('data-layout'),
                columns : []
            };
        this.$element.find('.oe_dashboard_column').each(function() {
            var actions = [];
            $(this).find('.oe_dashboard_action').each(function() {
                var action_id = $(this).attr('data-id'),
                    new_attrs = _.clone($(this).data('action_attrs'));
                if (new_attrs.domain) {
                    new_attrs.domain = new_attrs.domain_string;
                    delete(new_attrs.domain_string);
                }
                if (new_attrs.context) {
                    new_attrs.context = new_attrs.context_string;
                    delete(new_attrs.context_string);
                }
                actions.push(new_attrs);
            });
            board.columns.push(actions);
        });
        var arch = QWeb.render('DashBoard.xml', board);
        this.rpc('/web/view/add_custom', {
            view_id: this.view.fields_view.view_id,
            arch: arch
        }, function() {
            self.$element.find('.oe_dashboard_link_reset').show();
        });
    },
    on_load_action: function(result, index, action_attrs) {
        var self = this,
            action = result.result,
            view_mode = action_attrs.view_mode;

        if (action_attrs.context && action_attrs.context['dashboard_merge_domains_contexts'] === false) {
            // TODO: replace this 6.1 workaround by attribute on <action/>
            action.context = action_attrs.context || {};
            action.domain = action_attrs.domain || [];
        } else {
            if (action_attrs.context) {
                action.context = _.extend((action.context || {}), action_attrs.context);
            }
            if (action_attrs.domain) {
                action.domain = action.domain || [];
                action.domain.unshift.apply(action.domain, action_attrs.domain);
            }
        }

        var action_orig = _.extend({ flags : {} }, action);

        if (view_mode && view_mode != action.view_mode) {
            action.views = _.map(view_mode.split(','), function(mode) {
                mode = mode === 'tree' ? 'list' : mode;
                return _(action.views).find(function(view) { return view[1] == mode; })
                    || [false, mode];
            });
        }

        action.flags = {
            search_view : false,
            sidebar : false,
            views_switcher : false,
            action_buttons : false,
            pager: false,
            low_profile: true,
            display_title: false,
            list: {
                selectable: false
            }
        };
        var am = new instance.web.ActionManager(this),
            // FIXME: ideally the dashboard view shall be refactored like kanban.
            $action = $('#' + this.view.element_id + '_action_' + index);
        $action.parent().data('action_attrs', action_attrs);
        this.action_managers.push(am);
        am.appendTo($action);
        am.do_action(action);
        am.do_action = function (action) {
            self.do_action(action);
        };
        if (action_attrs.creatable && action_attrs.creatable !== 'false') {
            var action_id = parseInt(action_attrs.creatable, 10);
            $action.parent().find('button.oe_dashboard_button_create').click(function() {
                if (isNaN(action_id)) {
                    action_orig.flags.default_view = 'form';
                    self.do_action(action_orig);
                } else {
                    self.rpc('/web/action/load', {
                        action_id: action_id
                    }, function(result) {
                        result.result.flags = result.result.flags || {};
                        result.result.flags.default_view = 'form';
                        self.do_action(result.result);
                    });
                }
            });
        }
        if (am.inner_widget) {
            am.inner_widget.on_mode_switch.add(function(mode) {
                var new_views = [];
                _.each(action_orig.views, function(view) {
                    new_views[view[1] === mode ? 'unshift' : 'push'](view);
                });
                if (!new_views.length || new_views[0][1] !== mode) {
                    new_views.unshift([false, mode]);
                }
                action_orig.views = new_views;
                action_orig.res_id = am.inner_widget.dataset.ids[am.inner_widget.dataset.index];
                self.do_action(action_orig);
            });
        }
    },
    renderElement: function() {
        var check = _.detect(this.node.children, function(column, column_index) {
            return _.detect(column.children,function(element){
                return element.tag === "action"? element: false;
            });
        });
        if (!check) {
            return this.no_result();
        }
        // We should start with three columns available
        for (var i = this.node.children.length; i < 3; i++) {
            this.node.children.push({
                tag: 'column',
                attrs: {},
                children: []
            });
        }
        var rendered = QWeb.render(this.form_template, this);
        this.$element.html(rendered);
    },
    no_result: function() {
        if (this.view.options.action.help) {
            this.$element.append(
                $('<div class="oe_view_nocontent">')
                    .append($('<img>', { src: '/web_dashboard/static/src/img/view_todo_arrow.png' }))
                    .append($('<div>').html(this.view.options.action.help || " "))
            );
        }
    },
    do_reload: function() {
        var view_manager = this.view.getParent(),
            action_manager = view_manager.getParent();
        this.view.destroy();
        action_manager.do_action(view_manager.action);
    }
});
instance.web.form.DashBoardLegacy = instance.web.form.DashBoard.extend({
    renderElement: function() {
        if (this.node.tag == 'hpaned') {
            this.node.attrs.style = '2-1';
        } else if (this.node.tag == 'vpaned') {
            this.node.attrs.style = '1';
        }
        this.node.tag = 'board';
        _.each(this.node.children, function(child) {
            if (child.tag.indexOf('child') == 0) {
                child.tag = 'column';
                var actions = [], first_child = child.children[0];
                if (first_child && first_child.tag == 'vpaned') {
                    _.each(first_child.children, function(subchild) {
                        actions.push.apply(actions, subchild.children);
                    });
                    child.children = actions;
                }
            }
        });
        this._super(this);
    }
});

instance.web.form.tags.add('hpaned', 'instance.web.form.DashBoardLegacy');
instance.web.form.tags.add('vpaned', 'instance.web.form.DashBoardLegacy');
instance.web.form.tags.add('board', 'instance.web.form.DashBoard');

/*
 * Widgets
 * This client action designed to be used as a dashboard widget display
 * the html content of a res_widget given as argument
 */
instance.web.client_actions.add( 'board.home.widgets', 'instance.web_dashboard.Widget');
instance.web_dashboard.Widget = instance.web.View.extend(/** @lends instance.web_dashboard.Widgets# */{
    template: 'HomeWidget',
    /**
     * Initializes a "HomeWidget" client widget: handles the display of a given
     * res.widget objects in an OpenERP view (mainly a dashboard).
     *
     * @constructs instance.web_dashboard.Widget
     * @extends instance.web.View
     *
     * @param {Object} parent
     * @param {Object} options
     * @param {Number} options.widget_id
     */
    init: function (parent, options) {
        this._super(parent);
        this.widget_id = options.widget_id;
    },
    start: function () {
        var ds = new instance.web.DataSet(this, 'res.widget');
        return ds.read_ids([this.widget_id], ['title']).then(this.on_widget_loaded);
    },
    on_widget_loaded: function (widgets) {
        var widget = widgets[0];
        var url = _.str.sprintf(
            '/web_dashboard/widgets/content?session_id=%s&widget_id=%d',
            this.session.session_id, widget.id);
        this.$element.html(QWeb.render('HomeWidget.content', {
            widget: widget,
            url: url
        }));
    }
});

};
<commit_msg>[FIX] web_dashboard: allow columns without actions<commit_after>openerp.web_dashboard = function(instance) {
var QWeb = instance.web.qweb,
    _t = instance.web._t;

if (!instance.web_dashboard) {
    /** @namespace */
    instance.web_dashboard = {};
}

instance.web.form.DashBoard = instance.web.form.FormWidget.extend({
    init: function(view, node) {
        this._super(view, node);
        this.form_template = 'DashBoard';
        this.actions_attrs = {};
        this.action_managers = [];
    },
    start: function() {
        var self = this;
        this._super.apply(this, arguments);

        this.$element.find('.oe_dashboard_column').sortable({
            connectWith: '.oe_dashboard_column',
            handle: '.oe_dashboard_action_header',
            scroll: false
        }).disableSelection().bind('sortstop', self.do_save_dashboard);

        // Events
        this.$element.find('.oe_dashboard_link_reset').click(this.on_reset);
        this.$element.find('.oe_dashboard_link_change_layout').click(this.on_change_layout);

        this.$element.delegate('.oe_dashboard_column .oe_dashboard_fold', 'click', this.on_fold_action);
        this.$element.delegate('.oe_dashboard_column .ui-icon-closethick', 'click', this.on_close_action);

        // Init actions
        _.each(this.node.children, function(column, column_index) {
            _.each(column.children, function(action, action_index) {
                delete(action.attrs.width);
                delete(action.attrs.height);
                delete(action.attrs.colspan);
                var action_id = _.str.toNumber(action.attrs.name);
                if (!_.isNaN(action_id)) {
                    self.rpc('/web/action/load', {action_id: action_id}, function(result) {
                        self.on_load_action(result, column_index + '_' + action_index, action.attrs);
                    });
                }
            });
        });
    },
    on_reset: function() {
        this.rpc('/web/view/undo_custom', {
            view_id: this.view.fields_view.view_id,
            reset: true
        }, this.do_reload);
    },
    on_change_layout: function() {
        var self = this;
        var qdict = {
            current_layout : this.$element.find('.oe_dashboard').attr('data-layout')
        };
        var $dialog = instance.web.dialog($('<div>'), {
                            modal: true,
                            title: _t("Edit Layout"),
                            width: 'auto',
                            height: 'auto'
                        }).html(QWeb.render('DashBoard.layouts', qdict));
        $dialog.find('li').click(function() {
            var layout = $(this).attr('data-layout');
            $dialog.dialog('destroy');
            self.do_change_layout(layout);
        });
    },
    do_change_layout: function(new_layout) {
        var $dashboard = this.$element.find('.oe_dashboard');
        var current_layout = $dashboard.attr('data-layout');
        if (current_layout != new_layout) {
            var clayout = current_layout.split('-').length,
                nlayout = new_layout.split('-').length,
                column_diff = clayout - nlayout;
            if (column_diff > 0) {
                var $last_column = $();
                $dashboard.find('.oe_dashboard_column').each(function(k, v) {
                    if (k >= nlayout) {
                        $(v).find('.oe_dashboard_action').appendTo($last_column);
                    } else {
                        $last_column = $(v);
                    }
                });
            }
            $dashboard.toggleClass('oe_dashboard_layout_' + current_layout + ' oe_dashboard_layout_' + new_layout);
            $dashboard.attr('data-layout', new_layout);
            this.do_save_dashboard();
        }
    },
    on_fold_action: function(e) {
        var $e = $(e.currentTarget),
            $action = $e.parents('.oe_dashboard_action:first'),
            id = parseInt($action.attr('data-id'), 10);
        if ($e.is('.ui-icon-minusthick')) {
            $action.data('action_attrs').fold = '1';
        } else {
            delete($action.data('action_attrs').fold);
        }
        $e.toggleClass('ui-icon-minusthick ui-icon-plusthick');
        $action.find('.oe_dashboard_action_content').toggle();
        this.do_save_dashboard();
    },
    on_close_action: function(e) {
        if (confirm(_t("Are you sure you want to remove this item ?"))) {
            $(e.currentTarget).parents('.oe_dashboard_action:first').remove();
            this.do_save_dashboard();
        }
    },
    do_save_dashboard: function() {
        var self = this;
        var board = {
                form_title : this.view.fields_view.arch.attrs.string,
                style : this.$element.find('.oe_dashboard').attr('data-layout'),
                columns : []
            };
        this.$element.find('.oe_dashboard_column').each(function() {
            var actions = [];
            $(this).find('.oe_dashboard_action').each(function() {
                var action_id = $(this).attr('data-id'),
                    new_attrs = _.clone($(this).data('action_attrs'));
                if (new_attrs.domain) {
                    new_attrs.domain = new_attrs.domain_string;
                    delete(new_attrs.domain_string);
                }
                if (new_attrs.context) {
                    new_attrs.context = new_attrs.context_string;
                    delete(new_attrs.context_string);
                }
                actions.push(new_attrs);
            });
            board.columns.push(actions);
        });
        var arch = QWeb.render('DashBoard.xml', board);
        this.rpc('/web/view/add_custom', {
            view_id: this.view.fields_view.view_id,
            arch: arch
        }, function() {
            self.$element.find('.oe_dashboard_link_reset').show();
        });
    },
    on_load_action: function(result, index, action_attrs) {
        var self = this,
            action = result.result,
            view_mode = action_attrs.view_mode;

        if (action_attrs.context && action_attrs.context['dashboard_merge_domains_contexts'] === false) {
            // TODO: replace this 6.1 workaround by attribute on <action/>
            action.context = action_attrs.context || {};
            action.domain = action_attrs.domain || [];
        } else {
            if (action_attrs.context) {
                action.context = _.extend((action.context || {}), action_attrs.context);
            }
            if (action_attrs.domain) {
                action.domain = action.domain || [];
                action.domain.unshift.apply(action.domain, action_attrs.domain);
            }
        }

        var action_orig = _.extend({ flags : {} }, action);

        if (view_mode && view_mode != action.view_mode) {
            action.views = _.map(view_mode.split(','), function(mode) {
                mode = mode === 'tree' ? 'list' : mode;
                return _(action.views).find(function(view) { return view[1] == mode; })
                    || [false, mode];
            });
        }

        action.flags = {
            search_view : false,
            sidebar : false,
            views_switcher : false,
            action_buttons : false,
            pager: false,
            low_profile: true,
            display_title: false,
            list: {
                selectable: false
            }
        };
        var am = new instance.web.ActionManager(this),
            // FIXME: ideally the dashboard view shall be refactored like kanban.
            $action = $('#' + this.view.element_id + '_action_' + index);
        $action.parent().data('action_attrs', action_attrs);
        this.action_managers.push(am);
        am.appendTo($action);
        am.do_action(action);
        am.do_action = function (action) {
            self.do_action(action);
        };
        if (action_attrs.creatable && action_attrs.creatable !== 'false') {
            var action_id = parseInt(action_attrs.creatable, 10);
            $action.parent().find('button.oe_dashboard_button_create').click(function() {
                if (isNaN(action_id)) {
                    action_orig.flags.default_view = 'form';
                    self.do_action(action_orig);
                } else {
                    self.rpc('/web/action/load', {
                        action_id: action_id
                    }, function(result) {
                        result.result.flags = result.result.flags || {};
                        result.result.flags.default_view = 'form';
                        self.do_action(result.result);
                    });
                }
            });
        }
        if (am.inner_widget) {
            am.inner_widget.on_mode_switch.add(function(mode) {
                var new_views = [];
                _.each(action_orig.views, function(view) {
                    new_views[view[1] === mode ? 'unshift' : 'push'](view);
                });
                if (!new_views.length || new_views[0][1] !== mode) {
                    new_views.unshift([false, mode]);
                }
                action_orig.views = new_views;
                action_orig.res_id = am.inner_widget.dataset.ids[am.inner_widget.dataset.index];
                self.do_action(action_orig);
            });
        }
    },
    renderElement: function() {
        var check = _.detect(this.node.children, function(column, column_index) {
            return _.detect(column.children,function(element){
                return element.tag === "action"? element: false;
            });
        });
        if (!check) {
            return this.no_result();
        }
        // We should start with three columns available
        for (var i = this.node.children.length; i < 3; i++) {
            this.node.children.push({
                tag: 'column',
                attrs: {},
                children: []
            });
        }
        var rendered = QWeb.render(this.form_template, this);
        this.$element.html(rendered);
    },
    no_result: function() {
        if (this.view.options.action.help) {
            this.$element.append(
                $('<div class="oe_view_nocontent">')
                    .append($('<img>', { src: '/web_dashboard/static/src/img/view_todo_arrow.png' }))
                    .append($('<div>').html(this.view.options.action.help || " "))
            );
        }
    },
    do_reload: function() {
        var view_manager = this.view.getParent(),
            action_manager = view_manager.getParent();
        this.view.destroy();
        action_manager.do_action(view_manager.action);
    }
});
instance.web.form.DashBoardLegacy = instance.web.form.DashBoard.extend({
    renderElement: function() {
        if (this.node.tag == 'hpaned') {
            this.node.attrs.style = '2-1';
        } else if (this.node.tag == 'vpaned') {
            this.node.attrs.style = '1';
        }
        this.node.tag = 'board';
        _.each(this.node.children, function(child) {
            if (child.tag.indexOf('child') == 0) {
                child.tag = 'column';
                var actions = [], first_child = child.children[0];
                if (first_child && first_child.tag == 'vpaned') {
                    _.each(first_child.children, function(subchild) {
                        actions.push.apply(actions, subchild.children);
                    });
                    child.children = actions;
                }
            }
        });
        this._super(this);
    }
});

instance.web.form.tags.add('hpaned', 'instance.web.form.DashBoardLegacy');
instance.web.form.tags.add('vpaned', 'instance.web.form.DashBoardLegacy');
instance.web.form.tags.add('board', 'instance.web.form.DashBoard');

/*
 * Widgets
 * This client action designed to be used as a dashboard widget display
 * the html content of a res_widget given as argument
 */
instance.web.client_actions.add( 'board.home.widgets', 'instance.web_dashboard.Widget');
instance.web_dashboard.Widget = instance.web.View.extend(/** @lends instance.web_dashboard.Widgets# */{
    template: 'HomeWidget',
    /**
     * Initializes a "HomeWidget" client widget: handles the display of a given
     * res.widget objects in an OpenERP view (mainly a dashboard).
     *
     * @constructs instance.web_dashboard.Widget
     * @extends instance.web.View
     *
     * @param {Object} parent
     * @param {Object} options
     * @param {Number} options.widget_id
     */
    init: function (parent, options) {
        this._super(parent);
        this.widget_id = options.widget_id;
    },
    start: function () {
        var ds = new instance.web.DataSet(this, 'res.widget');
        return ds.read_ids([this.widget_id], ['title']).then(this.on_widget_loaded);
    },
    on_widget_loaded: function (widgets) {
        var widget = widgets[0];
        var url = _.str.sprintf(
            '/web_dashboard/widgets/content?session_id=%s&widget_id=%d',
            this.session.session_id, widget.id);
        this.$element.html(QWeb.render('HomeWidget.content', {
            widget: widget,
            url: url
        }));
    }
});

};
<|endoftext|>


<commit_before>/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.
 */

// Default container configuration. Rather than replacing this
// file, you should create your own container.js file and
// load it directly by modifying the value of web.xml.
// All configurations will automatically inherit values from this
// config, so you only need to provide configuration for items
// that you require explicit special casing for.

// Please namespace your attributes using the same conventions
// as you would for javascript objects, e.g. gadgets.features
// rather than "features".

// NOTE: Please _don't_ leave trailing commas because the php json parser
// errors out on this.

// Container must be an array; this allows multiple containers
// to share configuration.
{"gadgets.container" : ["default"],

// Set of regular expressions to validate the parent parameter. This is
// necessary to support situations where you want a single container to support
// multiple possible host names (such as for localized domains, such as
// <language>.example.org. If left as null, the parent parameter will be
// ignored; otherwise, any requests that do not include a parent
// value matching this set will return a 404 error.
"gadgets.parent" : null,

// Should all gadgets be forced on to a locked domain?
"gadgets.lockedDomainRequired" : false,

// DNS domain on which gadgets should render.
"gadgets.lockedDomainSuffix" : "-a.example.com:8080",

// This config data will be passed down to javascript. Please
// configure your object using the feature name rather than
// the javascript name.

// Only configuration for required features will be used.
// See individual feature.xml files for configuration details.
"gadgets.features" : {
  "core.io" : {
    // Note: /proxy is an open proxy. Be careful how you explose this!
    "proxyUrl" : "proxy?refresh=%refresh%&url=%url%",
    "jsonProxyUrl" : "proxy?output=js"
  },
  "views" : {
    "profile" : {
      "isOnlyVisible" : false,
      "aliases": ["DASHBOARD", "default"]
    },
    "canvas" : {
      "isOnlyVisible" : true,
      "aliases" : ["FULL_PAGE"]
    }
  },
  "rpc" : {
    // Path to the relay file. Automatically appended to the parent
    /// parameter if it passes input validation and is not null.
    // This should never be on the same host in a production environment!
    // Only use this for TESTING!
    "parentRelayUrl" : "/gadgets/files/container/rpc_relay.html",

    // If true, this will use the legacy ifpc wire format when making rpc
    // requests.
    "useLegacyProtocol" : false
  },
  // Skin defaults
  "skins" : {
    "properties" : {
      "BG_COLOR": "",
      "BG_IMAGE": "",
      "BG_POSITION": "",
      "BG_REPEAT": "",
      "FONT_COLOR": "",
      "ANCHOR_COLOR": ""
    }
  },
  "opensocial-0.7" : {
    // Path to fetch opensocial data from
    // Must be on the same domain as the gadget rendering server
    "path" : "/social/data",
    "domain" : "shindig",
    "enableCaja" : true,
    "supportedFields" : {
       "person" : ["id", "name", "thumbnailUrl", "profileUrl"],
       "activity" : ["id", "title"]
    },
    // If true, the restful wire format will be used.
    // Otherwise, uses the json wire format.
    // If you are using the default Shindig setup and want to use rest, don't
    // forget to change the "path" config to /social/rest
    "useRestful" : false
  }

}}
<commit_msg>Typo (explose -> expose)<commit_after>/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.
 */

// Default container configuration. Rather than replacing this
// file, you should create your own container.js file and
// load it directly by modifying the value of web.xml.
// All configurations will automatically inherit values from this
// config, so you only need to provide configuration for items
// that you require explicit special casing for.

// Please namespace your attributes using the same conventions
// as you would for javascript objects, e.g. gadgets.features
// rather than "features".

// NOTE: Please _don't_ leave trailing commas because the php json parser
// errors out on this.

// Container must be an array; this allows multiple containers
// to share configuration.
{"gadgets.container" : ["default"],

// Set of regular expressions to validate the parent parameter. This is
// necessary to support situations where you want a single container to support
// multiple possible host names (such as for localized domains, such as
// <language>.example.org. If left as null, the parent parameter will be
// ignored; otherwise, any requests that do not include a parent
// value matching this set will return a 404 error.
"gadgets.parent" : null,

// Should all gadgets be forced on to a locked domain?
"gadgets.lockedDomainRequired" : false,

// DNS domain on which gadgets should render.
"gadgets.lockedDomainSuffix" : "-a.example.com:8080",

// This config data will be passed down to javascript. Please
// configure your object using the feature name rather than
// the javascript name.

// Only configuration for required features will be used.
// See individual feature.xml files for configuration details.
"gadgets.features" : {
  "core.io" : {
    // Note: /proxy is an open proxy. Be careful how you expose this!
    "proxyUrl" : "proxy?refresh=%refresh%&url=%url%",
    "jsonProxyUrl" : "proxy?output=js"
  },
  "views" : {
    "profile" : {
      "isOnlyVisible" : false,
      "aliases": ["DASHBOARD", "default"]
    },
    "canvas" : {
      "isOnlyVisible" : true,
      "aliases" : ["FULL_PAGE"]
    }
  },
  "rpc" : {
    // Path to the relay file. Automatically appended to the parent
    /// parameter if it passes input validation and is not null.
    // This should never be on the same host in a production environment!
    // Only use this for TESTING!
    "parentRelayUrl" : "/gadgets/files/container/rpc_relay.html",

    // If true, this will use the legacy ifpc wire format when making rpc
    // requests.
    "useLegacyProtocol" : false
  },
  // Skin defaults
  "skins" : {
    "properties" : {
      "BG_COLOR": "",
      "BG_IMAGE": "",
      "BG_POSITION": "",
      "BG_REPEAT": "",
      "FONT_COLOR": "",
      "ANCHOR_COLOR": ""
    }
  },
  "opensocial-0.7" : {
    // Path to fetch opensocial data from
    // Must be on the same domain as the gadget rendering server
    "path" : "/social/data",
    "domain" : "shindig",
    "enableCaja" : true,
    "supportedFields" : {
       "person" : ["id", "name", "thumbnailUrl", "profileUrl"],
       "activity" : ["id", "title"]
    },
    // If true, the restful wire format will be used.
    // Otherwise, uses the json wire format.
    // If you are using the default Shindig setup and want to use rest, don't
    // forget to change the "path" config to /social/rest
    "useRestful" : false
  }

}}
<|endoftext|>


<commit_before>var path = require('path')
var packageConf = require('../package.json')

module.exports = {
  build: {
    env: {
      NODE_ENV: '"production"'
    },
    index: path.resolve(__dirname, '../dist/index.html'),
    assetsRoot: path.resolve(__dirname, '../dist'),
    assetsSubDirectory: 'static',
    assetsPublicPath: '/' + packageConf.name + '/',
    productionSourceMap: true,
    // Gzip off by default as many popular static hosts such as
    // Surge or Netlify already gzip all static assets for you.
    // Before setting to `true`, make sure to:
    // npm install --save-dev compression-webpack-plugin
    productionGzip: false,
    productionGzipExtensions: ['js', 'css'],
    // multi pages
    basePath: '/vue-destop',
    targetRoot: path.resolve(__dirname, '../../test/webapp'),
    autoDeploy: false,
    pagesDir: 'views',
    pagesSubDir: '',
    pageExt: 'html'
  },
  dev: {
    env: {
      NODE_ENV: '"development"'
    },
    port: 8888,
    assetsSubDirectory: 'static',
    assetsPublicPath: '/',
    proxyTable: {
      // proxy all requests starting with /api to rap
      '/api': {
        target: 'http://172.16.1.63:8018/mockjsdata/12',
        changeOrigin: true,
        pathRewrite: {
          '^/api': ''
        }
      }
    },
    // CSS Sourcemaps off by default because relative paths are "buggy"
    // with this option, according to the CSS-Loader README
    // (https://github.com/webpack/css-loader#sourcemaps)
    // In our experience, they generally work as expected,
    // just be aware of this issue when enabling this option.
    cssSourceMap: false,
    // multi pages
    // basePath: '/\<%=basePath %\>',
    basePath: '',
    pagesDir: '',
    pageExt: 'html'

  }
}
<commit_msg>update bathpath<commit_after>var path = require('path')
var packageConf = require('../package.json')

module.exports = {
  build: {
    env: {
      NODE_ENV: '"production"'
    },
    index: path.resolve(__dirname, '../dist/index.html'),
    assetsRoot: path.resolve(__dirname, '../dist'),
    assetsSubDirectory: 'static',
    assetsPublicPath: '/' + packageConf.name + '/',
    productionSourceMap: true,
    // Gzip off by default as many popular static hosts such as
    // Surge or Netlify already gzip all static assets for you.
    // Before setting to `true`, make sure to:
    // npm install --save-dev compression-webpack-plugin
    productionGzip: false,
    productionGzipExtensions: ['js', 'css'],
    // multi pages
    basePath: '/vue-destop/views',
    targetRoot: path.resolve(__dirname, '../../test/webapp'),
    autoDeploy: false,
    pagesDir: 'views',
    pagesSubDir: '',
    pageExt: 'html'
  },
  dev: {
    env: {
      NODE_ENV: '"development"'
    },
    port: 8888,
    assetsSubDirectory: 'static',
    assetsPublicPath: '/',
    proxyTable: {
      // proxy all requests starting with /api to rap
      '/api': {
        target: 'http://172.16.1.63:8018/mockjsdata/12',
        changeOrigin: true,
        pathRewrite: {
          '^/api': ''
        }
      }
    },
    // CSS Sourcemaps off by default because relative paths are "buggy"
    // with this option, according to the CSS-Loader README
    // (https://github.com/webpack/css-loader#sourcemaps)
    // In our experience, they generally work as expected,
    // just be aware of this issue when enabling this option.
    cssSourceMap: false,
    // multi pages
    // basePath: '/\<%=basePath %\>',
    basePath: '',
    pagesDir: '',
    pageExt: 'html'

  }
}
<|endoftext|>


<commit_before>module.exports = {
  scenarios: [
    {
      name: 'default',
      dependencies: { }
    },
    {
      name: 'ember-release',
      dependencies: {
        'ember': 'components/ember#release'
      },
      resolutions: {
        'ember': 'release'
      }
    },
    {
      name: 'ember-beta',
      dependencies: {
        'ember': 'components/ember#beta'
      },
      resolutions: {
        'ember': 'beta'
      }
    },
    {
      name: 'ember-canary',
      dependencies: {
        'ember': 'components/ember#canary'
      },
      resolutions: {
        'ember': 'canary'
      }
    }
  ]
};
<commit_msg>Disable tests on beta/canary builds<commit_after>module.exports = {
  scenarios: [
    {
      name: 'default',
      dependencies: { }
    },
    {
      name: 'ember-release',
      dependencies: {
        'ember': 'components/ember#release'
      },
      resolutions: {
        'ember': 'release'
      }
    }
    /* TODO: Skipping, Current code does not work on beta/canary builds yet.
    {
      name: 'ember-beta',
      dependencies: {
        'ember': 'components/ember#beta'
      },
      resolutions: {
        'ember': 'beta'
      }
    },
    {
      name: 'ember-canary',
      dependencies: {
        'ember': 'components/ember#canary'
      },
      resolutions: {
        'ember': 'canary'
      }
    }
    */
  ]
};
<|endoftext|>


<commit_before>'use strict';

const getChannelURL = require('ember-source-channel-url');

module.exports = function() {
  return Promise.all([
    getChannelURL('release')
  ]).then((urls) => {
    return {
      useYarn: true,
      scenarios: [
        {
          name: 'ember-lts-3.16',
          npm: {
            devDependencies: {
              'ember-source': '~3.16.0'
            }
          }
        },
        {
          name: 'ember-release',
          npm: {
            devDependencies: {
              'ember-source': urls[0]
            }
          }
        },
        {
          name: 'ember-default',
          npm: {
            devDependencies: {}
          }
        },
        {
          name: 'ember-default-with-jquery',
          env: {
            EMBER_OPTIONAL_FEATURES: JSON.stringify({
              'jquery-integration': true
            })
          },
          npm: {
            devDependencies: {
              '@ember/jquery': '^0.5.1'
            }
          }
        }
      ]
    };
  });
};
<commit_msg>Update try config<commit_after>'use strict';

const getChannelURL = require('ember-source-channel-url');

module.exports = async function() {
  return {
    useYarn: true,
    scenarios: [
      {
        name: 'ember-lts-3.16',
        npm: {
          devDependencies: {
            'ember-source': '~3.16.0'
          }
        }
      },
      {
        name: 'ember-release',
        npm: {
          devDependencies: {
            'ember-source': await getChannelURL('release')
          }
        }
      },
      {
        name: 'ember-default-with-jquery',
        env: {
          EMBER_OPTIONAL_FEATURES: JSON.stringify({
            'jquery-integration': true
          })
        },
        npm: {
          devDependencies: {
            '@ember/jquery': '^0.5.1'
          }
        }
      }
    ]
  };
};
<|endoftext|>


<commit_before>/**
 * Created by wbqd on 15. 1. 19..
 */
// Include the same assets from all.js, but for the vendor libraries (3rd party),
// include the minimized versions. These will not be minified during the build
// but instead concat together to form 1 vendor js file.
'use strict';

module.exports = {
    assets: {
        lib: {
        	css: [
        		'public/lib/bootstrap/dist/css/bootstrap.min.css'
        	],
        	js: [
                //'public/lib/jquery/dist/jquery.min.js',
                'public/lib/angular/angular.min.js',
                'public/lib/angular-resource/angular-resource.min.js',
                'public/lib/angular-cookies/angular-cookies.min.js',
                'public/lib/angular-animate/angular-animate.min.js',
                'public/lib/angular-touch/angular-touch.min.js',
                'public/lib/angular-sanitize/angular-sanitize.min.js',
                'public/lib/angular-ui-router/release/angular-ui-router.min.js',
                'public/lib/angular-ui-utils/ui-utils.min.js',
                'public/lib/angular-bootstrap/ui-bootstrap-tpls.min.js'/*,
                'public/lib/bootstrap/dist/js/bootstrap.min.js'*/
        	]
        },
        css: [
        	'public/modules/**/css/*.css'
        ],
        js: [
        	'public/config.js',
        	'public/application.js',
        	'public/modules/*/*.js',
        	'public/modules/*/*[!tests]*/*.js'
        ]
    }
};
<commit_msg>jquery not included fix<commit_after>/**
 * Created by wbqd on 15. 1. 19..
 */
// Include the same assets from all.js, but for the vendor libraries (3rd party),
// include the minimized versions. These will not be minified during the build
// but instead concat together to form 1 vendor js file.
'use strict';

module.exports = {
    assets: {
        lib: {
        	css: [
        		'public/lib/bootstrap/dist/css/bootstrap.min.css'
        	],
        	js: [
                'public/lib/jquery/dist/jquery.min.js',
                'public/lib/angular/angular.min.js',
                'public/lib/angular-resource/angular-resource.min.js',
                'public/lib/angular-cookies/angular-cookies.min.js',
                'public/lib/angular-animate/angular-animate.min.js',
                'public/lib/angular-touch/angular-touch.min.js',
                'public/lib/angular-sanitize/angular-sanitize.min.js',
                'public/lib/angular-ui-router/release/angular-ui-router.min.js',
                'public/lib/angular-ui-utils/ui-utils.min.js',
                'public/lib/angular-bootstrap/ui-bootstrap-tpls.min.js'/*,
                'public/lib/bootstrap/dist/js/bootstrap.min.js'*/
        	]
        },
        css: [
        	'public/modules/**/css/*.css'
        ],
        js: [
        	'public/config.js',
        	'public/application.js',
        	'public/modules/*/*.js',
        	'public/modules/*/*[!tests]*/*.js'
        ]
    }
};
<|endoftext|>


<commit_before>import React from 'react';
import PropTypes from 'prop-types';

import GrayBox from 'atoms/GrayBox';
import styles from './block-header.module.scss';

const BlockHeader = ({
  supertitle,
  title,
  description,
  cols,
  variant,
  colorDash,
  leftOffset,
  verticalPadding
}) => <GrayBox
  cols={cols}
  variant={variant}
  colorDash={colorDash}
  leftOffset={leftOffset}
  verticalPadding={verticalPadding}
>
  <Text variant='label' className={styles.label}>
    {supertitle}
  </Text>
  <Text font='a' size={2}>
    {title}
  </Text>
  <Text className={styles.description} font='b' size={9}>
    {description}
  </Text>
</GrayBox>;

BlockHeader.propTypes = {
  /**
   * The small title above the main title
   */
  supertitle: PropTypes.string,
  /**
   * The main title
   */
  title: PropTypes.string,
  /**
   * The description under the title
   */
  description: PropTypes.string,
  /**
   * How many columns the grey box spans
   */
  cols: PropTypes.number,
  /**
   * `left` or `right` fixed to the side of the section
   */
  variant: PropTypes.string,
  /**
   * Color of the color dash, e.g. "primary-1" or "secondary-2"
   */
  colorDash: PropTypes.string,
  /**
   * How much padding to have between titles and gray box in pixels e.g. `"12px"`
   */
  verticalPadding: PropTypes.string,
  /**
   * Number of columns to push the title to the right, eg `3`
   */
  leftOffset: PropTypes.number
};

export default BlockHeader;
<commit_msg>Clean git history<commit_after>import React from 'react';
import PropTypes from 'prop-types';

import GrayBox from 'atoms/GrayBox';
import styles from './block-header.module.scss';

const BlockHeader = ({
  supertitle,
  title,
  description,
  cols,
  variant,
  colorDash,
  leftOffset,
  verticalPadding
}) =>
  <GrayBox
    cols={cols}
    variant={variant}
    colorDash={colorDash}
    leftOffset={leftOffset}
    verticalPadding={verticalPadding}
  >
    <Text variant='label' className={styles.label}>
      {supertitle}
    </Text>
    <Text font='a' size={2}>
      {title}
    </Text>
    <Text className={styles.description} font='b' size={9}>
      {description}
    </Text>
    </GrayBox>;

BlockHeader.propTypes = {
  /**
   * The small title above the main title
   */
  supertitle: PropTypes.string,
  /**
   * The main title
   */
  title: PropTypes.string,
  /**
   * The description under the title
   */
  description: PropTypes.string,
  /**
   * How many columns the grey box spans
   */
  cols: PropTypes.number,
  /**
   * `left` or `right` fixed to the side of the section
   */
  variant: PropTypes.string,
  /**
   * Color of the color dash, e.g. "primary-1" or "secondary-2"
   */
  colorDash: PropTypes.string,
  /**
   * How much padding to have between titles and gray box in pixels e.g. `"12px"`
   */
  verticalPadding: PropTypes.string,
  /**
   * Number of columns to push the title to the right, eg `3`
   */
  leftOffset: PropTypes.number
};

export default BlockHeader;
<|endoftext|>


<commit_before>Munderscore-min.jsZYoH~ׯBBm`_tddXBd7%X[IGwWu|GEQFy!&Kg:N5tw~N\ߊyGFd4sE߈q҉!ҝÓ*X
!N·ND"+{^TIN1ۤ'̋"7E^n+&w Kg"RⰌ;u|e/6eU$wKS%i)gq+CQ3ҼURpxwp~j
1F2x eQdkU𻈪֣NJyWuV"h>/`lE6pfE#%-֤
ے~5պ"8<I+Q`F-\$ç딕յrCR5hq+v%yIf4ZMBG"jMBTu9wR?IXpMT)uѾq	FD<lJ{O |Ap~%<_?}tWNC6Y
ҬNS.ш١B2~ c	EI*U}ᲂ^xb<k/+zXAd~XvA!C@56pBXUr'PgHie^N+2&+BhBR~`# )O7@vfL9]p
i5B")EX:+܌j̚;Q	@KIx4]9]1ZMtVMM$ZC-s?0A2v {'N&UR玥p-hޘLF[c5QO3k0?0*^&b#"HX ǔܬcTQKu 'U뵃@=wYKnّPA-v.@^f%&HԳq:IƟ[hz&y`!
{v%1T20Υ4ICc+IS
=Ahtl1#"F pO!l")I85GQXPm~%g[D668C!vH%
NQoK7$]~+zQ%+ɑJk+ȱbtSp.r&	nPpA\jJq45
0ک(Ukq-TP@u%:1AoW4,V/xģXɫC;&#I'z4j
-c%JfNlOpq3L&HT$Y68r!=_
 z`]=_/Ջ|::נ\r_:8ցS$O=ex1
*?t5b:3ƌvo5n!}~:`[/M,"X},]%`hFC>7˓+[\-UBO;'NUf9lg(1c҇-]L:,kKaRO
f%~	4tH7N`ET|ln6)<R@*],=mU4mupu>.
O+Uj|Ei$\:bZJ,BnS"0DN:hLZ=hr;P<qm5yI(FmMp^+"vū`Rd=
D0j8=Ep-&%"2*c`нѤ_xgQAz̦֠`JlNr*`uO[UY'HR/}r	ee6;B^񒲀)7d;K|E0DFzBFш'^٭X%lcrىP5ؗF
/?f") 6a'fV5\I%6y5vxSZeyhio,m3Ƭ4)]]kP0U!E_$=%"Fs~޽n:)]5A)dd|(0
Ȇe5*))պȫ*=S^K6	s'h8.9:Ǒ+ޣ7p\B<']8:γ邝,zKgZP^
z$zf2ib9k8W^bƅ^`\Dxqb6lu,6N.*KOVΐQL-34
̶p6Jwv24iZ"Ѷ)B_;ʔ*XV'VXuTyf(ͳ3ƙGx ]NB%l6r|fb`EHDABQ|hn!MwF#(%g[fI3o[U/u^0ż7x*`:57aNV*Sz l죝T_}[;R߶)D&Jl/WPYF78_&zg^PDmU K~((@ ѧO)D|M*C/V~zD@$!wd!rPVp|ЎMJu[)zxOO'CI̷/n֒ߙS@.Ԗ9r5u"9E6	PK.B2<~被(k]0{͊נKɬCeoe\iU.?Ap#}=)U=w`ņJn	L`}cSR;Q;H`BT%J9[<h4QO	+F|nuP.6Ń7~H|JS) tLvq:N쨀v[Nv&"OuW=7'0׼{mq8ĥR!
<]>[ܔ7_ˋ+<oiu[\orZ}"BuvOuLn]!-~xhF{1~\t~zOZ
wJ}Fqܖ-倔K0c}3g&Zz)JE{MfzX4`
P<ɼg6i%XK]eϫg\_701h,3QYMk9o_yǒcr}4%Z'&:J[?hÕ?[pv]yu=EsPWUxp@-j{b[;]A{&<commit_msg>Accidentally committed gzipped version of underscore 1.1.5. Reversed this error.<commit_after>// Underscore.js 1.1.5
// (c) 2011 Jeremy Ashkenas, DocumentCloud Inc.
// Underscore is freely distributable under the MIT license.
// Portions of Underscore are inspired or borrowed from Prototype,
// Oliver Steele's Functional, and John Resig's Micro-Templating.
// For all details and documentation:
// http://documentcloud.github.com/underscore
(function(){var q=this,D=q._,n={},k=Array.prototype,o=Object.prototype,i=k.slice,E=k.unshift,F=o.toString,m=o.hasOwnProperty,s=k.forEach,t=k.map,u=k.reduce,v=k.reduceRight,w=k.filter,x=k.every,y=k.some,p=k.indexOf,z=k.lastIndexOf;o=Array.isArray;var G=Object.keys,A=Function.prototype.bind,c=function(a){return new l(a)};if(typeof module!=="undefined"&&module.exports){module.exports=c;c._=c}else q._=c;c.VERSION="1.1.5";var j=c.each=c.forEach=function(a,b,d){if(a!=null)if(s&&a.forEach===s)a.forEach(b,
d);else if(c.isNumber(a.length))for(var e=0,f=a.length;e<f;e++){if(b.call(d,a[e],e,a)===n)break}else for(e in a)if(m.call(a,e))if(b.call(d,a[e],e,a)===n)break};c.map=function(a,b,d){var e=[];if(a==null)return e;if(t&&a.map===t)return a.map(b,d);j(a,function(f,g,h){e[e.length]=b.call(d,f,g,h)});return e};c.reduce=c.foldl=c.inject=function(a,b,d,e){var f=d!==void 0;if(a==null)a=[];if(u&&a.reduce===u){if(e)b=c.bind(b,e);return f?a.reduce(b,d):a.reduce(b)}j(a,function(g,h,H){if(!f&&h===0){d=g;f=true}else d=
b.call(e,d,g,h,H)});if(!f)throw new TypeError("Reduce of empty array with no initial value");return d};c.reduceRight=c.foldr=function(a,b,d,e){if(a==null)a=[];if(v&&a.reduceRight===v){if(e)b=c.bind(b,e);return d!==void 0?a.reduceRight(b,d):a.reduceRight(b)}a=(c.isArray(a)?a.slice():c.toArray(a)).reverse();return c.reduce(a,b,d,e)};c.find=c.detect=function(a,b,d){var e;B(a,function(f,g,h){if(b.call(d,f,g,h)){e=f;return true}});return e};c.filter=c.select=function(a,b,d){var e=[];if(a==null)return e;
if(w&&a.filter===w)return a.filter(b,d);j(a,function(f,g,h){if(b.call(d,f,g,h))e[e.length]=f});return e};c.reject=function(a,b,d){var e=[];if(a==null)return e;j(a,function(f,g,h){b.call(d,f,g,h)||(e[e.length]=f)});return e};c.every=c.all=function(a,b,d){b=b||c.identity;var e=true;if(a==null)return e;if(x&&a.every===x)return a.every(b,d);j(a,function(f,g,h){if(!(e=e&&b.call(d,f,g,h)))return n});return e};var B=c.some=c.any=function(a,b,d){b=b||c.identity;var e=false;if(a==null)return e;if(y&&a.some===
y)return a.some(b,d);j(a,function(f,g,h){if(e=b.call(d,f,g,h))return n});return e};c.include=c.contains=function(a,b){var d=false;if(a==null)return d;if(p&&a.indexOf===p)return a.indexOf(b)!=-1;B(a,function(e){if(d=e===b)return true});return d};c.invoke=function(a,b){var d=i.call(arguments,2);return c.map(a,function(e){return(b?e[b]:e).apply(e,d)})};c.pluck=function(a,b){return c.map(a,function(d){return d[b]})};c.max=function(a,b,d){if(!b&&c.isArray(a))return Math.max.apply(Math,a);var e={computed:-Infinity};
j(a,function(f,g,h){g=b?b.call(d,f,g,h):f;g>=e.computed&&(e={value:f,computed:g})});return e.value};c.min=function(a,b,d){if(!b&&c.isArray(a))return Math.min.apply(Math,a);var e={computed:Infinity};j(a,function(f,g,h){g=b?b.call(d,f,g,h):f;g<e.computed&&(e={value:f,computed:g})});return e.value};c.sortBy=function(a,b,d){return c.pluck(c.map(a,function(e,f,g){return{value:e,criteria:b.call(d,e,f,g)}}).sort(function(e,f){var g=e.criteria,h=f.criteria;return g<h?-1:g>h?1:0}),"value")};c.sortedIndex=
function(a,b,d){d=d||c.identity;for(var e=0,f=a.length;e<f;){var g=e+f>>1;d(a[g])<d(b)?e=g+1:f=g}return e};c.toArray=function(a){if(!a)return[];if(a.toArray)return a.toArray();if(c.isArray(a))return a;if(c.isArguments(a))return i.call(a);return c.values(a)};c.size=function(a){return c.toArray(a).length};c.first=c.head=function(a,b,d){return b!=null&&!d?i.call(a,0,b):a[0]};c.rest=c.tail=function(a,b,d){return i.call(a,b==null||d?1:b)};c.last=function(a){return a[a.length-1]};c.compact=function(a){return c.filter(a,
function(b){return!!b})};c.flatten=function(a){return c.reduce(a,function(b,d){if(c.isArray(d))return b.concat(c.flatten(d));b[b.length]=d;return b},[])};c.without=function(a){var b=i.call(arguments,1);return c.filter(a,function(d){return!c.include(b,d)})};c.uniq=c.unique=function(a,b){return c.reduce(a,function(d,e,f){if(0==f||(b===true?c.last(d)!=e:!c.include(d,e)))d[d.length]=e;return d},[])};c.intersect=function(a){var b=i.call(arguments,1);return c.filter(c.uniq(a),function(d){return c.every(b,
function(e){return c.indexOf(e,d)>=0})})};c.zip=function(){for(var a=i.call(arguments),b=c.max(c.pluck(a,"length")),d=Array(b),e=0;e<b;e++)d[e]=c.pluck(a,""+e);return d};c.indexOf=function(a,b,d){if(a==null)return-1;var e;if(d){d=c.sortedIndex(a,b);return a[d]===b?d:-1}if(p&&a.indexOf===p)return a.indexOf(b);d=0;for(e=a.length;d<e;d++)if(a[d]===b)return d;return-1};c.lastIndexOf=function(a,b){if(a==null)return-1;if(z&&a.lastIndexOf===z)return a.lastIndexOf(b);for(var d=a.length;d--;)if(a[d]===b)return d;
return-1};c.range=function(a,b,d){if(arguments.length<=1){b=a||0;a=0}d=arguments[2]||1;for(var e=Math.max(Math.ceil((b-a)/d),0),f=0,g=Array(e);f<e;){g[f++]=a;a+=d}return g};c.bind=function(a,b){if(A&&a.bind===A)return a.bind.apply(a,i.call(arguments,1));var d=i.call(arguments,2);return function(){return a.apply(b,d.concat(i.call(arguments)))}};c.bindAll=function(a){var b=i.call(arguments,1);if(b.length==0)b=c.functions(a);j(b,function(d){a[d]=c.bind(a[d],a)});return a};c.memoize=function(a,b){var d=
{};b=b||c.identity;return function(){var e=b.apply(this,arguments);return m.call(d,e)?d[e]:d[e]=a.apply(this,arguments)}};c.delay=function(a,b){var d=i.call(arguments,2);return setTimeout(function(){return a.apply(a,d)},b)};c.defer=function(a){return c.delay.apply(c,[a,1].concat(i.call(arguments,1)))};var C=function(a,b,d){var e;return function(){var f=this,g=arguments,h=function(){e=null;a.apply(f,g)};d&&clearTimeout(e);if(d||!e)e=setTimeout(h,b)}};c.throttle=function(a,b){return C(a,b,false)};c.debounce=
function(a,b){return C(a,b,true)};c.once=function(a){var b=false,d;return function(){if(b)return d;b=true;return d=a.apply(this,arguments)}};c.wrap=function(a,b){return function(){var d=[a].concat(i.call(arguments));return b.apply(this,d)}};c.compose=function(){var a=i.call(arguments);return function(){for(var b=i.call(arguments),d=a.length-1;d>=0;d--)b=[a[d].apply(this,b)];return b[0]}};c.keys=G||function(a){if(a!==Object(a))throw new TypeError("Invalid object");var b=[],d;for(d in a)if(m.call(a,
d))b[b.length]=d;return b};c.values=function(a){return c.map(a,c.identity)};c.functions=c.methods=function(a){return c.filter(c.keys(a),function(b){return c.isFunction(a[b])}).sort()};c.extend=function(a){j(i.call(arguments,1),function(b){for(var d in b)a[d]=b[d]});return a};c.defaults=function(a){j(i.call(arguments,1),function(b){for(var d in b)if(a[d]==null)a[d]=b[d]});return a};c.clone=function(a){return c.isArray(a)?a.slice():c.extend({},a)};c.tap=function(a,b){b(a);return a};c.isEqual=function(a,
b){if(a===b)return true;var d=typeof a;if(d!=typeof b)return false;if(a==b)return true;if(!a&&b||a&&!b)return false;if(a._chain)a=a._wrapped;if(b._chain)b=b._wrapped;if(a.isEqual)return a.isEqual(b);if(c.isDate(a)&&c.isDate(b))return a.getTime()===b.getTime();if(c.isNaN(a)&&c.isNaN(b))return false;if(c.isRegExp(a)&&c.isRegExp(b))return a.source===b.source&&a.global===b.global&&a.ignoreCase===b.ignoreCase&&a.multiline===b.multiline;if(d!=="object")return false;if(a.length&&a.length!==b.length)return false;
d=c.keys(a);var e=c.keys(b);if(d.length!=e.length)return false;for(var f in a)if(!(f in b)||!c.isEqual(a[f],b[f]))return false;return true};c.isEmpty=function(a){if(c.isArray(a)||c.isString(a))return a.length===0;for(var b in a)if(m.call(a,b))return false;return true};c.isElement=function(a){return!!(a&&a.nodeType==1)};c.isArray=o||function(a){return F.call(a)==="[object Array]"};c.isArguments=function(a){return!!(a&&m.call(a,"callee"))};c.isFunction=function(a){return!!(a&&a.constructor&&a.call&&
a.apply)};c.isString=function(a){return!!(a===""||a&&a.charCodeAt&&a.substr)};c.isNumber=function(a){return!!(a===0||a&&a.toExponential&&a.toFixed)};c.isNaN=function(a){return a!==a};c.isBoolean=function(a){return a===true||a===false};c.isDate=function(a){return!!(a&&a.getTimezoneOffset&&a.setUTCFullYear)};c.isRegExp=function(a){return!!(a&&a.test&&a.exec&&(a.ignoreCase||a.ignoreCase===false))};c.isNull=function(a){return a===null};c.isUndefined=function(a){return a===void 0};c.noConflict=function(){q._=
D;return this};c.identity=function(a){return a};c.times=function(a,b,d){for(var e=0;e<a;e++)b.call(d,e)};c.mixin=function(a){j(c.functions(a),function(b){I(b,c[b]=a[b])})};var J=0;c.uniqueId=function(a){var b=J++;return a?a+b:b};c.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g};c.template=function(a,b){var d=c.templateSettings;d="var __p=[],print=function(){__p.push.apply(__p,arguments);};with(obj||{}){__p.push('"+a.replace(/\\/g,"\\\\").replace(/'/g,"\\'").replace(d.interpolate,
function(e,f){return"',"+f.replace(/\\'/g,"'")+",'"}).replace(d.evaluate||null,function(e,f){return"');"+f.replace(/\\'/g,"'").replace(/[\r\n\t]/g," ")+"__p.push('"}).replace(/\r/g,"\\r").replace(/\n/g,"\\n").replace(/\t/g,"\\t")+"');}return __p.join('');";d=new Function("obj",d);return b?d(b):d};var l=function(a){this._wrapped=a};c.prototype=l.prototype;var r=function(a,b){return b?c(a).chain():a},I=function(a,b){l.prototype[a]=function(){var d=i.call(arguments);E.call(d,this._wrapped);return r(b.apply(c,
d),this._chain)}};c.mixin(c);j(["pop","push","reverse","shift","sort","splice","unshift"],function(a){var b=k[a];l.prototype[a]=function(){b.apply(this._wrapped,arguments);return r(this._wrapped,this._chain)}});j(["concat","join","slice"],function(a){var b=k[a];l.prototype[a]=function(){return r(b.apply(this._wrapped,arguments),this._chain)}});l.prototype.chain=function(){this._chain=true;return this};l.prototype.value=function(){return this._wrapped}})();
<|endoftext|>


<commit_before>/**
 * This is the default configuration file for the Superdesk application. By default,
 * the app will use the file with the name "superdesk.config.js" found in the current
 * working directory, but other files may also be specified using relative paths with
 * the SUPERDESK_CONFIG environment variable or the grunt --config flag.
 */

module.exports = function(grunt) {
    return {
        defaultRoute: '/workspace',
        validatorMediaMetadata: {
            headline: {
                required: true
            },
            alt_text: {
                required: true
            },
            description_text: {
                required: true
            },
            copyrightholder: {
                required: false
            },
            byline: {
                required: false
            },
            usageterms: {
                required: false
            },
            copyrightnotice: {
                required: false
            }
        },
        features: {
            swimlane: {columnsLimit: 4}
        },
        ingest: {
            PROVIDER_DASHBOARD_DEFAULTS: {
                show_log_messages: true,
                show_ingest_count: true,
                show_time: true,
                log_messages: 'error',
                show_status: true
            },
            DEFAULT_SCHEDULE: {minutes: 5, seconds: 0},
            DEFAULT_IDLE_TIME: {hours: 0, minutes: 0},
        }
    };
};
<commit_msg>Add archive description to validator and point to my repo for demo<commit_after>/**
 * This is the default configuration file for the Superdesk application. By default,
 * the app will use the file with the name "superdesk.config.js" found in the current
 * working directory, but other files may also be specified using relative paths with
 * the SUPERDESK_CONFIG environment variable or the grunt --config flag.
 */

module.exports = function(grunt) {
    return {
        defaultRoute: '/workspace',
        validatorMediaMetadata: {
            headline: {
                required: true
            },
            alt_text: {
                required: true
            },
            archive_description: {
                required: false
            },
            description_text: {
                required: true
            },
            copyrightholder: {
                required: false
            },
            byline: {
                required: false
            },
            usageterms: {
                required: false
            },
            copyrightnotice: {
                required: false
            }
        },
        features: {
            swimlane: {columnsLimit: 4}
        },
        ingest: {
            PROVIDER_DASHBOARD_DEFAULTS: {
                show_log_messages: true,
                show_ingest_count: true,
                show_time: true,
                log_messages: 'error',
                show_status: true
            },
            DEFAULT_SCHEDULE: {minutes: 5, seconds: 0},
            DEFAULT_IDLE_TIME: {hours: 0, minutes: 0},
        }
    };
};
<|endoftext|>


<commit_before>function initTask(subTask) {
   var cellSide = 60;

   subTask.gridInfos = {
      hideSaveOrLoad: true,
      cellSide: cellSide,
      actionDelay: 200,
      itemTypes: {
         green_robot: { img: "green_robot.png", side: 80, nbStates: 9, isObstacle: true, offsetX: -14, category: "robot", team: 0, zOrder: 2 },
         hole: { num: 2, img: "hole.png", side: cellSide, category: "hole", isObstacle: false, isHole: true, zOrder: 0 },
         marble: { num: 3, img: "marble.png", side: cellSide, category: "marble", isObstacle: false, isTransportable: true, zOrder: 1 }
      },
      maxInstructions: 15,
      includeBlocks: {
         groupByCategory: false,
         generatedBlocks: {
            robot: {
               easy: ["east", "pickTransportable", "dropTransportable", "onHole"],
               medium: ["east", "west", "south", "pickTransportable", "dropTransportable", "onHole", "onTransportable"],
               hard: ["east", "west", "south", "pickTransportable", "dropTransportable", "onHole", "onTransportable"]
            }
         },
         standardBlocks: {
            includeAll: false,
            wholeCategories: [],
            singleBlocks: {
               easy: ["controls_whileUntil", "logic_negate"],
               medium: ["controls_repeat", "controls_whileUntil", "logic_negate"],
               hard: ["controls_whileUntil", "logic_negate", "controls_repeat"]
            }
         },
      },
      ignoreInvalidMoves: false,
      checkEndEveryTurn: false,
      checkEndCondition: function(context, lastTurn) {
         var solved = true;
         for (var iRow = 0; iRow < context.tiles.length; iRow++) {
            var row = subTask.data[subTask.level][subTask.iTestCase].tiles[iRow];
            for (var iCol = 0; iCol < row.length; iCol++) {
               var marbles = context.getItems(iRow, iCol, {category: "marble"});
               var holes = context.getItems(iRow, iCol, {category: "hole"});
               if (marbles.length != holes.length) {
                  solved = false;
               }
            }
         }
         if (solved) {
            context.success = true;
            throw("Bravo, vous avez rangé toutes les billes !");
         }
         if (lastTurn) {
            context.success = false;
            throw("Les billes sont mal rangées !");
         }
      },
      computeGrade: function(context, message) {
         var rate = 0;
         if (context.success) {
            rate = 1;
         }
         return {
            successRate: rate,
            message: message
         };
      }
   };

   subTask.data = {
      easy: [
         {
            tiles: [
                   [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
                   [1, 3, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1],
                   [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
               ],
            initItems: [
                  { row: 1, col: 0, dir: 0, type: "green_robot" },
               ]
         },
         {
            tiles: [
                   [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
                   [1, 3, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1],
                   [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
               ],
            initItems: [
                  { row: 1, col: 0, dir: 0, type: "green_robot" },
               ]
         }
      ],
      medium: [
         {
            tiles: [
                   [1, 1, 1, 1, 1, 1, 1],
                   [1, 3, 1, 1, 2, 1, 1],
                   [1, 3, 1, 1, 2, 1, 1],
                   [1, 3, 1, 1, 2, 1, 1],
                   [1, 3, 1, 1, 2, 1, 1],
                   [1, 3, 1, 1, 2, 1, 1],
                   [1, 3, 1, 1, 2, 1, 1],
                   [1, 1, 1, 1, 1, 1, 1],
               ],
            initItems: [
                  { row: 1, col: 0, dir: 0, type: "green_robot" },
               ]
         },
         {
            tiles: [
                   [1, 1, 1, 1, 1, 1, 1],
                   [1, 3, 1, 1, 2, 1, 1],
                   [1, 3, 1, 1, 2, 1, 1],
                   [1, 3, 1, 1, 2, 1, 1],
                   [1, 3, 1, 1, 2, 1, 1],
                   [1, 1, 1, 1, 1, 1, 1],
               ],
            initItems: [
                  { row: 1, col: 0, dir: 0, type: "green_robot" },
               ]
         }
      ],
      hard: [
         {
            tiles: [
                   [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
                   [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
                   [1, 3, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1],
                   [1, 1, 1, 1, 3, 1, 1, 1, 2, 1, 1, 1, 1],
                   [1, 1, 1, 3, 1, 2, 1, 1, 1, 1, 1, 1, 1],
                   [1, 1, 3, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1],
                   [1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1],
                   [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
               ],
            initItems: [
                  { row: 1, col: 0, dir: 0, type: "green_robot" },
               ]
         }
      ]
   };

   initBlocklySubTask(subTask);
   displayHelper.thresholdEasy = 5000;
   displayHelper.thresholdMedium = 10000;
}

initWrapper(initTask, ["easy", "medium", "hard"], null, true);
<commit_msg>change test cases<commit_after>function initTask(subTask) {
   var cellSide = 60;

   subTask.gridInfos = {
      hideSaveOrLoad: true,
      cellSide: cellSide,
      actionDelay: 200,
      itemTypes: {
         green_robot: { img: "green_robot.png", side: 80, nbStates: 9, isObstacle: true, offsetX: -14, category: "robot", team: 0, zOrder: 2 },
         hole: { num: 2, img: "hole.png", side: cellSide, category: "hole", isObstacle: false, isHole: true, zOrder: 0 },
         marble: { num: 3, img: "marble.png", side: cellSide, category: "marble", isObstacle: false, isTransportable: true, zOrder: 1 }
      },
      maxInstructions: 15,
      includeBlocks: {
         groupByCategory: false,
         generatedBlocks: {
            robot: {
               easy: ["east", "pickTransportable", "dropTransportable", "onHole"],
               medium: ["east", "west", "south", "pickTransportable", "dropTransportable", "onHole", "onTransportable"],
               hard: ["east", "west", "south", "pickTransportable", "dropTransportable", "onHole", "onTransportable"]
            }
         },
         standardBlocks: {
            includeAll: false,
            wholeCategories: [],
            singleBlocks: {
               easy: ["controls_whileUntil", "logic_negate"],
               medium: ["controls_repeat", "controls_whileUntil", "logic_negate"],
               hard: ["controls_whileUntil", "logic_negate", "controls_repeat"]
            }
         },
      },
      ignoreInvalidMoves: false,
      checkEndEveryTurn: false,
      checkEndCondition: function(context, lastTurn) {
         var solved = true;
         for (var iRow = 0; iRow < context.tiles.length; iRow++) {
            var row = subTask.data[subTask.level][subTask.iTestCase].tiles[iRow];
            for (var iCol = 0; iCol < row.length; iCol++) {
               var marbles = context.getItems(iRow, iCol, {category: "marble"});
               var holes = context.getItems(iRow, iCol, {category: "hole"});
               if (marbles.length != holes.length) {
                  solved = false;
               }
            }
         }
         if (solved) {
            context.success = true;
            throw("Bravo, vous avez rangé toutes les billes !");
         }
         if (lastTurn) {
            context.success = false;
            throw("Les billes sont mal rangées !");
         }
      },
      computeGrade: function(context, message) {
         var rate = 0;
         if (context.success) {
            rate = 1;
         }
         return {
            successRate: rate,
            message: message
         };
      }
   };

   subTask.data = {
      easy: [
         {
            tiles: [
                   [1, 3, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1]
               ],
            initItems: [
                  { row: 0, col: 0, dir: 0, type: "green_robot" },
               ]
         },
         {
            tiles: [
                   [1, 3, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1]
               ],
            initItems: [
                  { row: 0, col: 0, dir: 0, type: "green_robot" },
               ]
         }
      ],
      medium: [
         {
            tiles: [
                   [1, 3, 1, 1, 2, 1, 1],
                   [1, 3, 1, 1, 2, 1, 1],
                   [1, 3, 1, 1, 2, 1, 1],
                   [1, 3, 1, 1, 2, 1, 1],
                   [1, 3, 1, 1, 2, 1, 1],
                   [1, 3, 1, 1, 2, 1, 1],
                   [1, 1, 1, 1, 1, 1, 1],
               ],
            initItems: [
                  { row: 0, col: 0, dir: 0, type: "green_robot" },
               ]
         },
         {
            tiles: [
                   [1, 3, 1, 1, 2, 1, 1],
                   [1, 3, 1, 1, 2, 1, 1],
                   [1, 3, 1, 1, 2, 1, 1],
                   [1, 3, 1, 1, 2, 1, 1],
                   [1, 1, 1, 1, 1, 1, 1],
               ],
            initItems: [
                  { row: 0, col: 0, dir: 0, type: "green_robot" },
               ]
         }
      ],
      hard: [
         {
            tiles: [
                   [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
                   [1, 3, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1],
                   [1, 1, 1, 1, 3, 1, 1, 1, 2, 1, 1, 1, 1],
                   [1, 1, 1, 3, 1, 2, 1, 1, 1, 1, 1, 1, 1],
                   [1, 1, 3, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1],
                   [1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1],
                   [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
               ],
            initItems: [
                  { row: 0, col: 0, dir: 0, type: "green_robot" },
               ]
         }
      ]
   };

   initBlocklySubTask(subTask);
   displayHelper.thresholdEasy = 5000;
   displayHelper.thresholdMedium = 10000;
}

initWrapper(initTask, ["easy", "medium", "hard"], null, true);
<|endoftext|>


<commit_before>'use strict';

const express = require('../express');
const proxyaddr = require('proxy-addr');
const settings = require('../../utils/Settings');
const socketio = require('socket.io');
const socketIORouter = require('../../handler/SocketIORouter');
const hooks = require('../../../static/js/pluginfw/hooks');
const padMessageHandler = require('../../handler/PadMessageHandler');
const util = require('util');

let io;

exports.expressCloseServer = async () => {
  // According to the socket.io documentation every client is always in the default namespace (and
  // may also be in other namespaces).
  const ns = io.sockets; // The Namespace object for the default namespace.
  // Disconnect all socket.io clients. This probably isn't necessary; closing the socket.io Engine
  // (see below) probably gracefully disconnects all clients. But that is not documented, and this
  // doesn't seem to hurt, so hedge against surprising and undocumented socket.io behavior.
  for (const id of await util.promisify(ns.clients.bind(ns))()) {
    ns.connected[id].disconnect(true);
  }
  // Don't call io.close() because that closes the underlying HTTP server, which is already done
  // elsewhere. (Closing an HTTP server twice throws an exception.) The `engine` property of
  // socket.io Server objects is undocumented, but I don't see any other way to shut down socket.io
  // without also closing the HTTP server.
  io.engine.close();
};

exports.expressCreateServer = (hookName, args, cb) => {
  // init socket.io and redirect all requests to the MessageHandler
  // there shouldn't be a browser that isn't compatible to all
  // transports in this list at once
  // e.g. XHR is disabled in IE by default, so in IE it should use jsonp-polling
  io = socketio({
    transports: settings.socketTransportProtocols,
  }).listen(args.server, {
    /*
     * Do not set the "io" cookie.
     *
     * The "io" cookie is created by socket.io, and its purpose is to offer an
     * handle to perform load balancing with session stickiness when the library
     * falls back to long polling or below.
     *
     * In Etherpad's case, if an operator needs to load balance, he can use the
     * "express_sid" cookie, and thus "io" is of no use.
     *
     * Moreover, socket.io API does not offer a way of setting the "secure" flag
     * on it, and thus is a liability.
     *
     * Let's simply nuke "io".
     *
     * references:
     *   https://socket.io/docs/using-multiple-nodes/#Sticky-load-balancing
     *   https://github.com/socketio/socket.io/issues/2276#issuecomment-147184662 (not totally true, actually, see above)
     */
    cookie: false,
    maxHttpBufferSize: 10E3,
  });

  io.use((socket, next) => {
    const req = socket.request;
    // Express sets req.ip but socket.io does not. Replicate Express's behavior here.
    if (req.ip == null) {
      if (settings.trustProxy) {
        req.ip = proxyaddr(req, args.app.get('trust proxy fn'));
      } else {
        req.ip = socket.handshake.address;
      }
    }
    if (!req.headers.cookie) {
      // socketio.js-client on node.js doesn't support cookies (see https://git.io/JU8u9), so the
      // token and express_sid cookies have to be passed via a query parameter for unit tests.
      req.headers.cookie = socket.handshake.query.cookie;
    }
    // See: https://socket.io/docs/faq/#Usage-with-express-session
    express.sessionMiddleware(req, {}, next);
  });

  // var socketIOLogger = log4js.getLogger("socket.io");
  // Debug logging now has to be set at an environment level, this is stupid.
  // https://github.com/Automattic/socket.io/wiki/Migrating-to-1.0
  // This debug logging environment is set in Settings.js

  // minify socket.io javascript
  // Due to a shitty decision by the SocketIO team minification is
  // no longer available, details available at:
  // http://stackoverflow.com/questions/23981741/minify-socket-io-socket-io-js-with-1-0
  // if(settings.minify) io.enable('browser client minification');

  // Initialize the Socket.IO Router
  socketIORouter.setSocketIO(io);
  socketIORouter.addComponent('pad', padMessageHandler);

  hooks.callAll('socketio', {app: args.app, io, server: args.server});

  return cb();
};
<commit_msg>socketio: increase socketio limit to 1MiB<commit_after>'use strict';

const express = require('../express');
const proxyaddr = require('proxy-addr');
const settings = require('../../utils/Settings');
const socketio = require('socket.io');
const socketIORouter = require('../../handler/SocketIORouter');
const hooks = require('../../../static/js/pluginfw/hooks');
const padMessageHandler = require('../../handler/PadMessageHandler');
const util = require('util');

let io;

exports.expressCloseServer = async () => {
  // According to the socket.io documentation every client is always in the default namespace (and
  // may also be in other namespaces).
  const ns = io.sockets; // The Namespace object for the default namespace.
  // Disconnect all socket.io clients. This probably isn't necessary; closing the socket.io Engine
  // (see below) probably gracefully disconnects all clients. But that is not documented, and this
  // doesn't seem to hurt, so hedge against surprising and undocumented socket.io behavior.
  for (const id of await util.promisify(ns.clients.bind(ns))()) {
    ns.connected[id].disconnect(true);
  }
  // Don't call io.close() because that closes the underlying HTTP server, which is already done
  // elsewhere. (Closing an HTTP server twice throws an exception.) The `engine` property of
  // socket.io Server objects is undocumented, but I don't see any other way to shut down socket.io
  // without also closing the HTTP server.
  io.engine.close();
};

exports.expressCreateServer = (hookName, args, cb) => {
  // init socket.io and redirect all requests to the MessageHandler
  // there shouldn't be a browser that isn't compatible to all
  // transports in this list at once
  // e.g. XHR is disabled in IE by default, so in IE it should use jsonp-polling
  io = socketio({
    transports: settings.socketTransportProtocols,
  }).listen(args.server, {
    /*
     * Do not set the "io" cookie.
     *
     * The "io" cookie is created by socket.io, and its purpose is to offer an
     * handle to perform load balancing with session stickiness when the library
     * falls back to long polling or below.
     *
     * In Etherpad's case, if an operator needs to load balance, he can use the
     * "express_sid" cookie, and thus "io" is of no use.
     *
     * Moreover, socket.io API does not offer a way of setting the "secure" flag
     * on it, and thus is a liability.
     *
     * Let's simply nuke "io".
     *
     * references:
     *   https://socket.io/docs/using-multiple-nodes/#Sticky-load-balancing
     *   https://github.com/socketio/socket.io/issues/2276#issuecomment-147184662 (not totally true, actually, see above)
     */
    cookie: false,
    maxHttpBufferSize: 1 << 20, // 1MiB
  });

  io.use((socket, next) => {
    const req = socket.request;
    // Express sets req.ip but socket.io does not. Replicate Express's behavior here.
    if (req.ip == null) {
      if (settings.trustProxy) {
        req.ip = proxyaddr(req, args.app.get('trust proxy fn'));
      } else {
        req.ip = socket.handshake.address;
      }
    }
    if (!req.headers.cookie) {
      // socketio.js-client on node.js doesn't support cookies (see https://git.io/JU8u9), so the
      // token and express_sid cookies have to be passed via a query parameter for unit tests.
      req.headers.cookie = socket.handshake.query.cookie;
    }
    // See: https://socket.io/docs/faq/#Usage-with-express-session
    express.sessionMiddleware(req, {}, next);
  });

  // var socketIOLogger = log4js.getLogger("socket.io");
  // Debug logging now has to be set at an environment level, this is stupid.
  // https://github.com/Automattic/socket.io/wiki/Migrating-to-1.0
  // This debug logging environment is set in Settings.js

  // minify socket.io javascript
  // Due to a shitty decision by the SocketIO team minification is
  // no longer available, details available at:
  // http://stackoverflow.com/questions/23981741/minify-socket-io-socket-io-js-with-1-0
  // if(settings.minify) io.enable('browser client minification');

  // Initialize the Socket.IO Router
  socketIORouter.setSocketIO(io);
  socketIORouter.addComponent('pad', padMessageHandler);

  hooks.callAll('socketio', {app: args.app, io, server: args.server});

  return cb();
};
<|endoftext|>


<commit_before>// Test widget int class
casper.notebook_test(function () {
    index = this.append_cell(
        'from IPython.html import widgets\n' +
        'from IPython.display import display, clear_output\n' +
        'print("Success")');
    this.execute_cell_then(index);

    var int_text = {}
    int_text.query = '.widget-area .widget-subarea .widget-hbox-single .my-second-int-text';
    int_text.index = this.append_cell(
        'int_widget = widgets.IntTextWidget()\n' +
        'display(int_widget)\n' +
        'int_widget.add_class("my-second-int-text")\n' +
        'print(int_widget.model_id)\n');
    this.execute_cell_then(int_text.index, function(index){
        int_text.model_id = this.get_output_cell(index).text.trim();

        this.test.assert(this.cell_element_exists(index,
            '.widget-area .widget-subarea'),
            'Widget subarea exists.');

        this.test.assert(this.cell_element_exists(index, int_text.query),
            'Widget int textbox exists.');

        this.cell_element_function(int_text.index, int_text.query, 'val', ['']);
        this.sendKeys(int_text.query, '1.05');
    });

    this.wait_for_widget(int_text);

    index = this.append_cell('print(int_widget.value)\n');
    this.execute_cell_then(index, function(index){
        this.test.assertEquals(this.get_output_cell(index).text, '1\n',
            'Int textbox value set.');
        this.cell_element_function(int_text.index, int_text.query, 'val', ['']);
        this.sendKeys(int_text.query, '123456789');
    });

    this.wait_for_widget(int_text);

    index = this.append_cell('print(int_widget.value)\n');
    this.execute_cell_then(index, function(index){
        this.test.assertEquals(this.get_output_cell(index).text, '123456789\n',
            'Long int textbox value set (probably triggers throttling).');
        this.cell_element_function(int_text.index, int_text.query, 'val', ['']);
        this.sendKeys(int_text.query, '12hello');
    });

    this.wait_for_widget(int_text);

    index = this.append_cell('print(int_widget.value)\n');
    this.execute_cell_then(index, function(index){
        this.test.assertEquals(this.get_output_cell(index).text, '12\n',
            'Invald int textbox value caught and filtered.');
    });

    index = this.append_cell(
        'from IPython.html import widgets\n' +
        'from IPython.display import display, clear_output\n' +
        'print("Success")');
    this.execute_cell_then(index);

    var slider_query = '.widget-area .widget-subarea .widget-hbox-single .slider';
    var int_text2 = {};
    int_text2.query = '.widget-area .widget-subarea .widget-hbox-single .my-second-num-test-text';
    int_text2.index = this.append_cell(
        'intrange = [widgets.BoundedIntTextWidget(),\n' +
        '    widgets.IntSliderWidget()]\n' +
        '[display(intrange[i]) for i in range(2)]\n' +
        'intrange[0].add_class("my-second-num-test-text")\n' +
        'print(intrange[0].model_id)\n');
    this.execute_cell_then(int_text2.index, function(index){
        int_text2.model_id = this.get_output_cell(index).text.trim();

        this.test.assert(this.cell_element_exists(index,
            '.widget-area .widget-subarea'),
            'Widget subarea exists.');

        this.test.assert(this.cell_element_exists(index, slider_query),
            'Widget slider exists.');

        this.test.assert(this.cell_element_exists(index, int_text2.query),
            'Widget int textbox exists.');
    });

    index = this.append_cell(
        'for widget in intrange:\n' +
        '    widget.max = 50\n' +
        '    widget.min = -50\n' +
        '    widget.value = 25\n' +
        'print("Success")\n');
    this.execute_cell_then(index, function(index){

        this.test.assertEquals(this.get_output_cell(index).text, 'Success\n',
            'Int range properties cell executed with correct output.');

        this.test.assert(this.cell_element_exists(int_text2.index, slider_query),
            'Widget slider exists.');

        this.test.assert(this.cell_element_function(int_text2.index, slider_query,
            'slider', ['value']) == 25,
            'Slider set to Python value.');

        this.test.assert(this.cell_element_function(int_text2.index, int_text2.query,
            'val') == 25, 'Int textbox set to Python value.');

        // Clear the int textbox value and then set it to 1 by emulating
        // keyboard presses.
        this.cell_element_function(int_text2.index, int_text2.query, 'val', ['']);
        this.sendKeys(int_text2.query, '1');
    });

    this.wait_for_widget(int_text2);

    index = this.append_cell('print(intrange[0].value)\n');
    this.execute_cell_then(index, function(index){
        this.test.assertEquals(this.get_output_cell(index).text, '1\n',
            'Int textbox set int range value');

        // Clear the int textbox value and then set it to 120 by emulating
        // keyboard presses.
        this.cell_element_function(int_text2.index, int_text2.query, 'val', ['']);
        this.sendKeys(int_text2.query, '120');
    });

    this.wait_for_widget(int_text2);

    index = this.append_cell('print(intrange[0].value)\n');
    this.execute_cell_then(index, function(index){
        this.test.assertEquals(this.get_output_cell(index).text, '50\n',
            'Int textbox value bound');

        // Clear the int textbox value and then set it to 'hello world' by
        // emulating keyboard presses.  'hello world' should get filtered...
        this.cell_element_function(int_text2.index, int_text2.query, 'val', ['']);
        this.sendKeys(int_text2.query, 'hello world');
    });

    this.wait_for_widget(int_text2);

    index = this.append_cell('print(intrange[0].value)\n');
    this.execute_cell_then(index, function(index){
        this.test.assertEquals(this.get_output_cell(index).text, '50\n',
            'Invalid int textbox characters ignored');
    });
});<commit_msg>Make int widget tests play nicely with slimer<commit_after>// Test widget int class
casper.notebook_test(function () {
    index = this.append_cell(
        'from IPython.html import widgets\n' +
        'from IPython.display import display, clear_output\n' +
        'print("Success")');
    this.execute_cell_then(index);

    var int_text = {}
    int_text.query = '.widget-area .widget-subarea .widget-hbox-single .my-second-int-text';
    int_text.index = this.append_cell(
        'int_widget = widgets.IntTextWidget()\n' +
        'display(int_widget)\n' +
        'int_widget.add_class("my-second-int-text")\n' +
        'print(int_widget.model_id)\n');
    this.execute_cell_then(int_text.index, function(index){
        int_text.model_id = this.get_output_cell(index).text.trim();

        this.test.assert(this.cell_element_exists(index,
            '.widget-area .widget-subarea'),
            'Widget subarea exists.');

        this.test.assert(this.cell_element_exists(index, int_text.query),
            'Widget int textbox exists.');

        this.cell_element_function(int_text.index, int_text.query, 'val', ['']);
        this.sendKeys(int_text.query, '1.05');
    });

    this.wait_for_widget(int_text);

    index = this.append_cell('print(int_widget.value)\n');
    this.execute_cell_then(index, function(index){
        this.test.assertEquals(this.get_output_cell(index).text, '1\n',
            'Int textbox value set.');
        this.cell_element_function(int_text.index, int_text.query, 'val', ['']);
        this.sendKeys(int_text.query, '123456789');
    });

    this.wait_for_widget(int_text);

    index = this.append_cell('print(int_widget.value)\n');
    this.execute_cell_then(index, function(index){
        this.test.assertEquals(this.get_output_cell(index).text, '123456789\n',
            'Long int textbox value set (probably triggers throttling).');
        this.cell_element_function(int_text.index, int_text.query, 'val', ['']);
        this.sendKeys(int_text.query, '12hello');
    });

    this.wait_for_widget(int_text);

    index = this.append_cell('print(int_widget.value)\n');
    this.execute_cell_then(index, function(index){
        this.test.assertEquals(this.get_output_cell(index).text, '12\n',
            'Invald int textbox value caught and filtered.');
    });

    index = this.append_cell(
        'from IPython.html import widgets\n' +
        'from IPython.display import display, clear_output\n' +
        'print("Success")');
    this.execute_cell_then(index);

    var slider_query = '.widget-area .widget-subarea .widget-hbox-single .slider';
    var int_text2 = {};
    int_text2.query = '.widget-area .widget-subarea .widget-hbox-single .my-second-num-test-text';
    int_text2.index = this.append_cell(
        'intrange = [widgets.BoundedIntTextWidget(),\n' +
        '    widgets.IntSliderWidget()]\n' +
        '[display(intrange[i]) for i in range(2)]\n' +
        'intrange[0].add_class("my-second-num-test-text")\n' +
        'print(intrange[0].model_id)\n');
    this.execute_cell_then(int_text2.index, function(index){
        int_text2.model_id = this.get_output_cell(index).text.trim();

        this.test.assert(this.cell_element_exists(index,
            '.widget-area .widget-subarea'),
            'Widget subarea exists.');

        this.test.assert(this.cell_element_exists(index, slider_query),
            'Widget slider exists.');

        this.test.assert(this.cell_element_exists(index, int_text2.query),
            'Widget int textbox exists.');
    });

    index = this.append_cell(
        'for widget in intrange:\n' +
        '    widget.max = 50\n' +
        '    widget.min = -50\n' +
        '    widget.value = 25\n' +
        'print("Success")\n');
    this.execute_cell_then(index, function(index){

        this.test.assertEquals(this.get_output_cell(index).text, 'Success\n',
            'Int range properties cell executed with correct output.');

        this.test.assert(this.cell_element_exists(int_text2.index, slider_query),
            'Widget slider exists.');

        this.test.assert(this.cell_element_function(int_text2.index, slider_query,
            'slider', ['value']) == 25,
            'Slider set to Python value.');

        this.test.assert(this.cell_element_function(int_text2.index, int_text2.query,
            'val') == 25, 'Int textbox set to Python value.');

        // Clear the int textbox value and then set it to 1 by emulating
        // keyboard presses.
        this.evaluate(function(q){
            var textbox = IPython.notebook.element.find(q);
            textbox.val('1');
            textbox.trigger('keyup');
        }, {q: int_text2.query});
    });

    this.wait_for_widget(int_text2);

    index = this.append_cell('print(intrange[0].value)\n');
    this.execute_cell_then(index, function(index){
        this.test.assertEquals(this.get_output_cell(index).text, '1\n',
            'Int textbox set int range value');

        // Clear the int textbox value and then set it to 120 by emulating
        // keyboard presses.
        this.evaluate(function(q){
            var textbox = IPython.notebook.element.find(q);
            textbox.val('120');
            textbox.trigger('keyup');
        }, {q: int_text2.query});
    });

    this.wait_for_widget(int_text2);

    index = this.append_cell('print(intrange[0].value)\n');
    this.execute_cell_then(index, function(index){
        this.test.assertEquals(this.get_output_cell(index).text, '50\n',
            'Int textbox value bound');

        // Clear the int textbox value and then set it to 'hello world' by
        // emulating keyboard presses.  'hello world' should get filtered...
        this.evaluate(function(q){
            var textbox = IPython.notebook.element.find(q);
            textbox.val('hello world');
            textbox.trigger('keyup');
        }, {q: int_text2.query});
    });

    this.wait_for_widget(int_text2);

    index = this.append_cell('print(intrange[0].value)\n');
    this.execute_cell_then(index, function(index){
        this.test.assertEquals(this.get_output_cell(index).text, '50\n',
            'Invalid int textbox characters ignored');
    });
});<|endoftext|>