Example #1
0
 init: function(parent, field, $node) {
     this._super(parent);
     this.field = field;
     this.$node = $node;
     this.options = pyeval.py_eval(this.$node.attr("options") || '{}');
     this.set("value", field.raw_value);
 },
Example #2
0
 var recurse = function(node) {
     if (node.tag === "field" && node.attrs.name == self.view.group_by) {
         options = pyeval.py_eval(node.attrs.options || '{}');
         return;
     }
     _.each(node.children, function(child) {
         recurse(child);
     });
 };
Example #3
0
 _.each(modifiersNames, function (a) {
     if (node.attrs[a]) {
         var v = pyeval.py_eval(node.attrs[a]) ? true: false;
         if (inTreeView && a === 'invisible') {
             modifiers['tree_invisible'] = v;
         } else if (v || !(a in modifiers) || !_.isArray(modifiers[a])) {
             modifiers[a] = v;
         }
     }
 });
Example #4
0
 _.each(modifiersNames, function (a) {
     if (node.attrs[a]) {
         var pyevalContext = window.py.dict.fromJSON(context || {});
         var v = pyeval.py_eval(node.attrs[a], {context: pyevalContext}) ? true: false;
         if (inTreeView && a === 'invisible') {
             modifiers['column_invisible'] = v;
         } else if (v || !(a in modifiers) || !_.isArray(modifiers[a])) {
             modifiers[a] = v;
         }
     }
 });
Example #5
0
    init: function(field_manager, node) {
        this._super(field_manager, node);
        this.name = this.node.attrs.name;
        this.field = this.field_manager.get_field_desc(this.name);
        this.widget = this.node.attrs.widget;
        this.string = this.node.attrs.string || this.field.string || this.name;
        this.options = pyeval.py_eval(this.node.attrs.options || '{}');
        this.set({'value': false});

        this.on("change:value", this, function() {
            this.trigger('changed_value');
            this._check_css_flags();
        });

        this.$translate = $(); // Enterprise compatibility
    },
Example #6
0
    init: function(field_manager, node) {
        this._super(field_manager, node);
        this.name = this.node.attrs.name;
        this.field = this.field_manager.get_field_desc(this.name);
        this.widget = this.node.attrs.widget;
        this.string = this.node.attrs.string || this.field.string || this.name;
        this.options = pyeval.py_eval(this.node.attrs.options || '{}');
        this.set({'value': false});

        this.on("change:value", this, function() {
            this.trigger('changed_value');
            this._check_css_flags();
        });

        this.$translate = (_t.database.multi_lang && this.field.translate) ? $('<button/>', {
            type: 'button',
        }).addClass('o_field_translate fa fa-globe btn btn-link') : $();
    },
Example #7
0
 var recurse = function(node) {
     if (node.tag === "field" && node.attrs && node.attrs.options) {
         var options = pyeval.py_eval(node.attrs.options);
         var states_fields_to_read = _.map(
             options && options.states_legend || {},
             function (value, key, list) { return value; });
         var tooltip_fields_to_read = _.map(
             options && options.group_by_tooltip || {},
             function (value, key, list) { return key; });
         group_by_fields_to_read = _.union(
             group_by_fields_to_read,
             states_fields_to_read,
             tooltip_fields_to_read);
     }
     _.each(node.children, function(child) {
         recurse(child);
     });
 };
Example #8
0
        var handler = function (action) {
            // show effect if button have effect attribute
            // Rainbowman can be displayed from two places : from attribute on a button, or from python.
            // Code below handles the first case i.e 'effect' attribute on button.
            var effect = false;
            if (action_data.effect) {
                effect = pyeval.py_eval(action_data.effect);
            };

            if (action && action.constructor === Object) {
                // filter out context keys that are specific to the current action.
                // Wrong default_* and search_default_* values will no give the expected result
                // Wrong group_by values will simply fail and forbid rendering of the destination view
                var ncontext = new Context(
                    _.object(_.reject(_.pairs(self.env.context), function(pair) {
                      return pair[0].match('^(?:(?:default_|search_default_|show_).+|.+_view_ref|group_by|group_by_no_leaf|active_id|active_ids)$') !== null;
                    }))
                );
                ncontext.add(action_data.context || {});
                ncontext.add({active_model: env.model});
                if (recordID) {
                    ncontext.add({
                        active_id: recordID,
                        active_ids: [recordID],
                    });
                }
                ncontext.add(action.context || {});
                action.context = ncontext;
                // In case effect data is returned from python and also there is rainbow
                // attribute on button, priority is given to button attribute
                action.effect = effect || action.effect;
                return self.do_action(action, {
                    on_close: result_handler,
                });
            } else {
                // If action doesn't return anything, but have effect
                // attribute on button, display rainbowman
                self.do_action({"type":"ir.actions.act_window_close", 'effect': effect});
                return result_handler();
            }
        };
Example #9
0
    _processField: function (viewType, field, attrs) {
        var self = this;
        attrs.Widget = this._getFieldWidgetClass(viewType, field, attrs);

        if (!_.isObject(attrs.options)) { // parent arch could have already been processed (TODO this should not happen)
            attrs.options = attrs.options ? pyeval.py_eval(attrs.options) : {};
        }

        if (attrs.on_change && !field.onChange) {
            field.onChange = "1";
        }

        if (!_.isEmpty(field.views)) {
            // process the inner fields_view as well to find the fields they use.
            // register those fields' description directly on the view.
            // for those inner views, the list of all fields isn't necessary, so
            // basically the field_names will be the keys of the fields obj.
            // don't use _ to iterate on fields in case there is a 'length' field,
            // as _ doesn't behave correctly when there is a length key in the object
            attrs.views = {};
            _.each(field.views, function (innerFieldsView, viewType) {
                viewType = viewType === 'tree' ? 'list' : viewType;
                innerFieldsView.type = viewType;
                attrs.views[viewType] = self._processFieldsView(_.extend({}, innerFieldsView));
            });
            delete field.views;
        }

        if (field.type === 'one2many' || field.type === 'many2many') {
            if (attrs.Widget.prototype.useSubview) {
                if (!attrs.views) {
                    attrs.views = {};
                }
                var mode = attrs.mode;
                if (!mode) {
                    if (attrs.views.tree && attrs.views.kanban) {
                        mode = 'tree';
                    } else if (!attrs.views.tree && attrs.views.kanban) {
                        mode = 'kanban';
                    } else {
                        mode = 'tree,kanban';
                    }
                }
                if (mode.indexOf(',') !== -1) {
                    mode = config.device.size_class !== config.device.SIZES.XS ? 'tree' : 'kanban';
                }
                if (mode === 'tree') {
                    mode = 'list';
                    if (!attrs.views.list && attrs.views.tree) {
                        attrs.views.list = attrs.views.tree;
                    }
                }
                attrs.mode = mode;
            }
            if (attrs.Widget.prototype.fetchSubFields) {
                attrs.relatedFields = {
                    display_name: {type: 'char'},
                    //id: {type: 'integer'},
                };
                attrs.fieldsInfo = {};
                attrs.fieldsInfo.default = {display_name: {}, id: {}};
                attrs.viewType = 'default';
                if (attrs.color || 'color') {
                    attrs.relatedFields[attrs.color || 'color'] = {type: 'integer'};
                    attrs.fieldsInfo.default.color = {};
                }
            }
        }
        return attrs;
    },
Example #10
0
    _processField: function (viewType, field, attrs) {
        var self = this;
        attrs.Widget = this._getFieldWidgetClass(viewType, field, attrs);

        if (!_.isObject(attrs.options)) { // parent arch could have already been processed (TODO this should not happen)
            attrs.options = attrs.options ? pyeval.py_eval(attrs.options) : {};
        }

        if (attrs.on_change && !field.onChange) {
            field.onChange = "1";
        }

        // the relational data of invisible relational fields should not be
        // fetched (e.g. name_gets of invisible many2ones), at least those that
        // are always invisible.
        // the invisible attribute of a field is supposed to be static ("1" in
        // general), but not totally as it may use keys of the context
        // ("context.get('some_key')"). It is evaluated server-side, and the
        // result is put inside the modifiers as a value of the '(tree_)invisible'
        // key, and the raw value is left in the invisible attribute (it is used
        // in debug mode for informational purposes).
        // this should change, for instance the server might set the evaluated
        // value in invisible, which could then be seen as static by the client,
        // and add another key in debug mode containing the raw value.
        // for now, we do an hack to detect if the value is static and retrieve
        // it from the modifiers,
        if (attrs.invisible && attrs.modifiers.match('"(?:tree_)?invisible": ?true')) {
            attrs.__no_fetch = true;
        }

        if (!_.isEmpty(field.views)) {
            // process the inner fields_view as well to find the fields they use.
            // register those fields' description directly on the view.
            // for those inner views, the list of all fields isn't necessary, so
            // basically the field_names will be the keys of the fields obj.
            // don't use _ to iterate on fields in case there is a 'length' field,
            // as _ doesn't behave correctly when there is a length key in the object
            attrs.views = {};
            _.each(field.views, function (innerFieldsView, viewType) {
                viewType = viewType === 'tree' ? 'list' : viewType;
                innerFieldsView.type = viewType;
                attrs.views[viewType] = self._processFieldsView(_.extend({}, innerFieldsView));

                // default_order is like:
                //   'name,id desc'
                // but we need it like:
                //   [{name: 'id', asc: false}, {name: 'name', asc: true}]
                var defaultOrder = innerFieldsView.arch.attrs.default_order;
                if (defaultOrder) {
                    attrs.orderedBy = _.map(defaultOrder.split(','), function (order) {
                        order = order.trim().split(' ');
                        return {name: order[0], asc: order[1] !== 'desc'};
                    });
                }
            });
            delete field.views;
        }

        if (field.type === 'one2many' || field.type === 'many2many') {
            if (attrs.Widget.prototype.useSubview) {
                if (!attrs.views) {
                    attrs.views = {};
                }
                var mode = attrs.mode;
                if (!mode) {
                    if (attrs.views.tree && attrs.views.kanban) {
                        mode = 'tree';
                    } else if (!attrs.views.tree && attrs.views.kanban) {
                        mode = 'kanban';
                    } else {
                        mode = 'tree,kanban';
                    }
                }
                if (mode.indexOf(',') !== -1) {
                    mode = config.device.size_class !== config.device.SIZES.XS ? 'tree' : 'kanban';
                }
                if (mode === 'tree') {
                    mode = 'list';
                    if (!attrs.views.list && attrs.views.tree) {
                        attrs.views.list = attrs.views.tree;
                    }
                }
                attrs.mode = mode;
            }
            if (attrs.Widget.prototype.fieldsToFetch) {
                attrs.viewType = 'default';
                attrs.relatedFields = attrs.Widget.prototype.fieldsToFetch;
                attrs.fieldsInfo = {
                    default: _.mapObject(attrs.Widget.prototype.fieldsToFetch, function () {
                        return {};
                    }),
                };
                if (attrs.options.color_field) {
                    // used by m2m tags
                    attrs.relatedFields[attrs.options.color_field] = { type: 'integer' };
                    attrs.fieldsInfo.default[attrs.options.color_field] = {};
                }
            }
        }
        return attrs;
    },
Example #11
0
        this._traverse(arch, function (node) {
            if (typeof node === "string") {
                return false;
            }
            var modifiers = {};

            var isField = (node.tag === 'field');

            if (isField) {
                fieldNodes[node.attrs.name] = node;

                // 'transfer_field_to_modifiers' simulation
                var field = fields[node.attrs.name];

                var defaultValues = {};
                var stateExceptions = {};
                _.each(modifiersNames, function (attr) {
                    stateExceptions[attr] = [];
                    defaultValues[attr] = !!field[attr];
                });
                _.each(field['states'] || {}, function (modifs, state) {
                    _.each(modifs, function (modif) {
                        if (defaultValues[modif[0]] !== modif[1]) {
                            stateExceptions[modif[0]].append(state);
                        }
                    });
                });
                _.each(defaultValues, function (defaultValue, attr) {
                    if (stateExceptions[attr].length) {
                        modifiers[attr] = [("state", defaultValue ? "not in" : "in", stateExceptions[attr])];
                    } else {
                        modifiers[attr] = defaultValue;
                    }
                });
            }

            // 'transfer_node_to_modifiers' simulation
            if (node.attrs.attrs) {
                var attrs = pyeval.py_eval(node.attrs.attrs);
                _.extend(modifiers, attrs);
                delete node.attrs.attrs;
            }
            if (node.attrs.states) {
                if (!modifiers.invisible) {
                    modifiers.invisible = [];
                }
                modifiers.invisible.push(["state", "not in", node.attrs.states.split(",")]);
            }
            _.each(modifiersNames, function (a) {
                if (node.attrs[a]) {
                    var v = pyeval.py_eval(node.attrs[a]) ? true: false;
                    if (inTreeView && a === 'invisible') {
                        modifiers['tree_invisible'] = v;
                    } else if (v || !(a in modifiers) || !_.isArray(modifiers[a])) {
                        modifiers[a] = v;
                    }
                }
            });

            // 'transfer_modifiers_to_node' simulation
            _.each(modifiersNames, function (a) {
                if (a in modifiers && (!!modifiers[a] === false || (_.isArray(modifiers[a]) && !modifiers[a].length))) {
                    delete modifiers[a];
                }
            });
            node.attrs.modifiers = JSON.stringify(modifiers);

            return !isField;
        });
Example #12
0
        this._traverse(doc, function (node) {
            if (node.nodeType === Node.TEXT_NODE) {
                return false;
            }
            var modifiers = {};

            var isField = (node.tagName === 'field');

            if (isField) {
                var fieldName = node.getAttribute('name');
                fieldNodes[fieldName] = node;

                // 'transfer_field_to_modifiers' simulation
                var field = fields[fieldName];

                if (!field) {
                    throw new Error("Field " + fieldName + " does not exist");
                }
                var defaultValues = {};
                var stateExceptions = {};
                _.each(modifiersNames, function (attr) {
                    stateExceptions[attr] = [];
                    defaultValues[attr] = !!field[attr];
                });
                _.each(field.states || {}, function (modifs, state) {
                    _.each(modifs, function (modif) {
                        if (defaultValues[modif[0]] !== modif[1]) {
                            stateExceptions[modif[0]].append(state);
                        }
                    });
                });
                _.each(defaultValues, function (defaultValue, attr) {
                    if (stateExceptions[attr].length) {
                        modifiers[attr] = [("state", defaultValue ? "not in" : "in", stateExceptions[attr])];
                    } else {
                        modifiers[attr] = defaultValue;
                    }
                });
            }

            // 'transfer_node_to_modifiers' simulation
            var attrs = node.getAttribute('attrs');
            if (attrs) {
                attrs = pyeval.py_eval(attrs);
                _.extend(modifiers, attrs);
                node.removeAttribute('attrs');
            }

            var states = node.getAttribute('states');
            if (states) {
                if (!modifiers.invisible) {
                    modifiers.invisible = [];
                }
                modifiers.invisible.push(["state", "not in", states.split(",")]);
            }
            _.each(modifiersNames, function (a) {
                var mod = node.getAttribute(a);
                if (mod) {
                    var pyevalContext = window.py.dict.fromJSON(context || {});
                    var v = pyeval.py_eval(mod, {context: pyevalContext}) ? true: false;
                    if (inTreeView && a === 'invisible') {
                        modifiers.column_invisible = v;
                    } else if (v || !(a in modifiers) || !_.isArray(modifiers[a])) {
                        modifiers[a] = v;
                    }
                }
            });

            _.each(modifiersNames, function (a) {
                if (a in modifiers && (!!modifiers[a] === false || (_.isArray(modifiers[a]) && !modifiers[a].length))) {
                    delete modifiers[a];
                }
            });

            if (Object.keys(modifiers).length) {
                node.setAttribute('modifiers', JSON.stringify(modifiers));
            }

            return !isField;
        });