<commit_before>openerp.web_kanban = function (instance) {

var _t = instance.web._t,
   _lt = instance.web._lt;
var QWeb = instance.web.qweb;
instance.web.views.add('kanban', 'instance.web_kanban.KanbanView');

instance.web_kanban.KanbanView = instance.web.View.extend({
    template: "KanbanView",
    display_name: _lt('Kanban'),
    default_nr_columns: 1,
    view_type: "kanban",
    quick_create_class: "instance.web_kanban.QuickCreate",
    number_of_color_schemes: 10,
    init: function (parent, dataset, view_id, options) {
        this._super(parent, dataset, view_id, options);
        _.defaults(this.options, {
            "quick_creatable": true,
            "creatable": true,
            "create_text": undefined,
            "read_only_mode": false,
            "confirm_on_delete": true,
        });
        this.fields_view = {};
        this.fields_keys = [];
        this.group_by = null;
        this.group_by_field = {};
        this.grouped_by_m2o = false;
        this.state = {
            groups : {},
            records : {}
        };
        this.groups = [];
        this.aggregates = {};
        this.group_operators = ['avg', 'max', 'min', 'sum', 'count'];
        this.qweb = new QWeb2.Engine();
        this.qweb.debug = instance.session.debug;
        this.qweb.default_dict = _.clone(QWeb.default_dict);
        this.has_been_loaded = $.Deferred();
        this.search_domain = this.search_context = this.search_group_by = null;
        this.currently_dragging = {};
        this.limit = options.limit || 40;
        this.add_group_mutex = new $.Mutex();
    },
    start: function() {
        var self = this;
        this._super.apply(this, arguments);
        this.$el.on('click', '.oe_kanban_dummy_cell', function() {
            if (self.$buttons) {
                self.$buttons.find('.oe_kanban_add_column').effect('bounce', {distance: 18, times: 5}, 150);
            }
        });
    },
    destroy: function() {
        this._super.apply(this, arguments);
        $('html').off('click.kanban');
    },
    on_loaded: function(data) {
        this.fields_view = data;
        this.$el.addClass(this.fields_view.arch.attrs['class']);
        this.$buttons = $(QWeb.render("KanbanView.buttons", {'widget': this}));
        if (this.options.$buttons) {
            this.$buttons.appendTo(this.options.$buttons);
        } else {
            this.$el.find('.oe_kanban_buttons').replaceWith(this.$buttons);
        }
        this.$buttons
            .on('click', 'button.oe_kanban_button_new', this.do_add_record)
            .on('click', '.oe_kanban_add_column', this.do_add_group);
        this.$groups = this.$el.find('.oe_kanban_groups tr');
        this.fields_keys = _.keys(this.fields_view.fields);
        this.add_qweb_template();
        this.has_been_loaded.resolve();
        this._super.apply(this, arguments);
        return $.when();
    },
    _is_quick_create_enabled: function() {
        if (!this.options.quick_creatable || !this.is_action_enabled('create'))
            return false;
        if (this.fields_view.arch.attrs.quick_create !== undefined)
            return JSON.parse(this.fields_view.arch.attrs.quick_create);
        return !! this.group_by;
    },
    is_action_enabled: function(action) {
        if (action === 'create' && !this.options.creatable)
            return false;
        return this._super(action);
    },
    /*  add_qweb_template
    *   select the nodes into the xml and send to extract_aggregates the nodes with TagName="field"
    */
    add_qweb_template: function() {
        for (var i=0, ii=this.fields_view.arch.children.length; i < ii; i++) {
            var child = this.fields_view.arch.children[i];
            if (child.tag === "templates") {
                this.transform_qweb_template(child);
                this.qweb.add_template(instance.web.json_node_to_xml(child));
                break;
            } else if (child.tag === 'field') {
                this.extract_aggregates(child);
            }
        }
    },
    /*  extract_aggregates
    *   extract the agggregates from the nodes (TagName="field")
    */
    extract_aggregates: function(node) {
        for (var j = 0, jj = this.group_operators.length; j < jj;  j++) {
            if (node.attrs[this.group_operators[j]]) {
                this.aggregates[node.attrs.name] = node.attrs[this.group_operators[j]];
                break;
            }
        }
    },
    transform_qweb_template: function(node) {
        var qweb_add_if = function(node, condition) {
            if (node.attrs[QWeb.prefix + '-if']) {
                condition = _.str.sprintf("(%s) and (%s)", node.attrs[QWeb.prefix + '-if'], condition);
            }
            node.attrs[QWeb.prefix + '-if'] = condition;
        };
        // Process modifiers
        if (node.tag && node.attrs.modifiers) {
            var modifiers = JSON.parse(node.attrs.modifiers || '{}');
            if (modifiers.invisible) {
                qweb_add_if(node, _.str.sprintf("!kanban_compute_domain(%s)", JSON.stringify(modifiers.invisible)));
            }
        }
        switch (node.tag) {
            case 'field':
                if(this.fields_view.fields[ node.attrs['name'] ].type == 'many2many'){
                    node.tag =  'div';
                    node.attrs['class'] = 'oe_form_field oe_tags';
                    node.attrs['model'] = this.fields_view.fields[node.attrs['name']].relation;
                    node.attrs['t-att-data'] = 'record.' + node.attrs['name'] + '.raw_value';
                }else {
                    node.tag = QWeb.prefix;
                    node.attrs[QWeb.prefix + '-esc'] = 'record.' + node.attrs['name'] + '.value';
                }
                break;
            case 'button':
            case 'a':
                var type = node.attrs.type || '';
                if (_.indexOf('action,object,edit,open,delete'.split(','), type) !== -1) {
                    _.each(node.attrs, function(v, k) {
                        if (_.indexOf('icon,type,name,args,string,context,states,kanban_states'.split(','), k) != -1) {
                            node.attrs['data-' + k] = v;
                            delete(node.attrs[k]);
                        }
                    });
                    if (node.attrs['data-string']) {
                        node.attrs.title = node.attrs['data-string'];
                    }
                    if (node.attrs['data-icon']) {
                        node.children = [{
                            tag: 'img',
                            attrs: {
                                src: instance.session.prefix + '/web/static/src/img/icons/' + node.attrs['data-icon'] + '.png',
                                width: '16',
                                height: '16'
                            }
                        }];
                    }
                    if (node.tag == 'a') {
                        node.attrs.href = '#';
                    } else {
                        node.attrs.type = 'button';
                    }
                    node.attrs['class'] = (node.attrs['class'] || '') + ' oe_kanban_action oe_kanban_action_' + node.tag;
                }
                break;
        }
        if (node.children) {
            for (var i = 0, ii = node.children.length; i < ii; i++) {
                this.transform_qweb_template(node.children[i]);
            }
        }
    },
    do_add_record: function() {
        this.dataset.index = null;
        this.do_switch_view('form');
    },
    do_add_group: function() {
        var self = this;
        self.do_action({
            name: _t("Add column"),
            res_model: self.group_by_field.relation,
            views: [[false, 'form']],
            type: 'ir.actions.act_window',
            target: "new",
            flags: {
                action_buttons: true,
            }
        });
        var am = instance.webclient.action_manager;
        var form = am.dialog_widget.views.form.controller;
        form.on("on_button_cancel", am.dialog, am.dialog.close);
        form.on('record_created', self, function(r) {
            (new instance.web.DataSet(self, self.group_by_field.relation)).name_get([r]).then(function(new_record) {
                am.dialog.close();
                var domain = self.dataset.domain.slice(0);
                domain.push([self.group_by, '=', new_record[0][0]]);
                var dataset = new instance.web.DataSetSearch(self, self.dataset.model, self.dataset.get_context(), domain);
                var datagroup = {
                    get: function(key) {
                        return this[key];
                    },
                    value: new_record[0],
                    length: 0,
                    aggregates: {},
                };
                var new_group = new instance.web_kanban.KanbanGroup(self, [], datagroup, dataset);
                self.do_add_groups([new_group]).then(function() {
                    $(window).scrollTo(self.groups.slice(-1)[0].$el, { axis: 'x' });
                });
            });
        });
    },
    do_search: function(domain, context, group_by) {
        var self = this;
        this.$el.find('.oe_view_nocontent').remove();
        this.search_domain = domain;
        this.search_context = context;
        this.search_group_by = group_by;
        $.when(this.has_been_loaded).then(function() {
            self.group_by = group_by.length ? group_by[0] : self.fields_view.arch.attrs.default_group_by;
            self.group_by_field = self.fields_view.fields[self.group_by] || {};
            self.grouped_by_m2o = (self.group_by_field.type === 'many2one');
            self.$buttons.find('.oe_alternative').toggle(self.grouped_by_m2o);
            self.$el.toggleClass('oe_kanban_grouped_by_m2o', self.grouped_by_m2o);
            var grouping = new instance.web.Model(self.dataset.model, context, domain).query().group_by(self.group_by);
            $.when(grouping).then(function(groups) {
                if (groups) {
                    self.do_process_groups(groups);
                } else {
                    self.do_process_dataset();
                }
            });
        });
    },
    do_process_groups: function(groups) {
        var self = this;
        this.$el.removeClass('oe_kanban_ungrouped').addClass('oe_kanban_grouped');
        this.add_group_mutex.exec(function() {
            self.dataset.ids = [];
            var remaining = groups.length - 1,
                groups_array = [];
            return $.when.apply(null, _.map(groups, function (group, index) {
                var dataset = new instance.web.DataSetSearch(self, self.dataset.model,
                    new instance.web.CompoundContext(self.dataset.get_context(), group.model.context()), group.model.domain());
                return dataset.read_slice(self.fields_keys.concat(['__last_update']), { 'limit': self.limit })
                    .pipe(function(records) {
                        self.dataset.ids.push.apply(self.dataset.ids, dataset.ids);
                        groups_array[index] = new instance.web_kanban.KanbanGroup(self, records, group, dataset);
                        if (!remaining--) {
                            self.dataset.index = self.dataset.size() ? 0 : null;
                            return self.do_add_groups(groups_array);
                        }
                });
            }));
        });
        self.do_clear_groups();
    },
    do_process_dataset: function() {
        var self = this;
        this.$el.removeClass('oe_kanban_grouped').addClass('oe_kanban_ungrouped');
        this.add_group_mutex.exec(function() {
            var def = $.Deferred();
            self.dataset.read_slice(self.fields_keys.concat(['__last_update']), { 'limit': self.limit }).then(function(records) {
                var kgroup = new instance.web_kanban.KanbanGroup(self, records, null, self.dataset);
                self.do_add_groups([kgroup]).then(function() {
                    if (_.isEmpty(records)) {
                        self.no_result();
                    }
                    def.resolve();
                });
            }).then(null, function() {
                def.reject();
            });
            return def;
        });
        self.do_clear_groups();
    },
    do_reload: function() {
        this.do_search(this.search_domain, this.search_context, this.search_group_by);
    },
    do_clear_groups: function() {
        var groups = this.groups.slice(0);
        this.groups = [];
        _.each(groups, function(group) {
            group.destroy();
        });
    },
    do_add_groups: function(groups) {
        var self = this;
        var $parent = this.$el.parent();
        this.$el.detach();
        _.each(groups, function(group) {
            self.groups[group.undefined_title ? 'unshift' : 'push'](group);
        });
        var $last_td = self.$el.find('.oe_kanban_groups_headers td:last');
        var groups_started = _.map(this.groups, function(group) {
            if (!group.is_started) {
                return group.insertBefore($last_td);<commit_msg>[FIX] Race condition bug inserted in Revision: 3245 revid:<EMAIL>-20121016122951-hwm80wzmhnm8tlj5<commit_after>openerp.web_kanban = function (instance) {

var _t = instance.web._t,
   _lt = instance.web._lt;
var QWeb = instance.web.qweb;
instance.web.views.add('kanban', 'instance.web_kanban.KanbanView');

instance.web_kanban.KanbanView = instance.web.View.extend({
    template: "KanbanView",
    display_name: _lt('Kanban'),
    default_nr_columns: 1,
    view_type: "kanban",
    quick_create_class: "instance.web_kanban.QuickCreate",
    number_of_color_schemes: 10,
    init: function (parent, dataset, view_id, options) {
        this._super(parent, dataset, view_id, options);
        _.defaults(this.options, {
            "quick_creatable": true,
            "creatable": true,
            "create_text": undefined,
            "read_only_mode": false,
            "confirm_on_delete": true,
        });
        this.fields_view = {};
        this.fields_keys = [];
        this.group_by = null;
        this.group_by_field = {};
        this.grouped_by_m2o = false;
        this.state = {
            groups : {},
            records : {}
        };
        this.groups = [];
        this.aggregates = {};
        this.group_operators = ['avg', 'max', 'min', 'sum', 'count'];
        this.qweb = new QWeb2.Engine();
        this.qweb.debug = instance.session.debug;
        this.qweb.default_dict = _.clone(QWeb.default_dict);
        this.has_been_loaded = $.Deferred();
        this.search_domain = this.search_context = this.search_group_by = null;
        this.currently_dragging = {};
        this.limit = options.limit || 40;
        this.add_group_mutex = new $.Mutex();
    },
    start: function() {
        var self = this;
        this._super.apply(this, arguments);
        this.$el.on('click', '.oe_kanban_dummy_cell', function() {
            if (self.$buttons) {
                self.$buttons.find('.oe_kanban_add_column').effect('bounce', {distance: 18, times: 5}, 150);
            }
        });
    },
    destroy: function() {
        this._super.apply(this, arguments);
        $('html').off('click.kanban');
    },
    on_loaded: function(data) {
        this.fields_view = data;
        this.$el.addClass(this.fields_view.arch.attrs['class']);
        this.$buttons = $(QWeb.render("KanbanView.buttons", {'widget': this}));
        if (this.options.$buttons) {
            this.$buttons.appendTo(this.options.$buttons);
        } else {
            this.$el.find('.oe_kanban_buttons').replaceWith(this.$buttons);
        }
        this.$buttons
            .on('click', 'button.oe_kanban_button_new', this.do_add_record)
            .on('click', '.oe_kanban_add_column', this.do_add_group);
        this.$groups = this.$el.find('.oe_kanban_groups tr');
        this.fields_keys = _.keys(this.fields_view.fields);
        this.add_qweb_template();
        this.has_been_loaded.resolve();
        this._super.apply(this, arguments);
        return $.when();
    },
    _is_quick_create_enabled: function() {
        if (!this.options.quick_creatable || !this.is_action_enabled('create'))
            return false;
        if (this.fields_view.arch.attrs.quick_create !== undefined)
            return JSON.parse(this.fields_view.arch.attrs.quick_create);
        return !! this.group_by;
    },
    is_action_enabled: function(action) {
        if (action === 'create' && !this.options.creatable)
            return false;
        return this._super(action);
    },
    /*  add_qweb_template
    *   select the nodes into the xml and send to extract_aggregates the nodes with TagName="field"
    */
    add_qweb_template: function() {
        for (var i=0, ii=this.fields_view.arch.children.length; i < ii; i++) {
            var child = this.fields_view.arch.children[i];
            if (child.tag === "templates") {
                this.transform_qweb_template(child);
                this.qweb.add_template(instance.web.json_node_to_xml(child));
                break;
            } else if (child.tag === 'field') {
                this.extract_aggregates(child);
            }
        }
    },
    /*  extract_aggregates
    *   extract the agggregates from the nodes (TagName="field")
    */
    extract_aggregates: function(node) {
        for (var j = 0, jj = this.group_operators.length; j < jj;  j++) {
            if (node.attrs[this.group_operators[j]]) {
                this.aggregates[node.attrs.name] = node.attrs[this.group_operators[j]];
                break;
            }
        }
    },
    transform_qweb_template: function(node) {
        var qweb_add_if = function(node, condition) {
            if (node.attrs[QWeb.prefix + '-if']) {
                condition = _.str.sprintf("(%s) and (%s)", node.attrs[QWeb.prefix + '-if'], condition);
            }
            node.attrs[QWeb.prefix + '-if'] = condition;
        };
        // Process modifiers
        if (node.tag && node.attrs.modifiers) {
            var modifiers = JSON.parse(node.attrs.modifiers || '{}');
            if (modifiers.invisible) {
                qweb_add_if(node, _.str.sprintf("!kanban_compute_domain(%s)", JSON.stringify(modifiers.invisible)));
            }
        }
        switch (node.tag) {
            case 'field':
                if(this.fields_view.fields[ node.attrs['name'] ].type == 'many2many'){
                    node.tag =  'div';
                    node.attrs['class'] = 'oe_form_field oe_tags';
                    node.attrs['model'] = this.fields_view.fields[node.attrs['name']].relation;
                    node.attrs['t-att-data'] = 'record.' + node.attrs['name'] + '.raw_value';
                }else {
                    node.tag = QWeb.prefix;
                    node.attrs[QWeb.prefix + '-esc'] = 'record.' + node.attrs['name'] + '.value';
                }
                break;
            case 'button':
            case 'a':
                var type = node.attrs.type || '';
                if (_.indexOf('action,object,edit,open,delete'.split(','), type) !== -1) {
                    _.each(node.attrs, function(v, k) {
                        if (_.indexOf('icon,type,name,args,string,context,states,kanban_states'.split(','), k) != -1) {
                            node.attrs['data-' + k] = v;
                            delete(node.attrs[k]);
                        }
                    });
                    if (node.attrs['data-string']) {
                        node.attrs.title = node.attrs['data-string'];
                    }
                    if (node.attrs['data-icon']) {
                        node.children = [{
                            tag: 'img',
                            attrs: {
                                src: instance.session.prefix + '/web/static/src/img/icons/' + node.attrs['data-icon'] + '.png',
                                width: '16',
                                height: '16'
                            }
                        }];
                    }
                    if (node.tag == 'a') {
                        node.attrs.href = '#';
                    } else {
                        node.attrs.type = 'button';
                    }
                    node.attrs['class'] = (node.attrs['class'] || '') + ' oe_kanban_action oe_kanban_action_' + node.tag;
                }
                break;
        }
        if (node.children) {
            for (var i = 0, ii = node.children.length; i < ii; i++) {
                this.transform_qweb_template(node.children[i]);
            }
        }
    },
    do_add_record: function() {
        this.dataset.index = null;
        this.do_switch_view('form');
    },
    do_add_group: function() {
        var self = this;
        self.do_action({
            name: _t("Add column"),
            res_model: self.group_by_field.relation,
            views: [[false, 'form']],
            type: 'ir.actions.act_window',
            target: "new",
            flags: {
                action_buttons: true,
            }
        });
        var am = instance.webclient.action_manager;
        var form = am.dialog_widget.views.form.controller;
        form.on("on_button_cancel", am.dialog, am.dialog.close);
        form.on('record_created', self, function(r) {
            (new instance.web.DataSet(self, self.group_by_field.relation)).name_get([r]).then(function(new_record) {
                am.dialog.close();
                var domain = self.dataset.domain.slice(0);
                domain.push([self.group_by, '=', new_record[0][0]]);
                var dataset = new instance.web.DataSetSearch(self, self.dataset.model, self.dataset.get_context(), domain);
                var datagroup = {
                    get: function(key) {
                        return this[key];
                    },
                    value: new_record[0],
                    length: 0,
                    aggregates: {},
                };
                var new_group = new instance.web_kanban.KanbanGroup(self, [], datagroup, dataset);
                self.do_add_groups([new_group]).then(function() {
                    $(window).scrollTo(self.groups.slice(-1)[0].$el, { axis: 'x' });
                });
            });
        });
    },
    do_search: function(domain, context, group_by) {
        var self = this;
        this.$el.find('.oe_view_nocontent').remove();
        this.search_domain = domain;
        this.search_context = context;
        this.search_group_by = group_by;
        $.when(this.has_been_loaded).then(function() {
            self.group_by = group_by.length ? group_by[0] : self.fields_view.arch.attrs.default_group_by;
            self.group_by_field = self.fields_view.fields[self.group_by] || {};
            self.grouped_by_m2o = (self.group_by_field.type === 'many2one');
            self.$buttons.find('.oe_alternative').toggle(self.grouped_by_m2o);
            self.$el.toggleClass('oe_kanban_grouped_by_m2o', self.grouped_by_m2o);
            var grouping = new instance.web.Model(self.dataset.model, context, domain).query().group_by(self.group_by);
            $.when(grouping).then(function(groups) {
                if (groups) {
                    self.do_process_groups(groups);
                } else {
                    self.do_process_dataset();
                }
            });
        });
    },
    do_process_groups: function(groups) {
        var self = this;
        this.$el.removeClass('oe_kanban_ungrouped').addClass('oe_kanban_grouped');
        this.add_group_mutex.exec(function() {
            self.dataset.ids = [];
            var remaining = groups.length - 1,
                groups_array = [];
            return $.when.apply(null, _.map(groups, function (group, index) {
                self.do_clear_groups();
                var dataset = new instance.web.DataSetSearch(self, self.dataset.model,
                    new instance.web.CompoundContext(self.dataset.get_context(), group.model.context()), group.model.domain());
                return dataset.read_slice(self.fields_keys.concat(['__last_update']), { 'limit': self.limit })
                    .pipe(function(records) {
                        self.dataset.ids.push.apply(self.dataset.ids, dataset.ids);
                        groups_array[index] = new instance.web_kanban.KanbanGroup(self, records, group, dataset);
                        if (!remaining--) {
                            self.dataset.index = self.dataset.size() ? 0 : null;
                            return self.do_add_groups(groups_array);
                        }
                });
            }));
        });
    },
    do_process_dataset: function() {
        var self = this;
        this.$el.removeClass('oe_kanban_grouped').addClass('oe_kanban_ungrouped');
        this.add_group_mutex.exec(function() {
            var def = $.Deferred();
            self.dataset.read_slice(self.fields_keys.concat(['__last_update']), { 'limit': self.limit }).then(function(records) {
                self.do_clear_groups();
                var kgroup = new instance.web_kanban.KanbanGroup(self, records, null, self.dataset);
                self.do_add_groups([kgroup]).then(function() {
                    if (_.isEmpty(records)) {
                        self.no_result();
                    }
                    def.resolve();
                });
            }).then(null, function() {
                def.reject();
            });
            return def;
        });
    },
    do_reload: function() {
        this.do_search(this.search_domain, this.search_context, this.search_group_by);
    },
    do_clear_groups: function() {
        var groups = this.groups.slice(0);
        this.groups = [];
        _.each(groups, function(group) {
            group.destroy();
        });
    },
    do_add_groups: function(groups) {
        var self = this;
        var $parent = this.$el.parent();
        this.$el.detach();
        _.each(groups, function(group) {
            self.groups[group.undefined_title ? 'unshift' : 'push'](group);
        });
        var $last_td = self.$el.find('.oe_kanban_groups_headers td:last');
        var groups_started = _.map(this.groups, function(group) {
            if (!group.is_started) {
                return group.insertBefore($last_td);
{'fraction_non_alphanumeric': 0.1412583182093164, 'fraction_numerical': 0.003781004234724743, 'mean_word_length': 1.7213705113694824, 'pattern_counts': {'":': 10, '<': 10, '<?xml version=': 0, '>': 4, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 4}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2876788', 'n_tokens_mistral': 7805, 'n_tokens_neox': 7562, 'n_words': 1185}