tarteo
7 years ago
committed by
Andrea
90 changed files with 4375 additions and 9400 deletions
-
21bi_view_editor/README.rst
-
4bi_view_editor/__init__.py
-
11bi_view_editor/__manifest__.py
-
5bi_view_editor/hooks.py
-
174bi_view_editor/i18n/am.po
-
174bi_view_editor/i18n/ar.po
-
174bi_view_editor/i18n/bg.po
-
174bi_view_editor/i18n/bs.po
-
174bi_view_editor/i18n/ca.po
-
174bi_view_editor/i18n/cs.po
-
174bi_view_editor/i18n/da.po
-
174bi_view_editor/i18n/de.po
-
174bi_view_editor/i18n/el_GR.po
-
174bi_view_editor/i18n/en_GB.po
-
200bi_view_editor/i18n/es.po
-
174bi_view_editor/i18n/es_AR.po
-
174bi_view_editor/i18n/es_CL.po
-
174bi_view_editor/i18n/es_CO.po
-
174bi_view_editor/i18n/es_CR.po
-
174bi_view_editor/i18n/es_DO.po
-
174bi_view_editor/i18n/es_EC.po
-
174bi_view_editor/i18n/es_ES.po
-
174bi_view_editor/i18n/es_MX.po
-
174bi_view_editor/i18n/es_PE.po
-
174bi_view_editor/i18n/es_PY.po
-
174bi_view_editor/i18n/es_VE.po
-
174bi_view_editor/i18n/et.po
-
174bi_view_editor/i18n/eu.po
-
174bi_view_editor/i18n/fa.po
-
174bi_view_editor/i18n/fi.po
-
214bi_view_editor/i18n/fr.po
-
174bi_view_editor/i18n/fr_CA.po
-
174bi_view_editor/i18n/fr_CH.po
-
174bi_view_editor/i18n/gl.po
-
174bi_view_editor/i18n/gl_ES.po
-
174bi_view_editor/i18n/he.po
-
179bi_view_editor/i18n/hr.po
-
175bi_view_editor/i18n/hr_HR.po
-
174bi_view_editor/i18n/hu.po
-
174bi_view_editor/i18n/id.po
-
174bi_view_editor/i18n/it.po
-
174bi_view_editor/i18n/ja.po
-
174bi_view_editor/i18n/ko.po
-
174bi_view_editor/i18n/lt.po
-
174bi_view_editor/i18n/lt_LT.po
-
174bi_view_editor/i18n/lv.po
-
174bi_view_editor/i18n/mk.po
-
174bi_view_editor/i18n/mn.po
-
174bi_view_editor/i18n/nb.po
-
174bi_view_editor/i18n/nb_NO.po
-
195bi_view_editor/i18n/nl.po
-
174bi_view_editor/i18n/nl_BE.po
-
285bi_view_editor/i18n/nl_NL.po
-
176bi_view_editor/i18n/pl.po
-
174bi_view_editor/i18n/pt.po
-
175bi_view_editor/i18n/pt_BR.po
-
174bi_view_editor/i18n/pt_PT.po
-
174bi_view_editor/i18n/ro.po
-
174bi_view_editor/i18n/ru.po
-
174bi_view_editor/i18n/sk.po
-
192bi_view_editor/i18n/sl.po
-
174bi_view_editor/i18n/sr.po
-
174bi_view_editor/i18n/sr@latin.po
-
174bi_view_editor/i18n/sv.po
-
174bi_view_editor/i18n/th.po
-
174bi_view_editor/i18n/tr.po
-
187bi_view_editor/i18n/tr_TR.po
-
174bi_view_editor/i18n/uk.po
-
176bi_view_editor/i18n/vi.po
-
174bi_view_editor/i18n/vi_VN.po
-
174bi_view_editor/i18n/zh_CN.po
-
174bi_view_editor/i18n/zh_TW.po
-
4bi_view_editor/models/__init__.py
-
68bi_view_editor/models/bve_view.py
-
21bi_view_editor/models/ir_model.py
-
132bi_view_editor/models/models.py
-
33bi_view_editor/static/src/css/bve.css
-
305bi_view_editor/static/src/js/bi_view_editor.FieldList.js
-
52bi_view_editor/static/src/js/bi_view_editor.JoinNodeDialog.js
-
171bi_view_editor/static/src/js/bi_view_editor.ModelList.js
-
143bi_view_editor/static/src/js/bi_view_editor.js
-
445bi_view_editor/static/src/js/bve.js
-
183bi_view_editor/static/src/xml/bi_view_editor.xml
-
8bi_view_editor/templates/assets_template.xml
-
54bi_view_editor/templates/qweb_template.xml
-
4bi_view_editor/tests/__init__.py
-
5bi_view_editor/tests/test_bi_view.py
-
19bi_view_editor/views/bve_view.xml
-
4bi_view_editor/wizard/__init__.py
-
5bi_view_editor/wizard/wizard_ir_model_menu_create.py
@ -1,6 +1,4 @@ |
|||||
# -*- coding: utf-8 -*- |
|
||||
# Copyright 2015-2017 Onestein (<http://www.onestein.eu>) |
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
|
||||
|
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). |
||||
|
|
||||
from . import models |
from . import models |
||||
from . import wizard |
from . import wizard |
||||
|
@ -1,285 +0,0 @@ |
|||||
# Translation of Odoo Server. |
|
||||
# This file contains the translation of the following modules: |
|
||||
# * bi_view_editor |
|
||||
# |
|
||||
# Translators: |
|
||||
# Peter Hageman <hageman.p@gmail.com>, 2018 |
|
||||
msgid "" |
|
||||
msgstr "" |
|
||||
"Project-Id-Version: Odoo Server 10.0\n" |
|
||||
"Report-Msgid-Bugs-To: \n" |
|
||||
"POT-Creation-Date: 2018-01-25 03:45+0000\n" |
|
||||
"PO-Revision-Date: 2018-01-25 03:45+0000\n" |
|
||||
"Last-Translator: Peter Hageman <hageman.p@gmail.com>, 2018\n" |
|
||||
"Language-Team: Dutch (Netherlands) (https://www.transifex.com/oca/teams/23907/nl_NL/)\n" |
|
||||
"MIME-Version: 1.0\n" |
|
||||
"Content-Type: text/plain; charset=UTF-8\n" |
|
||||
"Content-Transfer-Encoding: \n" |
|
||||
"Language: nl_NL\n" |
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n" |
|
||||
|
|
||||
#. module: bi_view_editor |
|
||||
#: code:addons/bi_view_editor/models/bve_view.py:382 |
|
||||
#, python-format |
|
||||
msgid "%s (copy)" |
|
||||
msgstr "" |
|
||||
|
|
||||
#. module: bi_view_editor |
|
||||
#. openerp-web |
|
||||
#: code:addons/bi_view_editor/static/src/js/bve.js:32 |
|
||||
#, python-format |
|
||||
msgid "<b>Join</b> using the field" |
|
||||
msgstr "" |
|
||||
|
|
||||
#. module: bi_view_editor |
|
||||
#: model:ir.model.fields,field_description:bi_view_editor.field_bve_view_action_id |
|
||||
msgid "Action" |
|
||||
msgstr "" |
|
||||
|
|
||||
#. module: bi_view_editor |
|
||||
#: code:addons/bi_view_editor/models/bve_view.py:376 |
|
||||
#, python-format |
|
||||
msgid "BI View" |
|
||||
msgstr "" |
|
||||
|
|
||||
#. module: bi_view_editor |
|
||||
#: model:ir.model,name:bi_view_editor.model_bve_view |
|
||||
msgid "BI View Editor" |
|
||||
msgstr "" |
|
||||
|
|
||||
#. module: bi_view_editor |
|
||||
#. openerp-web |
|
||||
#: code:addons/bi_view_editor/static/src/js/bve.js:43 |
|
||||
#, python-format |
|
||||
msgid "Cancel" |
|
||||
msgstr "" |
|
||||
|
|
||||
#. module: bi_view_editor |
|
||||
#. openerp-web |
|
||||
#: code:addons/bi_view_editor/static/src/js/bve.js:41 |
|
||||
#, python-format |
|
||||
msgid "Choose join node" |
|
||||
msgstr "" |
|
||||
|
|
||||
#. module: bi_view_editor |
|
||||
#: model:ir.actions.act_window,help:bi_view_editor.action_bi_view_editor_view_form |
|
||||
msgid "Click to create a Custom Query Object." |
|
||||
msgstr "" |
|
||||
|
|
||||
#. module: bi_view_editor |
|
||||
#: model:ir.ui.view,arch_db:bi_view_editor.view_bi_view_editor_view_form |
|
||||
msgid "Create a Menu" |
|
||||
msgstr "" |
|
||||
|
|
||||
#. module: bi_view_editor |
|
||||
#: selection:bve.view,state:0 |
|
||||
msgid "Created" |
|
||||
msgstr "" |
|
||||
|
|
||||
#. module: bi_view_editor |
|
||||
#: model:ir.model.fields,field_description:bi_view_editor.field_bve_view_create_uid |
|
||||
msgid "Created by" |
|
||||
msgstr "Aangemaakt door" |
|
||||
|
|
||||
#. module: bi_view_editor |
|
||||
#: model:ir.model.fields,field_description:bi_view_editor.field_bve_view_create_date |
|
||||
msgid "Created on" |
|
||||
msgstr "Aangemaakt op" |
|
||||
|
|
||||
#. module: bi_view_editor |
|
||||
#: model:ir.ui.view,arch_db:bi_view_editor.view_bi_view_editor_view_tree |
|
||||
msgid "Custom BI View" |
|
||||
msgstr "" |
|
||||
|
|
||||
#. module: bi_view_editor |
|
||||
#: code:addons/bi_view_editor/models/bve_view.py:63 sql_constraint:bve.view:0 |
|
||||
#, python-format |
|
||||
msgid "Custom BI View names must be unique!" |
|
||||
msgstr "" |
|
||||
|
|
||||
#. module: bi_view_editor |
|
||||
#: model:ir.actions.act_window,name:bi_view_editor.action_bi_view_editor_view_form |
|
||||
#: model:ir.ui.menu,name:bi_view_editor.menu_bi_view_editor_view |
|
||||
msgid "Custom BI Views" |
|
||||
msgstr "" |
|
||||
|
|
||||
#. module: bi_view_editor |
|
||||
#: model:ir.ui.view,arch_db:bi_view_editor.view_bi_view_editor_view_form |
|
||||
msgid "Custom Object" |
|
||||
msgstr "" |
|
||||
|
|
||||
#. module: bi_view_editor |
|
||||
#: model:ir.ui.menu,name:bi_view_editor.menu_bi_view_editor_custom_reports |
|
||||
msgid "Custom Reports" |
|
||||
msgstr "" |
|
||||
|
|
||||
#. module: bi_view_editor |
|
||||
#: model:ir.model.fields,field_description:bi_view_editor.field_bve_view_data |
|
||||
msgid "Data" |
|
||||
msgstr "" |
|
||||
|
|
||||
#. module: bi_view_editor |
|
||||
#: model:ir.model.fields,field_description:bi_view_editor.field_bve_view_display_name |
|
||||
msgid "Display Name" |
|
||||
msgstr "Weergavenaam" |
|
||||
|
|
||||
#. module: bi_view_editor |
|
||||
#: selection:bve.view,state:0 |
|
||||
msgid "Draft" |
|
||||
msgstr "" |
|
||||
|
|
||||
#. module: bi_view_editor |
|
||||
#: model:ir.ui.view,arch_db:bi_view_editor.view_bi_view_editor_view_form |
|
||||
msgid "Generate BI View" |
|
||||
msgstr "" |
|
||||
|
|
||||
#. module: bi_view_editor |
|
||||
#: model:ir.model.fields,field_description:bi_view_editor.field_bve_view_group_ids |
|
||||
msgid "Groups" |
|
||||
msgstr "" |
|
||||
|
|
||||
#. module: bi_view_editor |
|
||||
#: model:ir.model.fields,field_description:bi_view_editor.field_bve_view_id |
|
||||
msgid "ID" |
|
||||
msgstr "ID" |
|
||||
|
|
||||
#. module: bi_view_editor |
|
||||
#: model:ir.model.fields,field_description:bi_view_editor.field_bve_view___last_update |
|
||||
msgid "Last Modified on" |
|
||||
msgstr "" |
|
||||
|
|
||||
#. module: bi_view_editor |
|
||||
#: model:ir.model.fields,field_description:bi_view_editor.field_bve_view_write_uid |
|
||||
msgid "Last Updated by" |
|
||||
msgstr "" |
|
||||
|
|
||||
#. module: bi_view_editor |
|
||||
#: model:ir.model.fields,field_description:bi_view_editor.field_bve_view_write_date |
|
||||
msgid "Last Updated on" |
|
||||
msgstr "" |
|
||||
|
|
||||
#. module: bi_view_editor |
|
||||
#: model:ir.model.fields,field_description:bi_view_editor.field_bve_view_model_name |
|
||||
msgid "Model name" |
|
||||
msgstr "" |
|
||||
|
|
||||
#. module: bi_view_editor |
|
||||
#: model:ir.model,name:bi_view_editor.model_ir_model |
|
||||
msgid "Models" |
|
||||
msgstr "" |
|
||||
|
|
||||
#. module: bi_view_editor |
|
||||
#: model:ir.model.fields,field_description:bi_view_editor.field_bve_view_name |
|
||||
msgid "Name" |
|
||||
msgstr "Naam" |
|
||||
|
|
||||
#. module: bi_view_editor |
|
||||
#: code:addons/bi_view_editor/models/models.py:42 |
|
||||
#, python-format |
|
||||
msgid "No data to be displayed." |
|
||||
msgstr "" |
|
||||
|
|
||||
#. module: bi_view_editor |
|
||||
#: code:addons/bi_view_editor/models/bve_view.py:285 |
|
||||
#, python-format |
|
||||
msgid "No data to process." |
|
||||
msgstr "" |
|
||||
|
|
||||
#. module: bi_view_editor |
|
||||
#: model:ir.model.fields,field_description:bi_view_editor.field_bve_view_note |
|
||||
#: model:ir.ui.view,arch_db:bi_view_editor.view_bi_view_editor_view_form |
|
||||
msgid "Notes" |
|
||||
msgstr "" |
|
||||
|
|
||||
#. module: bi_view_editor |
|
||||
#: model:ir.ui.view,arch_db:bi_view_editor.view_bi_view_editor_view_form |
|
||||
msgid "Open BI View" |
|
||||
msgstr "" |
|
||||
|
|
||||
#. module: bi_view_editor |
|
||||
#: model:ir.ui.view,arch_db:bi_view_editor.view_bi_view_editor_view_form |
|
||||
msgid "Query" |
|
||||
msgstr "" |
|
||||
|
|
||||
#. module: bi_view_editor |
|
||||
#: model:ir.ui.view,arch_db:bi_view_editor.view_bi_view_editor_view_form |
|
||||
msgid "Reset to Draft" |
|
||||
msgstr "" |
|
||||
|
|
||||
#. module: bi_view_editor |
|
||||
#: model:ir.ui.view,arch_db:bi_view_editor.view_bi_view_editor_view_form |
|
||||
msgid "Security" |
|
||||
msgstr "" |
|
||||
|
|
||||
#. module: bi_view_editor |
|
||||
#: model:ir.model.fields,field_description:bi_view_editor.field_bve_view_state |
|
||||
msgid "State" |
|
||||
msgstr "" |
|
||||
|
|
||||
#. module: bi_view_editor |
|
||||
#. openerp-web |
|
||||
#: code:addons/bi_view_editor/static/src/js/bve.js:26 |
|
||||
#, python-format |
|
||||
msgid "Use the field on model" |
|
||||
msgstr "" |
|
||||
|
|
||||
#. module: bi_view_editor |
|
||||
#: model:ir.model.fields,help:bi_view_editor.field_bve_view_data |
|
||||
msgid "" |
|
||||
"Use the special query builder to define the query to generate your report " |
|
||||
"dataset. NOTE: To be edited, the query should be in 'Draft' status." |
|
||||
msgstr "" |
|
||||
|
|
||||
#. module: bi_view_editor |
|
||||
#: model:ir.model.fields,help:bi_view_editor.field_bve_view_group_ids |
|
||||
msgid "" |
|
||||
"User groups allowed to see the generated report; if NO groups are specified " |
|
||||
"the report will be public for everyone." |
|
||||
msgstr "" |
|
||||
|
|
||||
#. module: bi_view_editor |
|
||||
#: model:ir.model.fields,field_description:bi_view_editor.field_bve_view_user_ids |
|
||||
msgid "Users" |
|
||||
msgstr "" |
|
||||
|
|
||||
#. module: bi_view_editor |
|
||||
#: model:ir.model.fields,field_description:bi_view_editor.field_bve_view_view_id |
|
||||
msgid "View" |
|
||||
msgstr "" |
|
||||
|
|
||||
#. module: bi_view_editor |
|
||||
#: code:addons/bi_view_editor/models/bve_view.py:420 |
|
||||
#, python-format |
|
||||
msgid "You cannot delete a created view! Reset the view to draft first." |
|
||||
msgstr "" |
|
||||
|
|
||||
#. module: bi_view_editor |
|
||||
#: model:ir.model,name:bi_view_editor.model_base |
|
||||
msgid "base" |
|
||||
msgstr "" |
|
||||
|
|
||||
#. module: bi_view_editor |
|
||||
#. openerp-web |
|
||||
#: code:addons/bi_view_editor/static/src/js/bve.js:32 |
|
||||
#, python-format |
|
||||
msgid "model" |
|
||||
msgstr "" |
|
||||
|
|
||||
#. module: bi_view_editor |
|
||||
#. openerp-web |
|
||||
#: code:addons/bi_view_editor/static/src/js/bve.js:30 |
|
||||
#, python-format |
|
||||
msgid "new" |
|
||||
msgstr "" |
|
||||
|
|
||||
#. module: bi_view_editor |
|
||||
#. openerp-web |
|
||||
#: code:addons/bi_view_editor/static/src/js/bve.js:32 |
|
||||
#, python-format |
|
||||
msgid "on " |
|
||||
msgstr "" |
|
||||
|
|
||||
#. module: bi_view_editor |
|
||||
#: model:ir.model,name:bi_view_editor.model_wizard_ir_model_menu_create |
|
||||
msgid "wizard.ir.model.menu.create" |
|
||||
msgstr "" |
|
@ -1,6 +1,4 @@ |
|||||
# -*- coding: utf-8 -*- |
|
||||
# Copyright 2015-2017 Onestein (<http://www.onestein.eu>) |
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
|
||||
|
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). |
||||
|
|
||||
from . import models |
from . import models |
||||
from . import bve_view |
from . import bve_view |
||||
|
@ -0,0 +1,305 @@ |
|||||
|
/* Copyright 2015-2018 Onestein (<http://www.onestein.eu>) |
||||
|
* License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). */
|
||||
|
|
||||
|
odoo.define('bi_view_editor.FieldList', function(require) { |
||||
|
"use strict"; |
||||
|
|
||||
|
var core = require('web.core'); |
||||
|
var qweb = core.qweb; |
||||
|
var Widget = require('web.Widget'); |
||||
|
|
||||
|
var FieldListContextMenu = Widget.extend({ |
||||
|
start: function() { |
||||
|
var res = this._super.apply(this, arguments); |
||||
|
this.$el.mouseleave(function() { |
||||
|
$(this).addClass('hidden'); |
||||
|
}); |
||||
|
return res; |
||||
|
}, |
||||
|
open: function(x, y) { |
||||
|
this.$el.css({ |
||||
|
'left': x + 'px', |
||||
|
'top': y + 'px' |
||||
|
}); |
||||
|
this.$el.removeClass('hidden'); |
||||
|
return _.extend({}, window.Backbone.Events); |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
var FieldListFieldContextMenu = FieldListContextMenu.extend({ |
||||
|
template: 'bi_view_editor.FieldList.FieldContextMenu', |
||||
|
open: function(x, y, field) { |
||||
|
this.$el.find('.checkbox-column').prop('checked', field.column); |
||||
|
this.$el.find('.checkbox-row').prop('checked', field.row); |
||||
|
this.$el.find('.checkbox-measure').prop('checked', field.measure); |
||||
|
this.$el.find('.checkbox-list').prop('checked', field.list); |
||||
|
|
||||
|
var measureable = |
||||
|
field.type === "float" || |
||||
|
field.type === "integer" || |
||||
|
field.type === "monetary" |
||||
|
; |
||||
|
|
||||
|
this.$el.find('.checkbox-column').attr('disabled', measureable); |
||||
|
this.$el.find('.checkbox-row').attr('disabled', measureable); |
||||
|
this.$el.find('.checkbox-measure').attr('disabled', !measureable); |
||||
|
this.$el.find('.checkbox-list').attr('disabled', false); |
||||
|
|
||||
|
var events = this._super(x, y, field); |
||||
|
this.$el.find('input').unbind('change'); |
||||
|
this.$el.find('input').change(function() { |
||||
|
var $checkbox = $(this); |
||||
|
var property = $checkbox.attr('data-for'); |
||||
|
field[property] = $checkbox.is(':checked'); |
||||
|
events.trigger('change', field); |
||||
|
}); |
||||
|
|
||||
|
return events; |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
var FieldListJoinContextMenu = FieldListContextMenu.extend({ |
||||
|
template: 'bi_view_editor.FieldList.JoinContextMenu', |
||||
|
open: function(x, y, node) { |
||||
|
this.$el.find('.checkbox-join-left').prop('checked', node.join_left); |
||||
|
|
||||
|
var events = this._super(x, y, node); |
||||
|
this.$el.find('input').unbind('change'); |
||||
|
this.$el.find('input').change(function() { |
||||
|
var $checkbox = $(this); |
||||
|
var property = $checkbox.attr('data-for'); |
||||
|
node[property] = $checkbox.is(':checked'); |
||||
|
events.trigger('change', node); |
||||
|
}); |
||||
|
return events; |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
var FieldList = Widget.extend({ |
||||
|
template: 'bi_view_editor.FieldList', |
||||
|
events: { |
||||
|
'click .delete-button': 'removeClicked', |
||||
|
'keyup input[name="description"]': 'keyupDescription' |
||||
|
}, |
||||
|
start: function() { |
||||
|
var res = this._super.apply(this, arguments); |
||||
|
this.contextmenu = new FieldListFieldContextMenu(this); |
||||
|
this.contextmenu.appendTo(this.$el); |
||||
|
this.contextmenu_join = new FieldListJoinContextMenu(this); |
||||
|
this.contextmenu_join.appendTo(this.$el); |
||||
|
this.$table = this.$el.find('tbody'); |
||||
|
this.mode = null; |
||||
|
return res; |
||||
|
}, |
||||
|
setMode: function(mode) { |
||||
|
if(mode === 'readonly') { |
||||
|
this.$el.find('input[type="text"]').attr('disabled', true); |
||||
|
this.$el.find(".delete-button:last").addClass('hidden'); |
||||
|
} else { |
||||
|
this.$el.find('input[type="text"]').removeAttr('disabled'); |
||||
|
this.$el.find(".delete-button:last").removeClass('hidden'); |
||||
|
} |
||||
|
this.mode = mode; |
||||
|
}, |
||||
|
get: function() { |
||||
|
return $.makeArray(this.$el.find("tbody tr").map(function () { |
||||
|
var field = $(this).data('field'); |
||||
|
field.description = $(this).find('input[name="description"]').val(); |
||||
|
return field; |
||||
|
})); |
||||
|
}, |
||||
|
getModelIds: function () { |
||||
|
var model_ids = {}; |
||||
|
this.$el.find("tbody tr").each(function () { |
||||
|
var data = $(this).data('field'); |
||||
|
model_ids[data.table_alias] = data.model_id; |
||||
|
}); |
||||
|
return model_ids; |
||||
|
}, |
||||
|
getModelData: function () { |
||||
|
var model_data = {}; |
||||
|
this.$el.find("tbody tr").each(function () { |
||||
|
var data = $(this).data('field'); |
||||
|
model_data[data.table_alias] = { |
||||
|
model_id: data.model_id, |
||||
|
model_name: data.model_name |
||||
|
}; |
||||
|
}); |
||||
|
return model_data; |
||||
|
}, |
||||
|
add: function(field) { |
||||
|
var self = this; |
||||
|
field.row = typeof field.row === 'undefined' ? false : field.row; |
||||
|
field.column = typeof field.column === 'undefined' ? false : field.column; |
||||
|
field.measure = typeof field.measure === 'undefined' ? false : field.measure; |
||||
|
field.list = typeof field.list === 'undefined' ? false : field.list; |
||||
|
field._id = typeof field._id === 'undefined' ? _.uniqueId('node_') : field._id; |
||||
|
if(field.join_node) { |
||||
|
field.join_left = typeof field.join_left === 'undefined' ? false : field.join_left; |
||||
|
} |
||||
|
|
||||
|
var i = 0; |
||||
|
var name = field.name; |
||||
|
while (this.get().filter(function(item) { |
||||
|
return item.name === field.name; |
||||
|
}).length > 0) { |
||||
|
field.name = name + '_' + i; |
||||
|
i++; |
||||
|
} |
||||
|
|
||||
|
// Render table row
|
||||
|
var $html = $(qweb.render(field.join_node ? 'bi_view_editor.JoinListItem' : 'bi_view_editor.FieldListItem', { |
||||
|
'field': field |
||||
|
})).data('field', field).contextmenu(function(e) { |
||||
|
var $item = $(this); |
||||
|
if(self.mode === 'readonly') { |
||||
|
return; |
||||
|
} |
||||
|
e.preventDefault(); |
||||
|
self.openContextMenu($item, e.pageX, e.pageY); |
||||
|
}); |
||||
|
|
||||
|
this.$el.find('tbody').append($html); |
||||
|
|
||||
|
this.$el.find(".delete-button").addClass('hidden'); |
||||
|
this.$el.find(".delete-button:last").removeClass('hidden'); |
||||
|
this.order(); |
||||
|
}, |
||||
|
remove: function(id) { |
||||
|
var $item = this.$el.find('tr[data-id="' + id + '"]'); |
||||
|
$item.remove(); |
||||
|
this.cleanJoinNodes(); |
||||
|
this.$el.find(".delete-button").addClass('hidden'); |
||||
|
this.$el.find(".delete-button:last").removeClass('hidden'); |
||||
|
this.trigger('removed', id); |
||||
|
}, |
||||
|
set: function(fields) { |
||||
|
var set_fields = fields; |
||||
|
if (!set_fields) { |
||||
|
set_fields = []; |
||||
|
} |
||||
|
this.$el.find('tbody tr').remove(); |
||||
|
for(var i = 0; i < set_fields.length; i++) { |
||||
|
this.add(set_fields[i]); |
||||
|
} |
||||
|
this.$el.find(".delete-button").addClass('hidden'); |
||||
|
this.$el.find(".delete-button:last").removeClass('hidden'); |
||||
|
}, |
||||
|
openContextMenu: function($item, x, y) { |
||||
|
var field = $item.data('field'); |
||||
|
var contextmenu = field.join_node ? this.contextmenu_join : this.contextmenu; |
||||
|
// Temporary disable contextmenu for join node (until left join is implemented)
|
||||
|
if (field.join_node) { |
||||
|
return; |
||||
|
} |
||||
|
contextmenu.open(x - 20, y - 20, $item.data('field')).on('change', function(f) { |
||||
|
$item.data('field', f); |
||||
|
this.refreshItem($item); |
||||
|
this.trigger('updated'); |
||||
|
}.bind(this)); |
||||
|
}, |
||||
|
refreshItem: function($item) { |
||||
|
var data = $item.data('field'); |
||||
|
var $attributes = $item.find('span[data-for], img[data-for]'); |
||||
|
$.each($attributes, function() { |
||||
|
var $attribute = $(this); |
||||
|
var value = data[$attribute.attr('data-for')]; |
||||
|
if(value) { |
||||
|
$attribute.removeClass('hidden'); |
||||
|
} else { |
||||
|
$attribute.addClass('hidden'); |
||||
|
} |
||||
|
}); |
||||
|
}, |
||||
|
removeClicked: function(e) { |
||||
|
var $button = $(e.currentTarget); |
||||
|
var id = $button.attr('data-id'); |
||||
|
this.remove(id); |
||||
|
}, |
||||
|
keyupDescription: function() { |
||||
|
this.trigger('updated'); |
||||
|
}, |
||||
|
cleanJoinNodes: function() { |
||||
|
var aliases = $.makeArray(this.$el.find("tbody tr").map(function () { |
||||
|
var data = $(this).data('field'); |
||||
|
return data.table_alias.localeCompare(data.join_node) > 0 ? data.join_node : data.table_alias; |
||||
|
})); |
||||
|
|
||||
|
this.$el.find("tbody tr").each(function () { |
||||
|
var data = $(this).data('field'); |
||||
|
if (typeof data.join_node === 'undefined') { |
||||
|
return; |
||||
|
} |
||||
|
var no_alias = data.table_alias.localeCompare(data.join_node) > 0 && |
||||
|
aliases.indexOf(data.table_alias) === -1; |
||||
|
if (no_alias || |
||||
|
aliases.indexOf(data.join_node) === -1) { |
||||
|
$(this).remove(); |
||||
|
} |
||||
|
}); |
||||
|
}, |
||||
|
getOrder: function() { |
||||
|
var items = this.get(); |
||||
|
var ordered = items.sort(function(a, b) { |
||||
|
var res = a.table_alias.localeCompare(b.table_alias); |
||||
|
if (res === 0) { |
||||
|
var both_join_node = a.join_node && b.join_node; |
||||
|
var both_not_join_node = !a.join_node && !b.join_node; |
||||
|
if(both_join_node || both_not_join_node) { |
||||
|
return 0; |
||||
|
} else if(!a.join_node && b.join_node) { |
||||
|
if(b.table_alias.localeCompare(b.join_node) > 0) { |
||||
|
return 1; |
||||
|
} |
||||
|
return -1; |
||||
|
} else if(a.join_node && !b.join_node) { |
||||
|
if(a.table_alias.localeCompare(a.join_node) > 0) { |
||||
|
return -1; |
||||
|
} |
||||
|
return 1; |
||||
|
} |
||||
|
} |
||||
|
return res; |
||||
|
}); |
||||
|
|
||||
|
var res = []; |
||||
|
_.each(ordered, function(item) { |
||||
|
var already_exists = _.findIndex(res, function(f) { |
||||
|
return f._id === item._id; |
||||
|
}) !== -1; |
||||
|
if(already_exists) { |
||||
|
return; |
||||
|
} |
||||
|
res.push(item); |
||||
|
if(item.join_node) { |
||||
|
var join_node_fields = _.filter(ordered, function(f) { |
||||
|
return f.table_alias === item.join_node && !f.join_node; |
||||
|
}); |
||||
|
res = _.union(res, join_node_fields); |
||||
|
} |
||||
|
}); |
||||
|
return res; |
||||
|
}, |
||||
|
order: function() { |
||||
|
var order = this.getOrder(); |
||||
|
var $rows = this.$el.find("tbody tr"); |
||||
|
|
||||
|
$rows.sort(function(a, b) { |
||||
|
var a_index = _.findIndex(order, function(item) { |
||||
|
return item._id === $(a).data('field')._id; |
||||
|
}); |
||||
|
var b_index = _.findIndex(order, function(item) { |
||||
|
return item._id === $(b).data('field')._id; |
||||
|
}); |
||||
|
return a_index - b_index; |
||||
|
}).appendTo(this.$el.find("tbody")); |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
return { |
||||
|
'FieldList': FieldList, |
||||
|
'FieldListContextMenu': FieldListContextMenu, |
||||
|
'FieldListFieldContextMenu': FieldListFieldContextMenu, |
||||
|
'FieldListJoinContextMenu': FieldListJoinContextMenu |
||||
|
}; |
||||
|
}); |
@ -0,0 +1,52 @@ |
|||||
|
/* Copyright 2015-2018 Onestein (<http://www.onestein.eu>) |
||||
|
* License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). */
|
||||
|
|
||||
|
odoo.define('bi_view_editor.JoinNodeDialog', function (require) { |
||||
|
"use strict"; |
||||
|
|
||||
|
var Dialog = require("web.Dialog"); |
||||
|
var core = require('web.core'); |
||||
|
var qweb = core.qweb; |
||||
|
var _t = core._t; |
||||
|
|
||||
|
var JoinNodeDialog = Dialog.extend({ |
||||
|
xmlDependencies: Dialog.prototype.xmlDependencies.concat([ |
||||
|
'/bi_view_editor/static/src/xml/bi_view_editor.xml' |
||||
|
]), |
||||
|
events: { |
||||
|
"click li": "choiceClicked", |
||||
|
}, |
||||
|
init: function(parent, options, choices, model_data) { |
||||
|
this.choices = choices; |
||||
|
// Prepare data for view
|
||||
|
for (var i = 0; i < choices.length; i++) { |
||||
|
if (choices[i].join_node !== -1 && choices[i].table_alias !== -1) { |
||||
|
choices[i].model_name = model_data[choices[i].table_alias].model_name; |
||||
|
} |
||||
|
choices[i].index = i; |
||||
|
} |
||||
|
|
||||
|
var defaults = _.defaults(options || {}, { |
||||
|
title: _t("Join..."), |
||||
|
dialogClass: 'oe_act_window', |
||||
|
$content: qweb.render('bi_view_editor.JoinNodeDialog', { |
||||
|
'choices': choices |
||||
|
}), |
||||
|
buttons: [{ |
||||
|
text: _t("Cancel"), |
||||
|
classes: "btn-default o_form_button_cancel", |
||||
|
close: true |
||||
|
}], |
||||
|
}); |
||||
|
this._super(parent, defaults); |
||||
|
}, |
||||
|
choiceClicked: function(e) { |
||||
|
this.trigger('chosen', { |
||||
|
choice: this.choices[$(e.currentTarget).attr('data-index')] |
||||
|
}); |
||||
|
this.close(); |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
return JoinNodeDialog; |
||||
|
}); |
@ -0,0 +1,171 @@ |
|||||
|
/* Copyright 2015-2018 Onestein (<http://www.onestein.eu>) |
||||
|
* License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). */
|
||||
|
|
||||
|
odoo.define('bi_view_editor.ModelList', function (require) { |
||||
|
"use strict"; |
||||
|
|
||||
|
var Widget = require('web.Widget'); |
||||
|
var core = require('web.core'); |
||||
|
var session = require('web.session'); |
||||
|
var qweb = core.qweb; |
||||
|
|
||||
|
var ModelList = Widget.extend({ |
||||
|
template: 'bi_view_editor.ModelList', |
||||
|
events: { |
||||
|
'keyup .search-bar > input': 'filterChanged' |
||||
|
}, |
||||
|
init: function(parent) { |
||||
|
var res = this._super(parent); |
||||
|
this.active_models = []; |
||||
|
this.cache_fields = {}; |
||||
|
this.current_filter = ''; |
||||
|
this.mode = null; |
||||
|
return res; |
||||
|
}, |
||||
|
setMode: function(mode) { |
||||
|
if(mode === 'readonly') { |
||||
|
this.$el.find('.search-bar').attr('disabled', true); |
||||
|
this.$el.find('.class-list, .class').addClass('readonly'); |
||||
|
} else { |
||||
|
this.$el.find('.search-bar').attr('disabled', false); |
||||
|
this.$el.find('.class-list, .class').removeClass('readonly'); |
||||
|
} |
||||
|
this.mode = mode; |
||||
|
}, |
||||
|
isActive: function(id) { |
||||
|
return this.active_models.indexOf(id) !== -1; |
||||
|
}, |
||||
|
removeAsActive: function(id) { |
||||
|
var i = this.active_models.indexOf(id); |
||||
|
this.active_models.splice(i, 1); |
||||
|
}, |
||||
|
addAsActive: function(id) { |
||||
|
this.active_models.push(id); |
||||
|
}, |
||||
|
loadModels: function(model_ids) { |
||||
|
if (model_ids) { |
||||
|
return this._rpc({ |
||||
|
model: 'ir.model', |
||||
|
method: 'get_related_models', |
||||
|
args: [model_ids], |
||||
|
context: { |
||||
|
lang: session.user_context.lang |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
return this._rpc({ |
||||
|
model: 'ir.model', |
||||
|
method: 'get_models', |
||||
|
context: { |
||||
|
lang: session.user_context.lang |
||||
|
} |
||||
|
}); |
||||
|
}, |
||||
|
loadFields: function(model_id) { |
||||
|
if (!(model_id in this.cache_fields)) { |
||||
|
var deferred = this._rpc({ |
||||
|
model: 'ir.model', |
||||
|
method: 'get_fields', |
||||
|
args: [model_id], |
||||
|
context: { |
||||
|
lang: session.user_context.lang |
||||
|
} |
||||
|
}); |
||||
|
this.cache_fields[model_id] = deferred; |
||||
|
} |
||||
|
return this.cache_fields[model_id]; |
||||
|
}, |
||||
|
populateModels: function (models) { |
||||
|
var self = this; |
||||
|
this.$el.find(".class-list").html(''); |
||||
|
|
||||
|
_.each(models, function(model) { |
||||
|
var $html = $(qweb.render('bi_view_editor.ModelListItem', { |
||||
|
'id': model.id, |
||||
|
'model': model.model, |
||||
|
'name': model.name |
||||
|
})); |
||||
|
$html.find('.class').data('model', model).click(function() { |
||||
|
self.modelClicked($(this)); |
||||
|
}); |
||||
|
self.$el.find(".class-list").append($html); |
||||
|
|
||||
|
if (self.isActive(model.id)) { |
||||
|
self.loadFields(model.id).done(function(fields) { |
||||
|
self.populateFields(fields, model.id); |
||||
|
}); |
||||
|
} |
||||
|
}); |
||||
|
}, |
||||
|
populateFields: function(fields, model_id) { |
||||
|
var self = this; |
||||
|
if(!model_id && fields.length === 0) { |
||||
|
return; |
||||
|
} |
||||
|
var data_model_id = model_id; |
||||
|
if(!data_model_id) { |
||||
|
data_model_id = fields[0].model_id; |
||||
|
} |
||||
|
var $model_item = this.$el.find(".class[data-id='" + data_model_id + "']"); |
||||
|
_.each(fields, function(field) { |
||||
|
var $field = $(qweb.render('bi_view_editor.ModelListFieldItem', { |
||||
|
name: field.name, |
||||
|
description: field.description |
||||
|
})).data('field', field).click(function() { |
||||
|
self.fieldClicked($(this)); |
||||
|
}).draggable({ |
||||
|
'revert': 'invalid', |
||||
|
'scroll': false, |
||||
|
'helper': 'clone', |
||||
|
'appendTo': 'body', |
||||
|
'containment': 'window' |
||||
|
}); |
||||
|
$model_item.after($field); |
||||
|
|
||||
|
}); |
||||
|
}, |
||||
|
modelClicked: function($el) { |
||||
|
if (this.mode === 'readonly') { |
||||
|
return; |
||||
|
} |
||||
|
var model = $el.data('model'); |
||||
|
$el.parent().find('.field').remove(); |
||||
|
if(this.isActive(model.id)) { |
||||
|
this.removeAsActive(model.id); |
||||
|
} else { |
||||
|
this.addAsActive(model.id); |
||||
|
this.loadFields(model.id).done(function(fields) { |
||||
|
this.populateFields(fields, model.id); |
||||
|
}.bind(this)); |
||||
|
} |
||||
|
}, |
||||
|
fieldClicked: function($el) { |
||||
|
if (this.mode === 'readonly') { |
||||
|
return; |
||||
|
} |
||||
|
this.trigger('field_clicked', $el.data('field')); |
||||
|
}, |
||||
|
filterChanged: function(e) { |
||||
|
var $input = $(e.target); |
||||
|
this.filter($input.val()); |
||||
|
}, |
||||
|
filter: function(value) { |
||||
|
this.active_models = []; |
||||
|
this.$el.find('.field').remove(); |
||||
|
var val = typeof value === 'undefined' ? this.current_filter : value.toLowerCase(); |
||||
|
this.$el.find(".class").each(function() { |
||||
|
var data = $(this).data('model'); |
||||
|
if (data.name.toLowerCase().indexOf(val) === -1 && |
||||
|
data.model.toLowerCase().indexOf(val) === -1) { |
||||
|
$(this).addClass('hidden'); |
||||
|
} else { |
||||
|
$(this).removeClass('hidden'); |
||||
|
} |
||||
|
}); |
||||
|
this.current_filter = val; |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
return ModelList; |
||||
|
|
||||
|
}); |
@ -0,0 +1,143 @@ |
|||||
|
/* Copyright 2015-2018 Onestein (<http://www.onestein.eu>) |
||||
|
* License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). */
|
||||
|
|
||||
|
odoo.define('bi_view_editor', function (require) { |
||||
|
"use strict"; |
||||
|
|
||||
|
var JoinNodeDialog = require('bi_view_editor.JoinNodeDialog'); |
||||
|
var ModelList = require('bi_view_editor.ModelList'); |
||||
|
var FieldList = require('bi_view_editor.FieldList').FieldList; |
||||
|
|
||||
|
var AbstractField = require('web.AbstractField'); |
||||
|
var Data = require('web.data'); |
||||
|
var field_registry = require('web.field_registry'); |
||||
|
|
||||
|
var BiViewEditor = AbstractField.extend({ |
||||
|
template: "bi_view_editor.Frame", |
||||
|
events: { |
||||
|
"click .clear-btn": "clear" |
||||
|
}, |
||||
|
start: function() { |
||||
|
var self = this; |
||||
|
var res = this._super.apply(this, arguments); |
||||
|
|
||||
|
// Init ModelList
|
||||
|
this.model_list = new ModelList(this); |
||||
|
this.model_list.appendTo(this.$(".body > .left")); |
||||
|
this.model_list.on('field_clicked', this, function(field) { |
||||
|
self.addField(_.extend({}, field)); |
||||
|
}); |
||||
|
|
||||
|
// Init FieldList
|
||||
|
this.field_list = new FieldList(this); |
||||
|
this.field_list.appendTo(this.$(".body > .right")); |
||||
|
this.field_list.on('removed', this, this.fieldListRemoved); |
||||
|
this.field_list.on('updated', this, this.fieldListChanged); |
||||
|
|
||||
|
this.$el.find(".body > .right").droppable({ |
||||
|
accept: "div.class-list div.field", |
||||
|
drop: function (event, ui) { |
||||
|
self.addField(_.extend({}, ui.draggable.data('field'))); |
||||
|
ui.draggable.draggable('option', 'revert', false); |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
this.on("change:effective_readonly", this, function() { |
||||
|
this.updateMode(); |
||||
|
}); |
||||
|
this.renderValue(); |
||||
|
this.loadAndPopulateModelList(); |
||||
|
this.updateMode(); |
||||
|
return res; |
||||
|
}, |
||||
|
clear: function() { |
||||
|
if (this.mode !== 'readonly') { |
||||
|
this.field_list.set([]); |
||||
|
this.loadAndPopulateModelList(); |
||||
|
this._setValue(JSON.stringify(this.field_list.get())); |
||||
|
} |
||||
|
}, |
||||
|
fieldListChanged: function() { |
||||
|
this._setValue(JSON.stringify(this.field_list.get())); |
||||
|
}, |
||||
|
fieldListRemoved: function() { |
||||
|
this.loadAndPopulateModelList(); |
||||
|
this._setValue(JSON.stringify(this.field_list.get())); |
||||
|
}, |
||||
|
renderValue: function() { |
||||
|
this.field_list.set(JSON.parse(this.value)); |
||||
|
}, |
||||
|
updateMode: function () { |
||||
|
if (this.mode === 'readonly') { |
||||
|
this.$el.find('.clear-btn').addClass('hidden'); |
||||
|
this.$el.find(".body .right").droppable("option", "disabled", true); |
||||
|
} else { |
||||
|
this.$el.find('.clear-btn').removeClass('hidden'); |
||||
|
this.$el.find('.body .right').droppable('option', 'disabled', false); |
||||
|
} |
||||
|
this.field_list.setMode(this.mode); |
||||
|
this.model_list.setMode(this.mode); |
||||
|
}, |
||||
|
loadAndPopulateModelList: function() { |
||||
|
var model_ids = null; |
||||
|
if (this.field_list.get().length > 0) { |
||||
|
model_ids = this.field_list.getModelIds(); |
||||
|
} |
||||
|
this.model_list.loadModels(model_ids).done(function(models) { |
||||
|
this.model_list.populateModels(models); |
||||
|
}.bind(this)); |
||||
|
}, |
||||
|
getTableAlias: function(field) { |
||||
|
if (typeof field.table_alias === 'undefined') { |
||||
|
var model_ids = this.field_list.getModelIds(); |
||||
|
var n = 0; |
||||
|
while (typeof model_ids["t" + n] !== 'undefined') { |
||||
|
n++; |
||||
|
} |
||||
|
return "t" + n; |
||||
|
} |
||||
|
return field.table_alias; |
||||
|
}, |
||||
|
addFieldAndJoinNode: function(field, join_node) { |
||||
|
if (join_node.join_node === -1 || join_node.table_alias === -1) { |
||||
|
field.table_alias = this.getTableAlias(field); |
||||
|
if (join_node.join_node === -1) { |
||||
|
join_node.join_node = field.table_alias; |
||||
|
} else { |
||||
|
join_node.table_alias = field.table_alias; |
||||
|
} |
||||
|
this.field_list.add(join_node); |
||||
|
} else { |
||||
|
field.table_alias = join_node.table_alias; |
||||
|
} |
||||
|
|
||||
|
this.field_list.add(field); |
||||
|
this.loadAndPopulateModelList(); |
||||
|
this._setValue(JSON.stringify(this.field_list.get())); |
||||
|
}, |
||||
|
addField: function(field) { |
||||
|
var data = _.extend({}, field); |
||||
|
var model = new Data.DataSet(this, "ir.model"); |
||||
|
var field_data = this.field_list.get(); |
||||
|
model.call('get_join_nodes', [field_data, data]).then(function(result) { |
||||
|
if (result.length === 1) { |
||||
|
this.addFieldAndJoinNode(data, result[0]); |
||||
|
} else if (result.length > 1) { |
||||
|
var dialog = new JoinNodeDialog(this, {}, result, this.field_list.getModelData()); |
||||
|
dialog.open().on('chosen', this, function(e) { |
||||
|
this.addFieldAndJoinNode(data, e.choice); |
||||
|
}); |
||||
|
} else { |
||||
|
var table_alias = this.getTableAlias(data); |
||||
|
data.table_alias = table_alias; |
||||
|
this.field_list.add(data); |
||||
|
this.loadAndPopulateModelList(); |
||||
|
this._setValue(JSON.stringify(this.field_list.get())); |
||||
|
} |
||||
|
}.bind(this)); |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
field_registry.add('BVEEditor', BiViewEditor); |
||||
|
|
||||
|
}); |
@ -1,445 +0,0 @@ |
|||||
odoo.define('bi_view_editor', function (require) { |
|
||||
"use strict"; |
|
||||
|
|
||||
var Core = require("web.core"); |
|
||||
var FormCommon = require('web.form_common'); |
|
||||
var Model = require('web.Model'); |
|
||||
var Data = require('web.data'); |
|
||||
var Widget = require('web.Widget'); |
|
||||
var Dialog = require("web.Dialog"); |
|
||||
var _t = Core._t; |
|
||||
|
|
||||
var JoinNodePopup = 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<choices.length; i++) { |
|
||||
var description = ""; |
|
||||
if (choices[i].join_node !== -1 && choices[i].table_alias !== -1) { |
|
||||
description = _t("Use the field on model") + " <b>" + model_data[choices[i].table_alias].model_name + "</b>"; |
|
||||
} else { |
|
||||
var new_str = ""; |
|
||||
if (choices[i].join_node !== -1) { |
|
||||
new_str = "<b>" + _t("new") + "</b> "; |
|
||||
} |
|
||||
description = _t("<b>Join</b> using the field") + " <u><b>" + choices[i].description + "</b></u> " + _t("on ") + new_str + _t("model") +" <b>" + choices[i].model_name + "</b>"; |
|
||||
} |
|
||||
joinnodes.append($('<a><input type="radio">' + description+ '</a>') |
|
||||
.data('idx', i) |
|
||||
.wrap('<p></p>') |
|
||||
.parent()); |
|
||||
} |
|
||||
var dialog = new Dialog(this, { |
|
||||
dialogClass: 'oe_act_window', |
|
||||
title: _t("Choose join node"), |
|
||||
$content: this.$el, |
|
||||
buttons: [{text: _t("Cancel"), |
|
||||
classes: "btn-default o_form_button_cancel", |
|
||||
close: true |
|
||||
}] |
|
||||
}).open(); |
|
||||
|
|
||||
joinnodes.find('a').click(function() { |
|
||||
callback(callback_data, choices[$(this).data('idx')]); |
|
||||
dialog.close(); |
|
||||
}); |
|
||||
|
|
||||
this.start(); |
|
||||
} |
|
||||
}); |
|
||||
|
|
||||
var BiViewEditor = FormCommon.AbstractField.extend({ |
|
||||
template: "BVEEditor", |
|
||||
activeModelMenus: [], |
|
||||
currentFilter: "", |
|
||||
init: function() { |
|
||||
this._super.apply(this, arguments); |
|
||||
}, |
|
||||
start: function() { |
|
||||
this._super(); |
|
||||
this.on("change:effective_readonly", this, function() { |
|
||||
this.display_field(); |
|
||||
this.render_value(); |
|
||||
}); |
|
||||
this.display_field(); |
|
||||
this.render_value(); |
|
||||
}, |
|
||||
display_field: function () { |
|
||||
var self = this; |
|
||||
this.$el.find(".body .right").droppable({ |
|
||||
accept: "div.class-list div.field", |
|
||||
drop: function (event, ui) { |
|
||||
self.add_field(ui.draggable); |
|
||||
ui.draggable.draggable('option', 'revert', false ); |
|
||||
} |
|
||||
}); |
|
||||
if (!this.get("effective_readonly")) { |
|
||||
this.$el.find('.search-bar').attr('disabled', false); |
|
||||
this.$el.find('.class-list').css('opacity', '1'); |
|
||||
this.$el.find('.class-list .class').css('cursor', 'pointer'); |
|
||||
this.$el.find(".body .right").droppable("option", "disabled", false); |
|
||||
this.$el.find('#clear').css('display', 'inline-block').click(function () { |
|
||||
self.set_fields([]); |
|
||||
self.internal_set_value('[]'); |
|
||||
}); |
|
||||
this.$el.find('.search-bar input').keyup(function(e) { |
|
||||
//Local filter
|
|
||||
self.filter($(this).val()); |
|
||||
}); |
|
||||
} else { |
|
||||
this.$el.find(".body .right").droppable("option", "disabled", true); |
|
||||
this.$el.find('#clear').css('display', 'none'); |
|
||||
this.$el.find('.search-bar').attr('disabled', true); |
|
||||
this.$el.find('.class-list').css('opacity', '.35'); |
|
||||
this.$el.find('.class-list .class').css('cursor', 'default'); |
|
||||
} |
|
||||
}, |
|
||||
filter: function(val) { |
|
||||
val = (typeof val !== 'undefined') ? val.toLowerCase() : this.currentFilter; |
|
||||
this.currentFilter = val; |
|
||||
this.$el.find(".class-list .class-container").each(function() { |
|
||||
var modelData = $(this).find(".class").data('model-data'); |
|
||||
//TODO: filter on all model fields (name, technical name, etc)
|
|
||||
|
|
||||
if(typeof modelData === 'undefined' || (modelData.name.toLowerCase().indexOf(val) === -1 && modelData.model.toLowerCase().indexOf(val) === -1)) |
|
||||
$(this).hide(); |
|
||||
else |
|
||||
$(this).show(); |
|
||||
}); |
|
||||
}, |
|
||||
get_field_icons: function(field) { |
|
||||
var icons = ""; |
|
||||
if(field.column) |
|
||||
icons += "<span class='fa fa-columns' title='Column'></span> "; |
|
||||
if(field.row) |
|
||||
icons += "<span class='fa fa-bars' title='Row'></span> "; |
|
||||
if(field.measure) |
|
||||
icons += "<span class='fa fa-bar-chart-o' title='Measure'></span> "; |
|
||||
if(field.list) |
|
||||
icons += "<span class='fa fa-list' title='List'></span> "; |
|
||||
|
|
||||
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 Model("ir.model"); |
|
||||
if (this.$el.find(".field-list tbody tr").length > 0) { |
|
||||
model.call("get_related_models", [this.get_model_ids()], { context: new Data.CompoundContext() }).then(function(result) { |
|
||||
self.show_classes(result); |
|
||||
}); |
|
||||
} else { |
|
||||
model.call("get_models", { context: new Data.CompoundContext() }).then(function(result) { |
|
||||
self.show_classes(result); |
|
||||
}); |
|
||||
} |
|
||||
}, |
|
||||
show_classes: function (result) { |
|
||||
var self = this; |
|
||||
var model = new 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'; |
|
||||
function addField() { |
|
||||
if (!self.get("effective_readonly")) { |
|
||||
self.add_field($(this)); |
|
||||
} |
|
||||
} |
|
||||
function clickHandler(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 Data.CompoundContext() }).then(function(result) { |
|
||||
for (var i = 0; i < result.length; i++) { |
|
||||
classel.find("#bve-field-" + result[i].name).remove(); |
|
||||
self._render_field(self, i, result, classel, addField) |
|
||||
} |
|
||||
}); |
|
||||
$(this).data('bve-processed', true); |
|
||||
} |
|
||||
} |
|
||||
function renderFields(result) { |
|
||||
if (typeof(result[0]) !== 'undefined') { |
|
||||
var item = self.$el.find(".class-list #bve-class-" + result[0].model_id); |
|
||||
for (var o = 0; o < result.length; o++) { |
|
||||
self._render_field(self, o, result, item, addField) |
|
||||
} |
|
||||
item.data('bve-processed', true); |
|
||||
} |
|
||||
} |
|
||||
for (var i = 0; i < result.length; i++) { |
|
||||
var item = $("<div style=\"" + css + "\" class=\"class\" title=\"" + result[i].model + "\" id=\"bve-class-" + result[i].id + "\">" + result[i].name + "</div>") |
|
||||
.data('model-data', result[i]) |
|
||||
.click(clickHandler) |
|
||||
.wrap("<div class=\"class-container\"></div>").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 Data.CompoundContext() }).then(renderFields); |
|
||||
} |
|
||||
self.filter(); |
|
||||
} |
|
||||
|
|
||||
}, |
|
||||
_render_field(_self, _index, _result, _item, _addField) { |
|
||||
if(_self.$el.find(".field-list tbody [name=label-" + _result[_index].id + "]").length > 0) return; |
|
||||
_item.after($("<div class=\"field\" title=\"" + _result[_index].name + "\" id=\"bve-field-" + _result[_index].name + "\">" + _result[_index].description + "</div>") |
|
||||
.data('field-data', _result[_index]) |
|
||||
.click(_addField) |
|
||||
.draggable({ |
|
||||
'revert': 'invalid', |
|
||||
'scroll': false, |
|
||||
'helper': 'clone', |
|
||||
'appendTo': 'body', |
|
||||
'containment': 'window' |
|
||||
}) |
|
||||
); |
|
||||
}, |
|
||||
set_checkbox: function(check, identifier, _contextMenu) { |
|
||||
if(check) |
|
||||
_contextMenu.find(identifier).attr('checked', true); |
|
||||
else |
|
||||
_contextMenu.find(identifier).attr('checked', false); |
|
||||
}, |
|
||||
_false_if_undefined: function(to_check) { |
|
||||
if (typeof to_check === 'undefined') return false; |
|
||||
return to_check; |
|
||||
}, |
|
||||
_true_if_undefined: function(to_check) { |
|
||||
if (typeof to_check === 'undefined') return true; |
|
||||
return to_check; |
|
||||
}, |
|
||||
add_field_to_table: function(data, options) { |
|
||||
var self = this; |
|
||||
data.row = self._false_if_undefined(data.row); |
|
||||
data.column = self._false_if_undefined(data.column); |
|
||||
data.measure = self._false_if_undefined(data.measure); |
|
||||
data.list = self._true_if_undefined(data.list); |
|
||||
|
|
||||
var n = 1; |
|
||||
var name = data.name; |
|
||||
function checkNameMatches(el) { return el.name === data.name;} |
|
||||
while ($.grep(self.get_fields(), checkNameMatches).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 = "<span id=\"delete-" + data.id + "\" class=\"delete-button fa fa-trash-o\"/>"; |
|
||||
disabled = ""; |
|
||||
} |
|
||||
|
|
||||
self.$el.find(".field-list tbody") |
|
||||
.append($("<tr class=\"" + classes + "\"><td><input " + disabled + "title=\"" + data.name + " (" + data.model + ")\" type=\"text\" name=\"label-" + data.id + "\" value=\"" + data.description + "\"/></td><td>" + data.model_name + "</td><td>" + self.get_field_icons(data) + "</td><td>" + delete_button + "</td></tr>") |
|
||||
.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
|
|
||||
self.set_checkbox(currentFieldData.column, '#column-checkbox', contextMenu); |
|
||||
self.set_checkbox(currentFieldData.row, '#row-checkbox', contextMenu); |
|
||||
self.set_checkbox(currentFieldData.measure, '#measure-checkbox', contextMenu); |
|
||||
self.set_checkbox(currentFieldData.list, '#list-checkbox', contextMenu); |
|
||||
|
|
||||
var to_disable = false; |
|
||||
if(currentFieldData.type === "float" || currentFieldData.type === "integer" || currentFieldData.type === "monetary") to_disable = true; |
|
||||
var identifiers = [['#column-checkbox', 'column', to_disable], ['#row-checkbox', 'row', to_disable], ['#measure-checkbox', 'measure', !to_disable], ['#list-checkbox', 'list', false]]; |
|
||||
identifiers.forEach(function (element) { |
|
||||
contextMenu.find(element[0]).attr('disabled', element[2]); |
|
||||
}); |
|
||||
|
|
||||
//Add change events
|
|
||||
identifiers.forEach(function (element) { |
|
||||
contextMenu.find(element[0]).unbind("change"); |
|
||||
contextMenu.find(element[0]).change(function() { |
|
||||
currentFieldData[element[1]] = $(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 the target of the click isn't the container nor a descendant of the container
|
|
||||
if (!container.is(e.target) && container.has(e.target).length === 0) |
|
||||
{ |
|
||||
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(); |
|
||||
self.$el.find(".field-list .delete-button").hide(); |
|
||||
self.$el.find(".field-list .delete-button:last").show(); |
|
||||
return false; |
|
||||
}); |
|
||||
|
|
||||
self.$el.find(".field-list .delete-button").hide(); |
|
||||
self.$el.find(".field-list .delete-button:last").show(); |
|
||||
}, |
|
||||
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; |
|
||||
|
|
||||
var go_to_else = true; |
|
||||
if (join_node.join_node === -1 || join_node.table_alias === -1){ |
|
||||
go_to_else = false; |
|
||||
field.table_alias = self.get_table_alias(field); |
|
||||
if (join_node.join_node === -1) join_node.join_node = field.table_alias; |
|
||||
else 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 self = this; |
|
||||
|
|
||||
// Quick fix for double click
|
|
||||
if(self._adding) { |
|
||||
return; |
|
||||
} |
|
||||
self._adding = true; |
|
||||
setTimeout(function() { |
|
||||
self._adding = false; |
|
||||
}, 1000); |
|
||||
// End quick fix
|
|
||||
|
|
||||
var data = field.data('field-data'); |
|
||||
var model = new Model("ir.model"); |
|
||||
var model_ids = this.get_model_ids(); |
|
||||
var field_data = this.get_fields(); |
|
||||
model.call('get_join_nodes', [field_data, data], {context: new Data.CompoundContext()}).then(function(result) { |
|
||||
|
|
||||
if (result.length === 1) { |
|
||||
self.add_field_and_join_node(data, result[0]); |
|
||||
self.internal_set_value(JSON.stringify(self.get_fields())); |
|
||||
} else if (result.length > 1) { |
|
||||
var pop = new 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.
|
|
||||
var 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(); |
|
||||
} |
|
||||
}); |
|
||||
Core.form_widget_registry.add('BVEEditor', BiViewEditor); |
|
||||
|
|
||||
}); |
|
@ -0,0 +1,183 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<template> |
||||
|
|
||||
|
<t t-name="bi_view_editor.Frame"> |
||||
|
<div class="oe_form_field_bi_editor"> |
||||
|
|
||||
|
<div class="body"> |
||||
|
|
||||
|
<div class="left"> |
||||
|
</div> |
||||
|
<div class="right"> |
||||
|
|
||||
|
</div> |
||||
|
<div class="clear"></div> |
||||
|
</div> |
||||
|
<div class="footer"> |
||||
|
<div class="left"></div> |
||||
|
<div class="right"><button class="clear-btn hidden"><span class="fa fa-eraser"></span> Clear</button></div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</t> |
||||
|
|
||||
|
<!-- Join Node Dialog --> |
||||
|
<t t-name="bi_view_editor.JoinNodeDialog"> |
||||
|
<div class="oe_bi_view_editor_join_node_dialog"> |
||||
|
<ul class="list-group" > |
||||
|
<t t-foreach="choices" t-as="choice"> |
||||
|
<t t-if="choice.join_node !== -1 and choice.table_alias !== -1"> |
||||
|
<li class="list-group-item list-group-item-action text-primary" t-attf-data-index="#{choice.index}"> |
||||
|
<b>Use the existing node</b> |
||||
|
</li> |
||||
|
</t> |
||||
|
<t t-elif="choice.join_node !== -1"> |
||||
|
<li class="list-group-item list-group-item-action text-success" t-attf-data-index="#{choice.index}"> |
||||
|
Use the field |
||||
|
<b><t t-esc="choice.model_name"/></b> |
||||
|
<i class="fa fa-caret-right"/> |
||||
|
<b><t t-esc="choice.description"/></b> |
||||
|
<span class="badge">new</span> |
||||
|
</li> |
||||
|
</t> |
||||
|
<t t-else=""> |
||||
|
<li class="list-group-item list-group-item-action" t-attf-data-index="#{choice.index}"> |
||||
|
Use the field |
||||
|
<b><t t-esc="choice.model_name"/></b> |
||||
|
<i class="fa fa-caret-right"/> |
||||
|
<b><t t-esc="choice.description"/></b> |
||||
|
</li> |
||||
|
</t> |
||||
|
</t> |
||||
|
</ul> |
||||
|
</div> |
||||
|
</t> |
||||
|
|
||||
|
<!-- ModelList --> |
||||
|
<t t-name="bi_view_editor.ModelList"> |
||||
|
<div> |
||||
|
<div class="search-bar"> |
||||
|
<span class="fa fa-search"></span> |
||||
|
<input type="text" class="search-bar" /> |
||||
|
</div> |
||||
|
<div class="class-list"> |
||||
|
</div> |
||||
|
</div> |
||||
|
</t> |
||||
|
|
||||
|
<!-- ModelListItem --> |
||||
|
<t t-name="bi_view_editor.ModelListItem"> |
||||
|
<div class="class-container"> |
||||
|
<div class="class" t-attf-title="#{model}" t-attf-data-id="#{id}"><t t-esc="name"/></div> |
||||
|
</div> |
||||
|
</t> |
||||
|
|
||||
|
<!-- ModelListFieldItem--> |
||||
|
<t t-name="bi_view_editor.ModelListFieldItem"> |
||||
|
<div class="field" t-attf-title="#{name}" t-attf-data-id="#{name}"><t t-esc="description"/></div> |
||||
|
</t> |
||||
|
|
||||
|
<!-- FieldList --> |
||||
|
<t t-name="bi_view_editor.FieldList"> |
||||
|
<div> |
||||
|
<table class="field-list"> |
||||
|
<thead> |
||||
|
<tr> |
||||
|
<th>Name</th> |
||||
|
<th>Model</th> |
||||
|
<th>Options</th> |
||||
|
<th></th> |
||||
|
</tr> |
||||
|
</thead> |
||||
|
<tbody> |
||||
|
</tbody> |
||||
|
</table> |
||||
|
</div> |
||||
|
</t> |
||||
|
|
||||
|
<!-- FieldContextMenu --> |
||||
|
<t t-name="bi_view_editor.FieldList.FieldContextMenu"> |
||||
|
<ul class="context-menu hidden"> |
||||
|
<li> |
||||
|
<div class="checkbox"> |
||||
|
<label> |
||||
|
<input type="checkbox" data-for="column" class="checkbox-column"/> Column |
||||
|
</label> |
||||
|
</div> |
||||
|
</li> |
||||
|
<li> |
||||
|
<div class="checkbox"> |
||||
|
<label> |
||||
|
<input type="checkbox" data-for="row" class="checkbox-row"/> Row |
||||
|
</label> |
||||
|
</div> |
||||
|
</li> |
||||
|
<li> |
||||
|
<div class="checkbox"> |
||||
|
<label> |
||||
|
<input type="checkbox" data-for="measure" class="checkbox-measure"/> Measure |
||||
|
</label> |
||||
|
</div> |
||||
|
</li> |
||||
|
<li> |
||||
|
<div class="checkbox"> |
||||
|
<label> |
||||
|
<input type="checkbox" data-for="list" class="checkbox-list"/> List |
||||
|
</label> |
||||
|
</div> |
||||
|
</li> |
||||
|
</ul> |
||||
|
</t> |
||||
|
|
||||
|
<!-- JoinContextMenu --> |
||||
|
<t t-name="bi_view_editor.FieldList.JoinContextMenu"> |
||||
|
<ul class="context-menu hidden"> |
||||
|
<li> |
||||
|
<div class="checkbox"> |
||||
|
<label> |
||||
|
<input type="checkbox" data-for="join_left" class="checkbox-join-left"/> Join Left |
||||
|
</label> |
||||
|
</div> |
||||
|
</li> |
||||
|
</ul> |
||||
|
</t> |
||||
|
|
||||
|
<!-- FieldListItem --> |
||||
|
<t t-name="bi_view_editor.FieldListItem"> |
||||
|
<tr t-attf-data-id="#{field._id}" class="field-node"> |
||||
|
<td> |
||||
|
<input t-attf-data-id="#{field._id}" t-attf-title="#{field.model_name} (#{field.model})" class="form-control input-sm" type="text" name="description" t-attf-value="#{field.description}"/> |
||||
|
</td> |
||||
|
<td> |
||||
|
<t t-esc="field.model_name" /> |
||||
|
</td> |
||||
|
<td> |
||||
|
<span data-for="column" t-attf-class="#{field.column and 'fa fa-columns' or 'fa fa-columns hidden'}" title='Column'></span> |
||||
|
<span data-for="row" t-attf-class="#{field.row and 'fa fa-bars' or 'fa fa-bars hidden'}" title='Row'></span> |
||||
|
<span data-for="measure" t-attf-class="#{field.measure and 'fa fa-bar-chart-o' or 'fa fa-bar-chart-o hidden'}" title='Measure'></span> |
||||
|
<span data-for="list" t-attf-class="#{field.list and 'fa fa-list' or 'fa fa-list hidden'}" title='List'></span> |
||||
|
</td> |
||||
|
<td> |
||||
|
<span t-attf-data-id="#{field._id}" class="delete-button fa fa-trash-o"/> |
||||
|
</td> |
||||
|
</tr> |
||||
|
</t> |
||||
|
|
||||
|
<t t-name="bi_view_editor.JoinListItem"> |
||||
|
<tr t-attf-data-id="#{field._id}" class="join-node"> |
||||
|
<td colspan="4"> |
||||
|
<input class="hidden" type="text" name="description" t-attf-value="#{field.description}"/> |
||||
|
<t t-if="field.join_node > field.table_alias"> |
||||
|
<b><t t-esc="field.model_name" /></b> |
||||
|
<i class="fa fa-caret-right"/> |
||||
|
<small><t t-esc="field.description" /></small> |
||||
|
</t> |
||||
|
<t t-else=""> |
||||
|
<small><t t-esc="field.description" /></small> |
||||
|
<i class="fa fa-caret-left"/> |
||||
|
<b><t t-esc="field.model_name" /></b> |
||||
|
</t> |
||||
|
<span t-attf-class="#{!field.join_left and 'hidden' or ''}" data-for="join_left"><i>(join left)</i></span> |
||||
|
</td> |
||||
|
</tr> |
||||
|
</t> |
||||
|
</template> |
@ -1,54 +0,0 @@ |
|||||
<?xml version="1.0" encoding="UTF-8"?> |
|
||||
<templates id="template" xml:space="preserve"> |
|
||||
<t t-name="JoinNodePopup"> |
|
||||
<div class="oe_form_nosheet"> |
|
||||
<div id="join-nodes"> |
|
||||
</div> |
|
||||
</div> |
|
||||
</t> |
|
||||
|
|
||||
|
|
||||
<t t-name="BVEEditor"> |
|
||||
<div class="oe_form_field_bi_editor"> |
|
||||
|
|
||||
<div class="body"> |
|
||||
|
|
||||
<div class="left"> |
|
||||
<div class="search-bar"> |
|
||||
<span class="fa fa-search"></span> |
|
||||
<input type="text" class="search-bar" /> |
|
||||
</div> |
|
||||
<div class="class-list"> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="right"> |
|
||||
<table class="field-list"> |
|
||||
<thead> |
|
||||
<tr> |
|
||||
<th>Name</th> |
|
||||
<th>Model</th> |
|
||||
<th>Options</th> |
|
||||
<th></th> |
|
||||
</tr> |
|
||||
</thead> |
|
||||
<tbody> |
|
||||
</tbody> |
|
||||
</table> |
|
||||
</div> |
|
||||
<div class="clear"></div> |
|
||||
</div> |
|
||||
<div class="footer"> |
|
||||
<div class="left"></div> |
|
||||
<div class="right"><button id="clear"><span class="fa fa-eraser"></span> Clear</button></div> |
|
||||
</div> |
|
||||
<ul class="context-menu"> |
|
||||
|
|
||||
<li><input type="checkbox" id="column-checkbox"/> Column</li> |
|
||||
<li><input type="checkbox" id="row-checkbox"/> Row</li> |
|
||||
<li><input type="checkbox" id="measure-checkbox"/> Measure</li> |
|
||||
<li><input type="checkbox" id="list-checkbox"/> List</li> |
|
||||
|
|
||||
</ul> |
|
||||
</div> |
|
||||
</t> |
|
||||
</templates> |
|
@ -1,5 +1,3 @@ |
|||||
# -*- coding: utf-8 -*- |
|
||||
# Copyright 2017 Onestein (<http://www.onestein.eu>) |
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
|
||||
|
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). |
||||
|
|
||||
from . import test_bi_view |
from . import test_bi_view |
@ -1,5 +1,3 @@ |
|||||
# -*- coding: utf-8 -*- |
|
||||
# Copyright 2017 Onestein (<http://www.onestein.eu>) |
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
|
||||
|
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). |
||||
|
|
||||
from . import wizard_ir_model_menu_create |
from . import wizard_ir_model_menu_create |
Write
Preview
Loading…
Cancel
Save
Reference in new issue