[14.0][MIG] bi_view_editor

pre-commit
pull/730/head
Andrea 2020-10-20 09:07:29 +02:00 committed by ilo
parent b5f53e2cc9
commit 6f089afa35
13 changed files with 129 additions and 125 deletions

View File

@ -1,4 +1,4 @@
# Copyright 2015-2019 Onestein (<https://www.onestein.eu>) # Copyright 2015-2020 Onestein (<https://www.onestein.eu>)
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
{ {
@ -8,8 +8,8 @@
"author": "Onestein,Odoo Community Association (OCA)", "author": "Onestein,Odoo Community Association (OCA)",
"license": "AGPL-3", "license": "AGPL-3",
"website": "https://github.com/OCA/reporting-engine", "website": "https://github.com/OCA/reporting-engine",
"category": "Reporting", "category": "Productivity",
"version": "13.0.1.0.0", "version": "14.0.1.0.0",
"development_status": "Beta", "development_status": "Beta",
"depends": ["web"], "depends": ["web"],
"data": [ "data": [

View File

@ -1,4 +1,4 @@
# Copyright 2015-2019 Onestein (<https://www.onestein.eu>) # Copyright 2015-2020 Onestein (<https://www.onestein.eu>)
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
import base64 import base64
@ -320,7 +320,11 @@ class BveView(models.Model):
try: try:
with self.env.cr.savepoint(): with self.env.cr.savepoint():
self.env.cr.execute( self.env.cr.execute(
"CREATE or REPLACE VIEW %s as (%s)", (AsIs(view_name), AsIs(query),) "CREATE or REPLACE VIEW %s as (%s)",
(
AsIs(view_name),
AsIs(query),
),
) )
except Exception as e: except Exception as e:
raise UserError( raise UserError(
@ -541,7 +545,7 @@ class BveView(models.Model):
self.env["ir.model"].sudo().search([("model", "=", self.model_name)]) self.env["ir.model"].sudo().search([("model", "=", self.model_name)])
) )
if models_to_delete: if models_to_delete:
models_to_delete.unlink() models_to_delete.with_context(_force_unlink=True).unlink()
table_name = self.model_name.replace(".", "_") table_name = self.model_name.replace(".", "_")
tools.drop_view_if_exists(self.env.cr, table_name) tools.drop_view_if_exists(self.env.cr, table_name)

View File

@ -44,20 +44,29 @@ class BveViewLine(models.Model):
@api.constrains("row", "column", "measure") @api.constrains("row", "column", "measure")
def _constrains_options_check(self): def _constrains_options_check(self):
measure_types = ["float", "integer", "monetary"] measure_types = ["float", "integer", "monetary"]
lines = self.filtered(lambda l: l.join_model_id or l.ttype in measure_types) for line in self.filtered(lambda l: l.row or l.column):
if lines.filtered(lambda l: l.row or l.column): if line.join_model_id or line.ttype in measure_types:
err_msg = _("This field cannot be a row or a column.") err_msg = _("This field cannot be a row or a column.")
raise ValidationError(err_msg) raise ValidationError(err_msg)
if lines.filtered(lambda l: l.measure): for line in self.filtered(lambda l: l.measure):
err_msg = _("This field cannot be a measure.") if line.join_model_id or line.ttype not in measure_types:
raise ValidationError(err_msg) err_msg = _("This field cannot be a measure.")
raise ValidationError(err_msg)
@api.constrains("table_alias", "field_id") @api.constrains("table_alias", "field_id")
def _constrains_unique_fields_check(self): def _constrains_unique_fields_check(self):
seen = set() seen = set()
for line in self.mapped("bve_view_id.field_ids"): for line in self.mapped("bve_view_id.field_ids"):
if (line.table_alias, line.field_id.id,) not in seen: if (
seen.add((line.table_alias, line.field_id.id,)) line.table_alias,
line.field_id.id,
) not in seen:
seen.add(
(
line.table_alias,
line.field_id.id,
)
)
else: else:
raise ValidationError( raise ValidationError(
_("Field %s/%s is duplicated.\n" "Please remove the duplications.") _("Field %s/%s is duplicated.\n" "Please remove the duplications.")

View File

@ -85,7 +85,11 @@ class IrModel(models.Model):
for field in fields: for field in fields:
for table_alias in model_table_map[field.model_id.id]: for table_alias in model_table_map[field.model_id.id]:
model_list.append( model_list.append(
dict(dict_for_field(field), table_alias=table_alias, join_node=-1,) dict(
dict_for_field(field),
table_alias=table_alias,
join_node=-1,
)
) )
return model_list return model_list
@ -125,16 +129,15 @@ class IrModel(models.Model):
@api.model @api.model
def get_related_models(self, model_table_map): def get_related_models(self, model_table_map):
""" Return list of model dicts for all models that can be """Return list of model dicts for all models that can be
joined with the already selected models. joined with the already selected models.
""" """
domain = self._get_related_models_domain(model_table_map) domain = self._get_related_models_domain(model_table_map)
return self.sudo().search(domain, order="name asc") return self.sudo().search(domain, order="name asc")
@api.model @api.model
def get_models(self, table_model_map=None): def get_models(self, table_model_map=None):
""" Return list of model dicts for all available models. """Return list of model dicts for all available models."""
"""
self = self.with_context(lang=self.env.user.lang) self = self.with_context(lang=self.env.user.lang)
model_table_map = defaultdict(list) model_table_map = defaultdict(list)
for k, v in (table_model_map or {}).items(): for k, v in (table_model_map or {}).items():
@ -150,10 +153,10 @@ class IrModel(models.Model):
@api.model @api.model
def get_join_nodes(self, field_data, new_field): def get_join_nodes(self, field_data, new_field):
""" Return list of field dicts of join nodes """Return list of field dicts of join nodes
Return all possible join nodes to add new_field to the query Return all possible join nodes to add new_field to the query
containing model_ids. containing model_ids.
""" """
def remove_duplicate_nodes(join_nodes): def remove_duplicate_nodes(join_nodes):

View File

@ -1,4 +1,4 @@
# Copyright 2017-2019 Onestein (<https://www.onestein.eu>) # Copyright 2017-2020 Onestein (<https://www.onestein.eu>)
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
import logging import logging
@ -37,13 +37,6 @@ models.BaseModel._auto_init = _auto_init
class Base(models.AbstractModel): class Base(models.AbstractModel):
_inherit = "base" _inherit = "base"
@api.model
def _setup_complete(self):
if not _bi_view(self._name):
super()._setup_complete()
else:
self.pool.models[self._name]._log_access = False
@api.model @api.model
def _read_group_process_groupby(self, gb, query): def _read_group_process_groupby(self, gb, query):
if not _bi_view(self._name): if not _bi_view(self._name):
@ -53,9 +46,3 @@ class Base(models.AbstractModel):
if split[0] not in self._fields: if split[0] not in self._fields:
raise UserError(_("No data to be displayed.")) raise UserError(_("No data to be displayed."))
return super()._read_group_process_groupby(gb, query) return super()._read_group_process_groupby(gb, query)
@api.model
def _add_magic_fields(self):
if _bi_view(self._name):
self._log_access = False
return super()._add_magic_fields()

View File

@ -4,8 +4,8 @@
<field name="name">bve_view read access</field> <field name="name">bve_view read access</field>
<field name="model_id" search="[('model','=','bve.view')]" model="ir.model" /> <field name="model_id" search="[('model','=','bve.view')]" model="ir.model" />
<field name="global" eval="True" /> <field name="global" eval="True" />
<field <field name="domain_force">
name="domain_force" ['|',('user_ids','=',False),('user_ids','in',user.id)]
> ['|',('user_ids','=',False),('user_ids','in',user.id)]</field> </field>
</record> </record>
</odoo> </odoo>

View File

@ -1,7 +1,7 @@
/* Copyright 2015-2019 Onestein (<https://www.onestein.eu>) /* Copyright 2015-2019 Onestein (<https://www.onestein.eu>)
* License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). */ * License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). */
odoo.define("bi_view_editor.FieldList", function(require) { odoo.define("bi_view_editor.FieldList", function (require) {
"use strict"; "use strict";
var core = require("web.core"); var core = require("web.core");
@ -11,14 +11,14 @@ odoo.define("bi_view_editor.FieldList", function(require) {
var FieldListContextMenu = Widget.extend( var FieldListContextMenu = Widget.extend(
_.extend({}, mixins.EventDispatcherMixin, { _.extend({}, mixins.EventDispatcherMixin, {
start: function() { start: function () {
var res = this._super.apply(this, arguments); var res = this._super.apply(this, arguments);
this.$el.mouseleave(function() { this.$el.mouseleave(function () {
$(this).addClass("d-none"); $(this).addClass("d-none");
}); });
return res; return res;
}, },
open: function(x, y) { open: function (x, y) {
this.$el.css({ this.$el.css({
left: x + "px", left: x + "px",
top: y + "px", top: y + "px",
@ -31,7 +31,7 @@ odoo.define("bi_view_editor.FieldList", function(require) {
var FieldListFieldContextMenu = FieldListContextMenu.extend({ var FieldListFieldContextMenu = FieldListContextMenu.extend({
template: "bi_view_editor.FieldList.FieldContextMenu", template: "bi_view_editor.FieldList.FieldContextMenu",
open: function(x, y, $item) { open: function (x, y, $item) {
var field = $item.data("field"); var field = $item.data("field");
this.$el.find(".checkbox-column").prop("checked", field.column); this.$el.find(".checkbox-column").prop("checked", field.column);
this.$el.find(".checkbox-row").prop("checked", field.row); this.$el.find(".checkbox-row").prop("checked", field.row);
@ -49,7 +49,7 @@ odoo.define("bi_view_editor.FieldList", function(require) {
var events = this._super(x, y, field); var events = this._super(x, y, field);
this.$el.find("input").unbind("change"); this.$el.find("input").unbind("change");
this.$el.find("input").change(function() { this.$el.find("input").change(function () {
var $checkbox = $(this); var $checkbox = $(this);
var property = $checkbox.attr("data-for"); var property = $checkbox.attr("data-for");
field[property] = $checkbox.is(":checked"); field[property] = $checkbox.is(":checked");
@ -62,13 +62,13 @@ odoo.define("bi_view_editor.FieldList", function(require) {
var FieldListJoinContextMenu = FieldListContextMenu.extend({ var FieldListJoinContextMenu = FieldListContextMenu.extend({
template: "bi_view_editor.FieldList.JoinContextMenu", template: "bi_view_editor.FieldList.JoinContextMenu",
open: function(x, y, $item) { open: function (x, y, $item) {
var node = $item.data("field"); var node = $item.data("field");
this.$el.find(".checkbox-join-left").prop("checked", node.join_left); this.$el.find(".checkbox-join-left").prop("checked", node.join_left);
var events = this._super(x, y, node); var events = this._super(x, y, node);
this.$el.find("input").unbind("change"); this.$el.find("input").unbind("change");
this.$el.find("input").change(function() { this.$el.find("input").change(function () {
var $checkbox = $(this); var $checkbox = $(this);
var property = $checkbox.attr("data-for"); var property = $checkbox.attr("data-for");
node[property] = $checkbox.is(":checked"); node[property] = $checkbox.is(":checked");
@ -84,14 +84,14 @@ odoo.define("bi_view_editor.FieldList", function(require) {
"click .delete-button": "removeClicked", "click .delete-button": "removeClicked",
'keyup input[name="description"]': "keyupDescription", 'keyup input[name="description"]': "keyupDescription",
}, },
start: function() { start: function () {
var res = this._super.apply(this, arguments); var res = this._super.apply(this, arguments);
this.contextmenu = new FieldListFieldContextMenu(this); this.contextmenu = new FieldListFieldContextMenu(this);
this.contextmenu.appendTo(this.$el); this.contextmenu.appendTo(this.$el);
this.contextmenu.on( this.contextmenu.on(
"change", "change",
this, this,
function(f, $item) { function (f, $item) {
$item.data("field", f); $item.data("field", f);
this.refreshItem($item); this.refreshItem($item);
this.trigger("updated"); this.trigger("updated");
@ -102,7 +102,7 @@ odoo.define("bi_view_editor.FieldList", function(require) {
this.contextmenu_join.on( this.contextmenu_join.on(
"change", "change",
this, this,
function(f, $item) { function (f, $item) {
$item.data("field", f); $item.data("field", f);
this.refreshItem($item); this.refreshItem($item);
this.trigger("updated"); this.trigger("updated");
@ -112,7 +112,7 @@ odoo.define("bi_view_editor.FieldList", function(require) {
this.mode = null; this.mode = null;
return res; return res;
}, },
setMode: function(mode) { setMode: function (mode) {
if (mode === "readonly") { if (mode === "readonly") {
this.$el.find('input[type="text"]').attr("disabled", true); this.$el.find('input[type="text"]').attr("disabled", true);
this.$el.find(".delete-button").addClass("d-none"); this.$el.find(".delete-button").addClass("d-none");
@ -122,28 +122,26 @@ odoo.define("bi_view_editor.FieldList", function(require) {
} }
this.mode = mode; this.mode = mode;
}, },
get: function() { get: function () {
return $.makeArray( return $.makeArray(
this.$el.find("tbody tr").map(function() { this.$el.find("tbody tr").map(function () {
var field = $(this).data("field"); var field = $(this).data("field");
field.description = $(this) field.description = $(this).find('input[name="description"]').val();
.find('input[name="description"]')
.val();
return field; return field;
}) })
); );
}, },
getModelIds: function() { getModelIds: function () {
var model_ids = {}; var model_ids = {};
this.$el.find("tbody tr").each(function() { this.$el.find("tbody tr").each(function () {
var data = $(this).data("field"); var data = $(this).data("field");
model_ids[data.table_alias] = data.model_id; model_ids[data.table_alias] = data.model_id;
}); });
return model_ids; return model_ids;
}, },
getModelData: function() { getModelData: function () {
var model_data = {}; var model_data = {};
this.$el.find("tbody tr").each(function() { this.$el.find("tbody tr").each(function () {
var data = $(this).data("field"); var data = $(this).data("field");
model_data[data.table_alias] = { model_data[data.table_alias] = {
model_id: data.model_id, model_id: data.model_id,
@ -152,7 +150,7 @@ odoo.define("bi_view_editor.FieldList", function(require) {
}); });
return model_data; return model_data;
}, },
add: function(field) { add: function (field) {
var self = this; var self = this;
field.row = typeof field.row === "undefined" ? false : field.row; field.row = typeof field.row === "undefined" ? false : field.row;
field.column = typeof field.column === "undefined" ? false : field.column; field.column = typeof field.column === "undefined" ? false : field.column;
@ -169,7 +167,7 @@ odoo.define("bi_view_editor.FieldList", function(require) {
var i = 0; var i = 0;
var name = field.name; var name = field.name;
while ( while (
this.get().filter(function(item) { this.get().filter(function (item) {
return item.name === field.name; return item.name === field.name;
}).length > 0 }).length > 0
) { ) {
@ -189,7 +187,7 @@ odoo.define("bi_view_editor.FieldList", function(require) {
) )
) )
.data("field", field) .data("field", field)
.contextmenu(function(e) { .contextmenu(function (e) {
var $item = $(this); var $item = $(this);
if (self.mode === "readonly") { if (self.mode === "readonly") {
return; return;
@ -200,12 +198,12 @@ odoo.define("bi_view_editor.FieldList", function(require) {
this.$el.find("tbody").append($html); this.$el.find("tbody").append($html);
}, },
remove: function(id) { remove: function (id) {
var $item = this.$el.find('tr[data-id="' + id + '"]'); var $item = this.$el.find('tr[data-id="' + id + '"]');
$item.remove(); $item.remove();
this.trigger("removed", id); this.trigger("removed", id);
}, },
set: function(fields) { set: function (fields) {
var set_fields = fields; var set_fields = fields;
if (!set_fields) { if (!set_fields) {
set_fields = []; set_fields = [];
@ -215,7 +213,7 @@ odoo.define("bi_view_editor.FieldList", function(require) {
this.add(set_fields[i]); this.add(set_fields[i]);
} }
}, },
openContextMenu: function($item, x, y) { openContextMenu: function ($item, x, y) {
var field = $item.data("field"); var field = $item.data("field");
var contextmenu = field.join_node var contextmenu = field.join_node
? this.contextmenu_join ? this.contextmenu_join
@ -226,10 +224,10 @@ odoo.define("bi_view_editor.FieldList", function(require) {
} }
contextmenu.open(x - 20, y - 20, $item); contextmenu.open(x - 20, y - 20, $item);
}, },
refreshItem: function($item) { refreshItem: function ($item) {
var data = $item.data("field"); var data = $item.data("field");
var $attributes = $item.find("span[data-for], img[data-for]"); var $attributes = $item.find("span[data-for], img[data-for]");
$.each($attributes, function() { $.each($attributes, function () {
var $attribute = $(this); var $attribute = $(this);
var value = data[$attribute.attr("data-for")]; var value = data[$attribute.attr("data-for")];
if (value) { if (value) {
@ -239,12 +237,12 @@ odoo.define("bi_view_editor.FieldList", function(require) {
} }
}); });
}, },
removeClicked: function(e) { removeClicked: function (e) {
var $button = $(e.currentTarget); var $button = $(e.currentTarget);
var id = $button.attr("data-id"); var id = $button.attr("data-id");
this.remove(id); this.remove(id);
}, },
keyupDescription: function() { keyupDescription: function () {
this.trigger("updated"); this.trigger("updated");
}, },
}); });

View File

@ -1,7 +1,7 @@
/* Copyright 2015-2019 Onestein (<https://www.onestein.eu>) /* Copyright 2015-2019 Onestein (<https://www.onestein.eu>)
* License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). */ * License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). */
odoo.define("bi_view_editor.JoinNodeDialog", function(require) { odoo.define("bi_view_editor.JoinNodeDialog", function (require) {
"use strict"; "use strict";
var Dialog = require("web.Dialog"); var Dialog = require("web.Dialog");
@ -16,7 +16,7 @@ odoo.define("bi_view_editor.JoinNodeDialog", function(require) {
events: { events: {
"click li": "choiceClicked", "click li": "choiceClicked",
}, },
init: function(parent, options, choices, model_data) { init: function (parent, options, choices, model_data) {
this.choices = choices; this.choices = choices;
// Prepare data for view // Prepare data for view
for (var i = 0; i < choices.length; i++) { for (var i = 0; i < choices.length; i++) {
@ -43,7 +43,7 @@ odoo.define("bi_view_editor.JoinNodeDialog", function(require) {
}); });
this._super(parent, defaults); this._super(parent, defaults);
}, },
choiceClicked: function(e) { choiceClicked: function (e) {
this.trigger("chosen", { this.trigger("chosen", {
choice: this.choices[$(e.currentTarget).attr("data-index")], choice: this.choices[$(e.currentTarget).attr("data-index")],
}); });

View File

@ -1,7 +1,7 @@
/* Copyright 2015-2019 Onestein (<https://www.onestein.eu>) /* Copyright 2015-2019 Onestein (<https://www.onestein.eu>)
* License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). */ * License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). */
odoo.define("bi_view_editor.ModelList", function(require) { odoo.define("bi_view_editor.ModelList", function (require) {
"use strict"; "use strict";
var Widget = require("web.Widget"); var Widget = require("web.Widget");
@ -13,7 +13,7 @@ odoo.define("bi_view_editor.ModelList", function(require) {
events: { events: {
"keyup .search-bar > input": "filterChanged", "keyup .search-bar > input": "filterChanged",
}, },
init: function(parent) { init: function (parent) {
var res = this._super(parent); var res = this._super(parent);
this.active_models = []; this.active_models = [];
this.cache_fields = {}; this.cache_fields = {};
@ -21,7 +21,7 @@ odoo.define("bi_view_editor.ModelList", function(require) {
this.mode = null; this.mode = null;
return res; return res;
}, },
setMode: function(mode) { setMode: function (mode) {
if (mode === "readonly") { if (mode === "readonly") {
this.$el.find(".search-bar").attr("disabled", true); this.$el.find(".search-bar").attr("disabled", true);
this.$el.find(".class-list, .class").addClass("readonly"); this.$el.find(".class-list, .class").addClass("readonly");
@ -31,24 +31,24 @@ odoo.define("bi_view_editor.ModelList", function(require) {
} }
this.mode = mode; this.mode = mode;
}, },
isActive: function(id) { isActive: function (id) {
return this.active_models.indexOf(id) !== -1; return this.active_models.indexOf(id) !== -1;
}, },
removeAsActive: function(id) { removeAsActive: function (id) {
var i = this.active_models.indexOf(id); var i = this.active_models.indexOf(id);
this.active_models.splice(i, 1); this.active_models.splice(i, 1);
}, },
addAsActive: function(id) { addAsActive: function (id) {
this.active_models.push(id); this.active_models.push(id);
}, },
loadModels: function(model_ids) { loadModels: function (model_ids) {
return this._rpc({ return this._rpc({
model: "ir.model", model: "ir.model",
method: "get_models", method: "get_models",
args: model_ids ? [model_ids] : [], args: model_ids ? [model_ids] : [],
}); });
}, },
loadFields: function(model_id) { loadFields: function (model_id) {
if (!(model_id in this.cache_fields)) { if (!(model_id in this.cache_fields)) {
var deferred = this._rpc({ var deferred = this._rpc({
model: "ir.model", model: "ir.model",
@ -59,11 +59,11 @@ odoo.define("bi_view_editor.ModelList", function(require) {
} }
return this.cache_fields[model_id]; return this.cache_fields[model_id];
}, },
populateModels: function(models) { populateModels: function (models) {
var self = this; var self = this;
this.$el.find(".class-list").html(""); this.$el.find(".class-list").html("");
_.each(models, function(model) { _.each(models, function (model) {
var $html = $( var $html = $(
qweb.render("bi_view_editor.ModelListItem", { qweb.render("bi_view_editor.ModelListItem", {
id: model.id, id: model.id,
@ -74,19 +74,19 @@ odoo.define("bi_view_editor.ModelList", function(require) {
$html $html
.find(".class") .find(".class")
.data("model", model) .data("model", model)
.click(function() { .click(function () {
self.modelClicked($(this)); self.modelClicked($(this));
}); });
self.$el.find(".class-list").append($html); self.$el.find(".class-list").append($html);
if (self.isActive(model.id)) { if (self.isActive(model.id)) {
self.loadFields(model.id).then(function(fields) { self.loadFields(model.id).then(function (fields) {
self.populateFields(fields, model.id); self.populateFields(fields, model.id);
}); });
} }
}); });
}, },
populateFields: function(fields, model_id) { populateFields: function (fields, model_id) {
var self = this; var self = this;
if (!model_id && fields.length === 0) { if (!model_id && fields.length === 0) {
return; return;
@ -96,7 +96,7 @@ odoo.define("bi_view_editor.ModelList", function(require) {
data_model_id = fields[0].model_id; data_model_id = fields[0].model_id;
} }
var $model_item = this.$el.find(".class[data-id='" + data_model_id + "']"); var $model_item = this.$el.find(".class[data-id='" + data_model_id + "']");
_.each(fields, function(field) { _.each(fields, function (field) {
var $field = $( var $field = $(
qweb.render("bi_view_editor.ModelListFieldItem", { qweb.render("bi_view_editor.ModelListFieldItem", {
name: field.name, name: field.name,
@ -104,7 +104,7 @@ odoo.define("bi_view_editor.ModelList", function(require) {
}) })
) )
.data("field", field) .data("field", field)
.click(function() { .click(function () {
self.fieldClicked($(this)); self.fieldClicked($(this));
}) })
.draggable({ .draggable({
@ -117,43 +117,41 @@ odoo.define("bi_view_editor.ModelList", function(require) {
$model_item.after($field); $model_item.after($field);
}); });
}, },
modelClicked: function($el) { modelClicked: function ($el) {
if (this.mode === "readonly") { if (this.mode === "readonly") {
return; return;
} }
var model = $el.data("model"); var model = $el.data("model");
$el.parent() $el.parent().find(".field").remove();
.find(".field")
.remove();
if (this.isActive(model.id)) { if (this.isActive(model.id)) {
this.removeAsActive(model.id); this.removeAsActive(model.id);
} else { } else {
this.addAsActive(model.id); this.addAsActive(model.id);
this.loadFields(model.id).then( this.loadFields(model.id).then(
function(fields) { function (fields) {
this.populateFields(fields, model.id); this.populateFields(fields, model.id);
}.bind(this) }.bind(this)
); );
} }
}, },
fieldClicked: function($el) { fieldClicked: function ($el) {
if (this.mode === "readonly") { if (this.mode === "readonly") {
return; return;
} }
this.trigger("field_clicked", $el.data("field")); this.trigger("field_clicked", $el.data("field"));
}, },
filterChanged: function(e) { filterChanged: function (e) {
var $input = $(e.target); var $input = $(e.target);
this.filter($input.val()); this.filter($input.val());
}, },
filter: function(value) { filter: function (value) {
this.active_models = []; this.active_models = [];
this.$el.find(".field").remove(); this.$el.find(".field").remove();
var val = var val =
typeof value === "undefined" typeof value === "undefined"
? this.current_filter ? this.current_filter
: value.toLowerCase(); : value.toLowerCase();
this.$el.find(".class").each(function() { this.$el.find(".class").each(function () {
var data = $(this).data("model"); var data = $(this).data("model");
if ( if (
data.name.toLowerCase().indexOf(val) === -1 && data.name.toLowerCase().indexOf(val) === -1 &&

View File

@ -1,7 +1,7 @@
/* Copyright 2015-2019 Onestein (<https://www.onestein.eu>) /* Copyright 2015-2019 Onestein (<https://www.onestein.eu>)
* License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). */ * License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). */
odoo.define("bi_view_editor", function(require) { odoo.define("bi_view_editor", function (require) {
"use strict"; "use strict";
var JoinNodeDialog = require("bi_view_editor.JoinNodeDialog"); var JoinNodeDialog = require("bi_view_editor.JoinNodeDialog");
@ -17,32 +17,32 @@ odoo.define("bi_view_editor", function(require) {
events: { events: {
"click .clear-btn": "clear", "click .clear-btn": "clear",
}, },
start: function() { start: function () {
var self = this; var self = this;
var res = this._super.apply(this, arguments); var res = this._super.apply(this, arguments);
// Init ModelList // Init ModelList
this.model_list = new ModelList(this); this.model_list = new ModelList(this);
this.model_list.appendTo(this.$(".body > .left")); this.model_list.appendTo(this.$(".body > .left"));
this.model_list.on("field_clicked", this, function(field) { this.model_list.on("field_clicked", this, function (field) {
self.addField(_.extend({}, field)); self.addField(_.extend({}, field));
}); });
// Init FieldList // Init FieldList
this.field_list = new FieldList(this); this.field_list = new FieldList(this);
this.field_list.appendTo(this.$(".body > .right")).then( this.field_list.appendTo(this.$(".body > .right")).then(
function() { function () {
this.field_list.on("removed", this, this.fieldListRemoved); this.field_list.on("removed", this, this.fieldListRemoved);
this.field_list.on("updated", this, this.fieldListChanged); this.field_list.on("updated", this, this.fieldListChanged);
this.$el.find(".body > .right").droppable({ this.$el.find(".body > .right").droppable({
accept: "div.class-list div.field", accept: "div.class-list div.field",
drop: function(event, ui) { drop: function (event, ui) {
self.addField(_.extend({}, ui.draggable.data("field"))); self.addField(_.extend({}, ui.draggable.data("field")));
ui.draggable.draggable("option", "revert", false); ui.draggable.draggable("option", "revert", false);
}, },
}); });
this.on("change:effective_readonly", this, function() { this.on("change:effective_readonly", this, function () {
this.updateMode(); this.updateMode();
}); });
this.renderValue(); this.renderValue();
@ -53,31 +53,31 @@ odoo.define("bi_view_editor", function(require) {
return res; return res;
}, },
clear: function() { clear: function () {
if (this.mode !== "readonly") { if (this.mode !== "readonly") {
this.field_list.set([]); this.field_list.set([]);
this.loadAndPopulateModelList(); this.loadAndPopulateModelList();
this._setValue(this.field_list.get()); this._setValue(this.field_list.get());
} }
}, },
fieldListChanged: function() { fieldListChanged: function () {
this._setValue(this.field_list.get()); this._setValue(this.field_list.get());
}, },
fieldListRemoved: function() { fieldListRemoved: function () {
this._setValue(this.field_list.get()); this._setValue(this.field_list.get());
var model = new Data.DataSet(this, "bve.view"); var model = new Data.DataSet(this, "bve.view");
model.call("get_clean_list", [this.lastSetValue]).then( model.call("get_clean_list", [this.lastSetValue]).then(
function(result) { function (result) {
this.field_list.set(JSON.parse(result)); this.field_list.set(JSON.parse(result));
this._setValue(this.field_list.get()); this._setValue(this.field_list.get());
}.bind(this) }.bind(this)
); );
this.loadAndPopulateModelList(); this.loadAndPopulateModelList();
}, },
renderValue: function() { renderValue: function () {
this.field_list.set(JSON.parse(this.value)); this.field_list.set(JSON.parse(this.value));
}, },
updateMode: function() { updateMode: function () {
if (this.mode === "readonly") { if (this.mode === "readonly") {
this.$el.find(".clear-btn").addClass("d-none"); this.$el.find(".clear-btn").addClass("d-none");
this.$el.find(".body .right").droppable("option", "disabled", true); this.$el.find(".body .right").droppable("option", "disabled", true);
@ -88,18 +88,18 @@ odoo.define("bi_view_editor", function(require) {
this.field_list.setMode(this.mode); this.field_list.setMode(this.mode);
this.model_list.setMode(this.mode); this.model_list.setMode(this.mode);
}, },
loadAndPopulateModelList: function() { loadAndPopulateModelList: function () {
var model_ids = null; var model_ids = null;
if (this.field_list.get().length > 0) { if (this.field_list.get().length > 0) {
model_ids = this.field_list.getModelIds(); model_ids = this.field_list.getModelIds();
} }
this.model_list.loadModels(model_ids).then( this.model_list.loadModels(model_ids).then(
function(models) { function (models) {
this.model_list.populateModels(models); this.model_list.populateModels(models);
}.bind(this) }.bind(this)
); );
}, },
getTableAlias: function(field) { getTableAlias: function (field) {
if (typeof field.table_alias === "undefined") { if (typeof field.table_alias === "undefined") {
var model_ids = this.field_list.getModelIds(); var model_ids = this.field_list.getModelIds();
var n = 1; var n = 1;
@ -110,7 +110,7 @@ odoo.define("bi_view_editor", function(require) {
} }
return field.table_alias; return field.table_alias;
}, },
addFieldAndJoinNode: function(field, join_node) { addFieldAndJoinNode: function (field, join_node) {
if (join_node.join_node === -1 || join_node.table_alias === -1) { if (join_node.join_node === -1 || join_node.table_alias === -1) {
field.table_alias = this.getTableAlias(field); field.table_alias = this.getTableAlias(field);
if (join_node.join_node === -1) { if (join_node.join_node === -1) {
@ -127,12 +127,12 @@ odoo.define("bi_view_editor", function(require) {
this.loadAndPopulateModelList(); this.loadAndPopulateModelList();
this._setValue(this.field_list.get()); this._setValue(this.field_list.get());
}, },
addField: function(field) { addField: function (field) {
var data = _.extend({}, field); var data = _.extend({}, field);
var model = new Data.DataSet(this, "ir.model"); var model = new Data.DataSet(this, "ir.model");
var field_data = this.field_list.get(); var field_data = this.field_list.get();
model.call("get_join_nodes", [field_data, data]).then( model.call("get_join_nodes", [field_data, data]).then(
function(result) { function (result) {
if (result.length === 1) { if (result.length === 1) {
this.addFieldAndJoinNode(data, result[0]); this.addFieldAndJoinNode(data, result[0]);
} else if (result.length > 1) { } else if (result.length > 1) {
@ -142,7 +142,7 @@ odoo.define("bi_view_editor", function(require) {
result, result,
this.field_list.getModelData() this.field_list.getModelData()
); );
dialog.open().on("chosen", this, function(e) { dialog.open().on("chosen", this, function (e) {
this.addFieldAndJoinNode(data, e.choice); this.addFieldAndJoinNode(data, e.choice);
}); });
} else { } else {
@ -154,7 +154,7 @@ odoo.define("bi_view_editor", function(require) {
}.bind(this) }.bind(this)
); );
}, },
_parseValue: function(value) { _parseValue: function (value) {
return JSON.stringify(value); return JSON.stringify(value);
}, },
}); });

View File

@ -4,6 +4,7 @@
<div class="oe_form_field_bi_editor"> <div class="oe_form_field_bi_editor">
<div class="body"> <div class="body">
<div class="left"> <div class="left">
</div> </div>
<div class="right"> <div class="right">
@ -13,9 +14,10 @@
<div class="footer"> <div class="footer">
<div class="left" /> <div class="left" />
<div class="right"> <div class="right">
<button class="clear-btn d-none"><span <button class="clear-btn d-none">
class="fa fa-eraser" <span class="fa fa-eraser" />
/> Clear</button> Clear
</button>
</div> </div>
</div> </div>
</div> </div>
@ -76,6 +78,7 @@
<input type="text" class="search-bar" /> <input type="text" class="search-bar" />
</div> </div>
<div class="class-list"> <div class="class-list">
</div> </div>
</div> </div>
</t> </t>
@ -106,6 +109,7 @@
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
</tbody> </tbody>
</table> </table>
</div> </div>
@ -165,7 +169,8 @@
type="checkbox" type="checkbox"
data-for="join_left" data-for="join_left"
class="checkbox-join-left" class="checkbox-join-left"
/> Join Left />
Join Left
</label> </label>
</div> </div>
</li> </li>

View File

@ -354,7 +354,7 @@ class TestBiViewEditor(TransactionCase):
uninstall_hook(self.cr, self.env) uninstall_hook(self.cr, self.env)
def test_18_action_translations(self): def test_18_action_translations(self):
self.env["res.lang"].load_lang("it_IT") self.env["res.lang"]._activate_lang("it_IT")
vals = self.bi_view1_vals vals = self.bi_view1_vals
vals.update({"name": "Test View1"}) vals.update({"name": "Test View1"})
bi_view1 = self.env["bve.view"].create(vals) bi_view1 = self.env["bve.view"].create(vals)

View File

@ -1,4 +1,4 @@
# Copyright 2017-2019 Onestein (<https://www.onestein.eu>) # Copyright 2017-2020 Onestein (<https://www.onestein.eu>)
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo import api, models from odoo import api, models
@ -21,7 +21,7 @@ class WizardModelMenuCreate(models.TransientModel):
) )
self.env["ir.model.data"].create( self.env["ir.model.data"].create(
{ {
"name": bve_view.name + ", id=" + str(menu.id), "name": bve_view.name + ",id=" + str(menu.id),
"noupdate": True, "noupdate": True,
"module": "bi_view_editor", "module": "bi_view_editor",
"model": "ir.ui.menu", "model": "ir.ui.menu",