From 7be6ff98be57f03fedb191cb59706ffa709e3577 Mon Sep 17 00:00:00 2001 From: astirpe Date: Fri, 24 Jun 2016 14:17:36 +0200 Subject: [PATCH] Porting bi_view_editor to V9 --- bi_view_editor/README.rst | 99 ++++ bi_view_editor/__init__.py | 5 + bi_view_editor/__openerp__.py | 34 ++ bi_view_editor/models/__init__.py | 6 + bi_view_editor/models/bve_view.py | 306 ++++++++++++ bi_view_editor/models/ir_model.py | 223 +++++++++ bi_view_editor/security/ir.model.access.csv | 3 + bi_view_editor/security/rules.xml | 13 + bi_view_editor/static/description/icon.png | Bin 0 -> 4213 bytes .../static/description/main_screenshot.png | Bin 0 -> 64606 bytes bi_view_editor/static/src/css/bve.css | 175 +++++++ bi_view_editor/static/src/js/bve.js | 447 ++++++++++++++++++ bi_view_editor/templates/assets_template.xml | 13 + bi_view_editor/templates/qweb_template.xml | 78 +++ bi_view_editor/views/bve_view.xml | 70 +++ 15 files changed, 1472 insertions(+) create mode 100644 bi_view_editor/README.rst create mode 100644 bi_view_editor/__init__.py create mode 100644 bi_view_editor/__openerp__.py create mode 100644 bi_view_editor/models/__init__.py create mode 100644 bi_view_editor/models/bve_view.py create mode 100644 bi_view_editor/models/ir_model.py create mode 100644 bi_view_editor/security/ir.model.access.csv create mode 100644 bi_view_editor/security/rules.xml create mode 100644 bi_view_editor/static/description/icon.png create mode 100644 bi_view_editor/static/description/main_screenshot.png create mode 100644 bi_view_editor/static/src/css/bve.css create mode 100644 bi_view_editor/static/src/js/bve.js create mode 100644 bi_view_editor/templates/assets_template.xml create mode 100644 bi_view_editor/templates/qweb_template.xml create mode 100644 bi_view_editor/views/bve_view.xml diff --git a/bi_view_editor/README.rst b/bi_view_editor/README.rst new file mode 100644 index 00000000..a7283ea9 --- /dev/null +++ b/bi_view_editor/README.rst @@ -0,0 +1,99 @@ +.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 + +============== +BI View Editor +============== + +The module BI View Editor is user-friendly tool (Query Builder) integrated in Odoo. +It creates views for Odoo 9, allowing the user to specify graphically the sources +and the attributes of the data-set to analyze, automating all the operations for +creating all the necessary low level Odoo objects. + + +It is intended for: + +- Graphically define your analysis data-set +- Add new computed information to your data set +- Specify the visualization attributes +- Create the basis for a new data exploration method in Odoo + + +Benefits would be: + +- More freedom to consultants or end users to customize views +- No more external tools for data analysis +- Easy update of your BI reports +- No more external tools for data analysis + + + +Usage +===== + + +To graphically design your analysis data-set: + +- From the Reporting menu, select "Custom BI Views" +- Browse trough the business objects in the Query tab +- Pick the interesting fields (Drag & Drop) +- Save and click "Generate BI View" + + + +.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas + :alt: Try me on Runbot + :target: https://runbot.odoo-community.org/runbot/143/9.0 + +Known issues / Roadmap +====================== + +* Non-stored fields are not supported yet +* Provide graph view for table relations (would be a "nice to have") +* Porting to Odoo 9.0 + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues +`_. In case of trouble, please +check there if your issue has already been reported. If you spotted it first, +help us smashing it by providing a detailed and welcomed `feedback +`_. + +Credits +======= + +Images +------ + +* Odoo Community Association: `Icon `_. + +Contributors +------------ + +* Simon Janssens +* Diego Luis Neto +* Dennis Sluijk +* Kevin Graveman +* Richard Dijkstra +* Andrea Stirpe + +Maintainer +---------- + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +This module is maintained by the OCA. + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +To contribute to this module, please visit https://odoo-community.org. diff --git a/bi_view_editor/__init__.py b/bi_view_editor/__init__.py new file mode 100644 index 00000000..1be685b8 --- /dev/null +++ b/bi_view_editor/__init__.py @@ -0,0 +1,5 @@ +# -*- coding: utf-8 -*- +# © 2015-2016 ONESTEiN BV () +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from . import models diff --git a/bi_view_editor/__openerp__.py b/bi_view_editor/__openerp__.py new file mode 100644 index 00000000..ad4a4342 --- /dev/null +++ b/bi_view_editor/__openerp__.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +# © 2015-2016 ONESTEiN BV () +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +{ + 'name': 'BI View Editor', + 'summary': '''Graphical BI views builder for Odoo 8''', + 'images': ['static/description/main_screenshot.png'], + 'author': 'ONESTEiN BV,Odoo Community Association (OCA)', + 'license': 'AGPL-3', + 'website': 'http://www.onestein.eu', + 'category': 'Reporting', + 'version': '9.0.1.0.0', + 'depends': [ + 'base', + 'web', + ], + 'data': [ + 'security/ir.model.access.csv', + 'security/rules.xml', + 'templates/assets_template.xml', + 'views/bve_view.xml', + ], + 'qweb': [ + 'templates/qweb_template.xml', + ], + 'js': [ + 'static/src/js/bve.js' + ], + 'demo': [], + 'installable': True, + 'auto_install': False, + 'application': False, +} diff --git a/bi_view_editor/models/__init__.py b/bi_view_editor/models/__init__.py new file mode 100644 index 00000000..319d0dfb --- /dev/null +++ b/bi_view_editor/models/__init__.py @@ -0,0 +1,6 @@ +# -*- coding: utf-8 -*- +# © 2015-2016 ONESTEiN BV () +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from . import bve_view +from . import ir_model diff --git a/bi_view_editor/models/bve_view.py b/bi_view_editor/models/bve_view.py new file mode 100644 index 00000000..30fd5a48 --- /dev/null +++ b/bi_view_editor/models/bve_view.py @@ -0,0 +1,306 @@ +# -*- coding: utf-8 -*- +# © 2015-2016 ONESTEiN BV () +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +import json + +from openerp import tools +from openerp import SUPERUSER_ID +from openerp import models, fields, api +from openerp.exceptions import Warning as UserError +from openerp.tools.translate import _ + + +class BveView(models.Model): + _name = 'bve.view' + _description = "BI View Editor" + + @api.depends('group_ids') + @api.multi + def _compute_users(self): + for bve_view in self: + if bve_view.sudo().group_ids: + bve_view.user_ids = self.env['res.users'].sudo().browse( + list(set([u.id for group in bve_view.sudo().group_ids + for u in group.users]))) + else: + bve_view.user_ids = self.env['res.users'].sudo().search([]) + + name = fields.Char(size=128, string="Name", required=True) + model_name = fields.Char(size=128, string="Model Name") + + note = fields.Text(string="Notes") + + state = fields.Selection( + [('draft', 'Draft'), + ('created', 'Created')], + string="State", + default="draft") + data = fields.Text( + string="Data", + help="Use the special query builder to define the query " + "to generate your report dataset. " + "NOTE: Te be edited, the query should be in 'Draft' status.") + + action_id = fields.Many2one('ir.actions.act_window', string="Action") + view_id = fields.Many2one('ir.ui.view', string="View") + + group_ids = fields.Many2many( + 'res.groups', + string="Groups", + help="User groups allowed to see the generated report; " + "if NO groups are specified the report will be public " + "for everyone.") + + user_ids = fields.Many2many( + 'res.users', + string="Users", + compute=_compute_users, + store=True) + + _sql_constraints = [ + ('name_uniq', + 'unique(name)', + 'Custom BI View names must be unique!'), + ] + + @api.multi + def unlink(self): + for view in self: + if view.state == 'created': + raise UserError( + _('You cannot delete a created view! ' + 'Reset the view to draft first.')) + + super(BveView, self).unlink() + + @api.multi + def action_edit_query(self): + return { + 'type': 'ir.actions.client', + 'tag': 'bi_view_editor.open', + 'target': 'new', + 'params': {'bve_view_id': self.id} + } + + @api.multi + def action_reset(self): + if self.action_id: + if self.action_id.view_id: + self.action_id.view_id.sudo().unlink() + self.action_id.sudo().unlink() + + models = self.env['ir.model'].sudo().search( + [('model', '=', self.model_name)]) + for model in models: + model.sudo().unlink() + + table_name = self.model_name.replace(".", "_") + tools.drop_view_if_exists(self.env.cr, table_name) + + self.write({ + 'state': 'draft' + }) + return True + + def _create_graph_view(self): + fields_info = json.loads(self.data) + return ["""""".format( + field_info['name'], + (field_info['row'] and 'row') or + (field_info['column'] and 'col') or + (field_info['measure'] and 'measure')) + for field_info in fields_info if field_info['row'] or + field_info['column'] or field_info['measure']] + + @api.multi + def action_create(self): + + def _get_fields_info(fields_data): + fields_info = [] + for field_data in fields_data: + field = self.env['ir.model.fields'].browse(field_data["id"]) + vals = { + "table": self.env[field.model_id.model]._table, + "table_alias": field_data["table_alias"], + "select_field": field.name, + "as_field": "x_" + field_data["name"], + "join": False, + "model": field.model_id.model + } + if field_data.get("join_node"): + vals.update({"join": field_data["join_node"]}) + fields_info.append(vals) + return fields_info + + def _build_query(): + data = self.data + if not data: + raise UserError(_('No data to process.')) + info = _get_fields_info(json.loads(data)) + fields = [("{}.{}".format(f["table_alias"], + f["select_field"]), + f["as_field"]) for f in info if 'join_node' not in f] + tables = set([(f["table"], f["table_alias"]) for f in info]) + join_nodes = [ + (f["table_alias"], + f["join"], + f["select_field"]) for f in info if f["join"] is not False] + + table_name = self.model_name.replace(".", "_") + tools.drop_view_if_exists(self.env.cr, table_name) + + basic_fields = [ + ("t0.id", "id"), + ("t0.write_uid", "write_uid"), + ("t0.write_date", "write_date"), + ("t0.create_uid", "create_uid"), + ("t0.create_date", "create_date") + ] + + q = """CREATE or REPLACE VIEW %s as ( + SELECT %s + FROM %s + WHERE %s + )""" % (table_name, ','.join( + ["{} AS {}".format(f[0], f[1]) + for f in basic_fields + fields]), ','.join( + ["{} AS {}".format(t[0], t[1]) + for t in list(tables)]), " AND ".join( + ["{}.{} = {}.id".format(j[0], j[2], j[1]) + for j in join_nodes] + ["TRUE"])) + + self.env.cr.execute(q) + + def _prepare_field(field_data): + if not field_data["custom"]: + field = self.env['ir.model.fields'].browse(field_data["id"]) + vals = { + "name": "x_" + field_data["name"], + "complete_name": field.complete_name, + 'model': self.model_name, + 'relation': field.relation, + "field_description": field_data.get( + "description", field.field_description), + "ttype": field.ttype, + "selection": field.selection, + "size": field.size, + 'state': "manual" + } + if field.ttype == 'selection' and not field.selection: + model_obj = self.env[field.model_id.model] + selection = model_obj._columns[field.name].selection + selection_domain = str(selection) + vals.update({"selection": selection_domain}) + return vals + + def _prepare_object(): + return { + 'name': self.name, + 'model': self.model_name, + 'field_id': [ + (0, 0, _prepare_field(field)) + for field in json.loads(self.data) + if 'join_node' not in field] + } + + def _build_object(): + res_id = self.env['ir.model'].sudo().create(_prepare_object()) + return res_id + + # read access + def group_ids_with_access(model_name, access_mode): + self.env.cr.execute('''SELECT + g.id + FROM + ir_model_access a + JOIN ir_model m ON (a.model_id=m.id) + JOIN res_groups g ON (a.group_id=g.id) + LEFT JOIN ir_module_category c ON (c.id=g.category_id) + WHERE + m.model=%s AND + a.active IS True AND + a.perm_''' + access_mode, (model_name,)) + return [x[0] for x in self.env.cr.fetchall()] + + def _build_access_rules(obj): + info = json.loads(self.data) + models = list(set([f["model"] for f in info])) + read_groups = set.intersection(*[set( + group_ids_with_access(model, 'read')) for model in models]) + + for group in read_groups: + self.env['ir.model.access'].sudo().create({ + 'name': 'read access to ' + self.model_name, + 'model_id': obj.id, + 'group_id': group, + 'perm_read': True, + }) + + # edit access + for group in self.group_ids: + self.env['ir.model.access'].sudo().create({ + 'name': 'read access to ' + self.model_name, + 'model_id': obj.id, + 'group_id': group.id, + 'perm_read': True, + 'perm_write': True, + }) + + return + + self.model_name = "x_bve." + ''.join( + [x for x in self.name.lower() + if x.isalnum()]).replace("_", ".").replace(" ", ".") + + _build_query() + obj = _build_object() + _build_access_rules(obj) + self.env.cr.commit() + + from openerp.modules.registry import RegistryManager + self.env.registry = RegistryManager.new(self.env.cr.dbname) + RegistryManager.signal_registry_change(self.env.cr.dbname) + self.pool = self.env.registry + + view_id = self.pool.get('ir.ui.view').create( + self.env.cr, SUPERUSER_ID, + {'name': "Analysis", + 'type': 'graph', + 'model': self.model_name, + 'priority': 16, + 'arch': """ + {} + """.format("".join(self._create_graph_view())) + }, context={}) + view_ids = [view_id] + + action_vals = {'name': self.name, + 'res_model': self.model_name, + 'type': 'ir.actions.act_window', + 'view_type': 'form', + 'view_mode': 'graph', + 'view_id': view_ids and view_ids[0] or 0, + 'context': "{'service_name': '%s'}" % self.name, + } + act_window = self.env['ir.actions.act_window'] + action_id = act_window.sudo().create(action_vals) + + self.write({ + 'action_id': action_id.id, + 'view_id': view_id, + 'state': 'created' + }) + + return True + + @api.multi + def open_view(self): + return { + 'type': 'ir.actions.act_window', + 'res_model': self.model_name, + 'view_type': 'graph', + 'view_mode': 'graph', + } diff --git a/bi_view_editor/models/ir_model.py b/bi_view_editor/models/ir_model.py new file mode 100644 index 00000000..2bc6ee03 --- /dev/null +++ b/bi_view_editor/models/ir_model.py @@ -0,0 +1,223 @@ +# -*- coding: utf-8 -*- +# © 2015-2016 ONESTEiN BV () +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from openerp import models, api +from openerp.modules.registry import RegistryManager + +NO_BI_MODELS = [ + "temp.range", + "account.statement.operation.template", + "fetchmail.server" +] + +NO_BI_FIELDS = [ + "id", + "create_uid", + "create_date", + "write_uid", + "write_date" +] + + +def dict_for_field(field): + return { + "id": field.id, + "name": field.name, + "description": field.field_description, + "type": field.ttype, + "relation": field.relation, + "custom": False, + + "model_id": field.model_id.id, + "model": field.model_id.model, + "model_name": field.model_id.name + } + + +def dict_for_model(model): + return { + "id": model.id, + "name": model.name, + "model": model.model + } + + +class IrModel(models.Model): + _inherit = 'ir.model' + + def _filter_bi_fields(self, ir_model_field_obj): + name = ir_model_field_obj.name + model = ir_model_field_obj.model_id + model_name = model.model + if name in self.env[model_name]._columns: + f = self.env[model_name]._columns[name] + return f._classic_write + return False + + @api.model + def _filter_bi_models(self, model): + model_name = model["model"] + if model_name in NO_BI_MODELS or \ + model_name.startswith("workflow") or \ + model_name.startswith("ir.") or \ + model["name"] == "Unknow" or \ + "report" in model_name or \ + model_name.startswith("base_") or \ + "_" in model_name or \ + "." in model["name"] or \ + "mail" in model_name or \ + "edi." in model_name: + return False + return self.env['ir.model.access'].check( + model["model"], 'read', False) + + @api.model + def get_related_fields(self, model_ids): + """ Return list of field dicts for all fields that can be + joined with models in model_ids + """ + model_names = dict([(model.id, model.model) + for model in self.env['ir.model'].sudo().search( + [('id', 'in', model_ids.values())])]) + filter_bi_fields = self._filter_bi_fields + if filter_bi_fields: + rfields = [ + dict(dict_for_field(field), + join_node=-1, + table_alias=model[0]) + for field in filter( + filter_bi_fields, + self.env['ir.model.fields'].sudo().search( + [('model_id', 'in', model_ids.values()), + ('ttype', 'in', ['many2one'])])) + for model in model_ids.items() + if model[1] == field.model_id.id + ] + + lfields = [ + dict(dict_for_field(field), + join_node=model[0], + table_alias=-1) + for field in filter( + filter_bi_fields, + self.env['ir.model.fields'].sudo().search( + [('relation', 'in', model_names.values()), + ('ttype', 'in', ['many2one'])])) + for model in model_ids.items() + if model_names[model[1]] == field['relation'] + ] + + return [dict(field, join_node=model[0]) + for field in lfields + if model_names[model[1]] == field['relation']] + [ + dict(field, table_alias=model[0]) + for model in model_ids.items() + for field in rfields if model[1] == field['model_id']] + + @api.model + def get_related_models(self, model_ids): + """ Return list of model dicts for all models that can be + joined with models in model_ids + """ + related_fields = self.get_related_fields(model_ids) + return sorted(filter( + self._filter_bi_models, + [{"id": model.id, "name": model.name, "model": model.model} + for model in self.env['ir.model'].sudo().search( + ['|', + ('id', 'in', model_ids.values() + [ + f['model_id'] + for f in related_fields if f['table_alias'] == -1]), + ('model', 'in', [ + f['relation'] + for f in related_fields if f['join_node'] == -1])])]), + key=lambda x: x['name']) + + @api.model + def get_models(self): + """ Return list of model dicts for all available models. + """ + models_domain = [('transient', '=', False)] + return sorted(filter( + self._filter_bi_models, + [dict_for_model(model) + for model in self.search(models_domain)]), + key=lambda x: x['name']) + + @api.model + def get_join_nodes(self, field_data, new_field): + """ Return list of field dicts of join nodes + + Return all possible join nodes to add new_field to the query + containing model_ids. + """ + model_ids = dict([(field['table_alias'], + field['model_id']) for field in field_data]) + keys = [(field['table_alias'], field['id']) + for field in field_data if field.get('join_node', -1) != -1] + join_nodes = ([{'table_alias': alias} + for alias, model_id in model_ids.items() + if model_id == new_field['model_id']] + [ + d for d in self.get_related_fields(model_ids) + if (d['relation'] == new_field['model'] and + d['join_node'] == -1) or + (d['model_id'] == new_field['model_id'] and + d['table_alias'] == -1)]) + return filter( + lambda x: 'id' not in x or + (x['table_alias'], x['id']) not in keys, join_nodes) + + @api.model + def get_fields(self, model_id): + bi_field_domain = [ + ('model_id', '=', model_id), + ("name", "not in", NO_BI_FIELDS), + ('ttype', 'not in', [ + 'many2many', "one2many", "html", "binary", "reference"]) + ] + filter_bi_fields = self._filter_bi_fields + fields_obj = self.env['ir.model.fields'] + fields = filter(filter_bi_fields, + fields_obj.sudo().search(bi_field_domain)) + return sorted([{"id": field.id, + "model_id": model_id, + "name": field.name, + "description": field.field_description, + "type": field.ttype, + "custom": False, + "model": field.model_id.model, + "model_name": field.model_id.name} + for field in fields], key=lambda x: x['description'], + reverse=True) + + def create(self, cr, user, vals, context=None): + if context is None: + context = {} + if context and context.get('bve'): + vals['state'] = 'base' + res = super(IrModel, self).create(cr, user, vals, context) + if vals.get('state', 'base') == 'bve': + vals['state'] = 'manual' + + # add model in registry + self.instanciate(cr, user, vals['model'], context) + self.pool.setup_models(cr, partial=(not self.pool.ready)) + + # update database schema + # model = self.pool[vals['model']] + # ctx = dict( + # context, + # field_name=vals['name'], + # field_state='manual', + # select=vals.get('select_level', '0'), + # update_custom_fields=True) + RegistryManager.signal_registry_change(cr.dbname) + +# self.write(cr, user, [res], {'state': 'manual'}) + q = ("""UPDATE ir_model SET state = 'manual' + WHERE id = """ + str(res)) + + cr.execute(q) + + return res diff --git a/bi_view_editor/security/ir.model.access.csv b/bi_view_editor/security/ir.model.access.csv new file mode 100644 index 00000000..2547fb5a --- /dev/null +++ b/bi_view_editor/security/ir.model.access.csv @@ -0,0 +1,3 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_bve_view_everyone,bve.view,bi_view_editor.model_bve_view,,1,1,1,1 +access_bve_view_technical_settings,bve.view,bi_view_editor.model_bve_view,base.group_no_one,1,1,1,1 diff --git a/bi_view_editor/security/rules.xml b/bi_view_editor/security/rules.xml new file mode 100644 index 00000000..d68db5db --- /dev/null +++ b/bi_view_editor/security/rules.xml @@ -0,0 +1,13 @@ + + + + + + bve_view read access + + + ['|',('user_ids','=',False),('user_ids','in',user.id)] + + + + diff --git a/bi_view_editor/static/description/icon.png b/bi_view_editor/static/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..bd6f94bca93bd9a90b9cae3f5d25c22a031c6249 GIT binary patch literal 4213 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 GoBspxuv0Jq literal 0 HcmV?d00001 diff --git a/bi_view_editor/static/description/main_screenshot.png b/bi_view_editor/static/description/main_screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..66789facc400cbe2a7ddf5fece5c132e54bd717c GIT binary patch literal 64606 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

@Jr}LMy^m&!g`SOF#;Y!oC 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 "; + if(field.row) + icons += " "; + if(field.measure) + icons += " "; + + return icons; + }, + update_field_view: function(row) { + row.find("td:nth-child(3)").html(this.get_field_icons(row.data('field-data'))); + }, + render_value: function() { + this.set_fields(JSON.parse(this.get('value'))); + }, + load_classes: function(scrollTo) { + scrollTo = (typeof scrollTo == 'undefined') ? false : scrollTo; + var self = this; + var model = new instance.web.Model("ir.model"); + if (this.$el.find(".field-list tbody tr").length > 0) { + model.call("get_related_models", [this.get_model_ids()], { context: new instance.web.CompoundContext() }).then(function(result) { + self.show_classes(result); + //if(scrollTo) self.$el.find('.class-list').scrollTo('#bve-class-' + scrollTo.model_id); + }); + } else { + model.call("get_models", { context: new instance.web.CompoundContext() }).then(function(result) { + self.show_classes(result); + //if(scrollTo) self.$el.find('.class-list').scrollTo('#bve-class-' + scrollTo.model_id); + }); + } + }, + show_classes: function (result) { + var self = this; + var model = new instance.web.Model("ir.model"); + self.$el.find(".class-list .class").remove(); + self.$el.find(".class-list .field").remove(); + var css = this.get('effective_readonly') ? 'cursor: default' : 'cursor: pointer' + + for (var i = 0; i < result.length; i++) { + var item = $("

") + .data('model-data', result[i]) + .click(function (evt) { + if(self.get("effective_readonly")) return; + var classel = $(this); + + if (classel.data('bve-processed')) { + classel.parent().find('.field').remove(); + classel.data('bve-processed', false); + var index = self.activeModelMenus.indexOf(classel.data('model-data').id); + if(index != -1) self.activeModelMenus.splice(index, 1); + } else { + self.activeModelMenus.push(classel.data('model-data').id); + model.call("get_fields", [classel.data('model-data').id], { context: new instance.web.CompoundContext() }).then(function(result) { + for (var i = 0; i < result.length; i++) { + classel.find("#bve-field-" + result[i]["name"]).remove(); + if(self.$el.find(".field-list tbody [name=label-" + result[i].id + "]").length > 0) continue; + classel.after($("
" + result[i]["description"] + "
") + .data('field-data', result[i]) + .click(function () { + if (!self.get("effective_readonly")) { + self.add_field($(this)); + } + }) + .draggable({ + 'revert': 'invalid', + 'scroll': false, + 'helper': 'clone', + 'appendTo': 'body', + 'containment': 'window' + }) + ); + } + }); + + $(this).data('bve-processed', true); + } + }) + .wrap("
").parent(); + self.$el.find(".class-list").append(item); + + var index = self.activeModelMenus.indexOf(item.find(".class").data('model-data').id); + if(index != -1 && !self.get("effective_readonly")) { + model.call("get_fields", [self.activeModelMenus[index]], { context: new instance.web.CompoundContext() }).then(function(result) { + var item = self.$el.find(".class-list #bve-class-" + result[0].model_id); + for (var o = 0; o < result.length; o++) { + if(self.$el.find(".field-list tbody [name=label-" + result[o].id + "]").length > 0) continue; + item.after($("
" + result[o]["description"] + "
") + .data('field-data', result[o]) + .click(function () { + if (!self.get("effective_readonly")) { + self.add_field($(this)); + } + }) + .draggable({ + 'revert': 'invalid', + 'scroll': false, + 'helper': 'clone', + 'appendTo': 'body', + 'containment': 'window' + })); + } + item.data('bve-processed', true); + }); + } + self.filter(); + } + + }, + add_field_to_table: function(data, options) { + var self = this; + if (typeof data.row == 'undefined') { + data.row = false; + } + if (typeof data.column == 'undefined') { + data.column = false; + } + if (typeof data.measure == 'undefined') { + data.measure = false; + } + + var n = 1; + var name = data.name; + while ($.grep(self.get_fields(), function (el) { return el.name == data.name;}).length > 0) { + data.name = name + '_' + n; + n += 1; + } + var classes = ""; + if (typeof data.join_node != 'undefined') { + classes = "join-node displaynone"; + } + var delete_button = ""; + var disabled = " disabled=\"disabled\" "; + if (!this.get("effective_readonly")) { + delete_button = ""; + disabled = ""; + } + + self.$el.find(".field-list tbody") + .append($("" + data.model_name + "" + self.get_field_icons(data) + "" + delete_button + "") + .data('field-data', data) + .contextmenu(function(e) { + e.preventDefault(); + if (self.get("effective_readonly")) return; + var target = $(e.currentTarget); + var currentFieldData = target.data('field-data'); + + var contextMenu = self.$el.find(".context-menu"); + contextMenu.css("left", e.pageX + "px"); + contextMenu.css("top", e.pageY + "px"); + contextMenu.mouseleave(function() { + contextMenu.hide(); + }); + contextMenu.find("li").hover(function() { + $(this).find("ul").css("color", "#000"); + $(this).find("ul").show(); + }, function() { + $(this).find("ul").hide(); + }); + + //Set checkboxes + if(currentFieldData.column) + contextMenu.find('#column-checkbox').attr('checked', true); + else + contextMenu.find('#column-checkbox').attr('checked', false); + + if(currentFieldData.row) + contextMenu.find('#row-checkbox').attr('checked', true); + else + contextMenu.find('#row-checkbox').attr('checked', false); + + if(currentFieldData.measure) + contextMenu.find('#measure-checkbox').attr('checked', true); + else + contextMenu.find('#measure-checkbox').attr('checked', false); + + if(currentFieldData.type == "float" || currentFieldData.type == "integer") { + contextMenu.find('#column-checkbox').attr('disabled', true); + contextMenu.find('#row-checkbox').attr('disabled', true); + contextMenu.find('#measure-checkbox').attr('disabled', false); + } + else { + contextMenu.find('#column-checkbox').attr('disabled', false); + contextMenu.find('#row-checkbox').attr('disabled', false); + contextMenu.find('#measure-checkbox').attr('disabled', true); + } + + //Add change events + contextMenu.find('#column-checkbox').unbind("change"); + contextMenu.find('#column-checkbox').change(function() { + currentFieldData.column = $(this).is(":checked"); + target.data('field-data', currentFieldData); + self.update_field_view(target); + self.internal_set_value(JSON.stringify(self.get_fields())); + }); + contextMenu.find('#row-checkbox').unbind("change"); + contextMenu.find('#row-checkbox').change(function() { + currentFieldData.row = $(this).is(":checked"); + target.data('field-data', currentFieldData); + self.update_field_view(target); + self.internal_set_value(JSON.stringify(self.get_fields())); + }); + contextMenu.find('#measure-checkbox').unbind("change"); + contextMenu.find('#measure-checkbox').change(function() { + currentFieldData.measure = $(this).is(":checked"); + target.data('field-data', currentFieldData); + self.update_field_view(target); + self.internal_set_value(JSON.stringify(self.get_fields())); + }); + contextMenu.show(); + + $(document).mouseup(function (e) { + var container = $(".context-menu"); + + if (!container.is(e.target) // if the target of the click isn't the container... + && container.has(e.target).length === 0) // ... nor a descendant of the container + { + container.hide(); + } + }); + + }) + ); + + self.$el.find('.delete-button').unbind("click"); + self.$el.find('.delete-button').click(function() { + $(this).closest('tr').remove(); + self.clean_join_nodes(); + self.internal_set_value(JSON.stringify(self.get_fields())); + self.load_classes(); + return false; + }) + }, + clean_join_nodes: function () { + var aliases = $.makeArray(this.$el.find(".field-list tbody tr").map(function (idx, el) { + var d = $(this).data('field-data'); + return d.table_alias; + })); + + this.$el.find(".field-list tbody tr").each(function (idx, el) { + var d = $(this).data('field-data'); + if (typeof d.join_node != 'undefined' && aliases.indexOf(d.join_node) === -1) { + $(this).remove(); + } + }); + }, + get_model_ids: function () { + var model_ids = {}; + this.$el.find(".field-list tbody tr").each(function (idx, el) { + var d = $(this).data('field-data'); + model_ids[d.table_alias] = d.model_id; + }); + return model_ids; + }, + get_model_data: function () { + var model_data = {}; + this.$el.find(".field-list tbody tr").each(function (idx, el) { + var d = $(this).data('field-data'); + model_data[d.table_alias] = {model_id: d.model_id, model_name: d.model_name}; + }); + return model_data; + }, + get_table_alias: function(field) { + if (typeof field.table_alias != 'undefined') { + return field.table_alias; + } else { + var model_ids = this.get_model_ids(); + var n = 0; + while (typeof model_ids["t" + n] != 'undefined') n++; + return "t" + n; + } + }, + add_field_and_join_node: function(field, join_node) { + var self = this; + if (join_node.join_node == -1) { + field.table_alias = self.get_table_alias(field); + join_node.join_node = field.table_alias; + self.add_field_to_table(join_node); + } else if (join_node.table_alias == -1) { + field.table_alias = self.get_table_alias(field); + join_node.table_alias = field.table_alias; + self.add_field_to_table(join_node); + } else { + field.table_alias = join_node.table_alias; + } + self.add_field_to_table(field); + self.internal_set_value(JSON.stringify(self.get_fields())); + self.load_classes(field); + }, + add_field: function(field) { + var data = field.data('field-data'); + var model = new instance.web.Model("ir.model"); + var model_ids = this.get_model_ids(); + var field_data = this.get_fields(); + var self = this; + model.call('get_join_nodes', [field_data, data], {context: new instance.web.CompoundContext()}).then(function(result) { + //self.$el.find(".search-bar").val(""); + //self.filter(""); + if (result.length == 1) { + self.add_field_and_join_node(data, result[0]); + self.internal_set_value(JSON.stringify(self.get_fields())); + //self.load_classes(data); + } else if (result.length > 1) { + var pop = new instance.bi_view_editor.JoinNodePopup(self); + pop.display_popup(result, self.get_model_data(), self.add_field_and_join_node.bind(self), data); + } else { + // first field and table only. + table_alias = self.get_table_alias(data); + data.table_alias = table_alias; + self.add_field_to_table(data); + self.internal_set_value(JSON.stringify(self.get_fields())); + self.load_classes(data); + } + }); + }, + get_fields: function() { + return $.makeArray(this.$el.find(".field-list tbody tr").map(function (idx, el) { + var d = $(this).data('field-data'); + d.description = $("input[name='label-" + d.id + "']").val(); + return d; + })); + }, + set_fields: function(values) { + this.activeModelMenus = []; + if (!values) { + values = []; + } + this.$el.find('.field-list tbody tr').remove(); + for(var i = 0; i < values.length; i++) { + this.add_field_to_table(values[i]); + } + this.load_classes(); + } + }); + instance.web.form.widgets.add('BVEEditor', 'instance.bi_view_editor.BVEEditor'); + + + local.JoinNodePopup = instance.web.Widget.extend({ + template: "JoinNodePopup", + start: function() { + var self = this; + }, + + display_popup: function(choices, model_data, callback, callback_data) { + var self = this; + this.renderElement(); + var joinnodes = this.$el.find('#join-nodes'); + joinnodes.empty(); + for (var i=0; i" + description+ "
") + .data('idx', i) + .wrap("

") + .parent()); + + } + var dialog = new instance.web.Dialog(this, { + dialogClass: 'oe_act_window', + title: "Choose Join Node", + }, this.$el).open(); + + joinnodes.find('a').click(function() { + callback(callback_data, choices[$(this).data('idx')]); + dialog.close(); + }) + + //dialog.on('closing', this, function (e){ + // self.check_exit(true); + //}); + //this.$buttonpane = dialog.$buttons; + this.start(); + } + }); +}; diff --git a/bi_view_editor/templates/assets_template.xml b/bi_view_editor/templates/assets_template.xml new file mode 100644 index 00000000..ad6014c5 --- /dev/null +++ b/bi_view_editor/templates/assets_template.xml @@ -0,0 +1,13 @@ + + + + + + + + diff --git a/bi_view_editor/templates/qweb_template.xml b/bi_view_editor/templates/qweb_template.xml new file mode 100644 index 00000000..a1859ac1 --- /dev/null +++ b/bi_view_editor/templates/qweb_template.xml @@ -0,0 +1,78 @@ + + + +
+

Please choose the join node

+
+
+
+
+ + + +
+ + +
+ +
+ +
+
+
+
+ + + + + + + + + + + +
NameModelOptions
+
+
+
+ +
    + +
  • Column
  • +
  • Row
  • +
  • Measure
  • + + +
+
+
+
diff --git a/bi_view_editor/views/bve_view.xml b/bi_view_editor/views/bve_view.xml new file mode 100644 index 00000000..3694506c --- /dev/null +++ b/bi_view_editor/views/bve_view.xml @@ -0,0 +1,70 @@ + + + + + + bve.view.tree + bve.view + + + + + + + + + bve.view.form + bve.view + +
+
+
+ +

+ +

+ + + + + + + + + + + +
+
+
+
+ + + Custom BI Views + ir.actions.act_window + bve.view + form + tree,form + +

+ Click to create a Custom Query Object. +

+ +

+
+
+ + + + +
+