[MERGE] crm_*: hide irrelevant measures from graph/pivot views
PURPOSE Support invisible attributes to remove irrelevant fields in standard views. SPECIFICATIONS Add the possibility to not display some fields in the measures dropdown for the graph and pivot views. When a field is not displayed in the measures of a pivot views we remove them also from the list of groupable fields. Update CRM addons to hide irrelevant measures. LINKS Task ID-2288381 Community PR #54774 Enterprise PR odoo/enterprise#11970 Upgrade PR odoo/upgrade#1519 Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
This commit is contained in:
@@ -36,6 +36,7 @@
|
||||
<field name="stage_id" type="row"/>
|
||||
<field name="date_deadline" type="row" interval="month"/>
|
||||
<field name="prorated_revenue" type="measure"/>
|
||||
<field name="color" invisible="1"/>
|
||||
</graph>
|
||||
</field>
|
||||
</record>
|
||||
@@ -48,6 +49,7 @@
|
||||
<graph string="Leads Analysis" stacked="True" sample="1">
|
||||
<field name="create_date" interval="month" type="col"/>
|
||||
<field name="team_id" type="col"/>
|
||||
<field name="color" invisible="1"/>
|
||||
</graph>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
@@ -746,6 +746,7 @@
|
||||
<graph string="Opportunities" sample="1">
|
||||
<field name="stage_id" type="col"/>
|
||||
<field name="user_id" type="row"/>
|
||||
<field name="color" invisible="1"/>
|
||||
</graph>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
@@ -22,4 +22,48 @@
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="crm_lead_view_pivot" model="ir.ui.view">
|
||||
<field name="name">crm.lead.view.pivot.inherit.lead.website</field>
|
||||
<field name="model">crm.lead</field>
|
||||
<field name="inherit_id" ref="crm.crm_lead_view_pivot"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//pivot" position="inside">
|
||||
<field name="reveal_iap_credits" invisible="1"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="crm_lead_view_graph" model="ir.ui.view">
|
||||
<field name="name">crm.lead.view.graph.inherit.lead.website</field>
|
||||
<field name="model">crm.lead</field>
|
||||
<field name="inherit_id" ref="crm.crm_lead_view_graph"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//graph" position="inside">
|
||||
<field name="reveal_iap_credits" invisible="1"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="crm_lead_view_graph_report_opportunity" model="ir.ui.view">
|
||||
<field name="name">crm.lead.view.graph.report.opportunity.inherit.lead.website</field>
|
||||
<field name="model">crm.lead</field>
|
||||
<field name="inherit_id" ref="crm.crm_opportunity_report_view_graph"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//graph" position="inside">
|
||||
<field name="reveal_iap_credits" invisible="1"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="crm_lead_view_graph_report_lead" model="ir.ui.view">
|
||||
<field name="name">crm.lead.view.graph.report.lead.inherit.lead.website</field>
|
||||
<field name="model">crm.lead</field>
|
||||
<field name="inherit_id" ref="crm.crm_opportunity_report_view_graph_lead"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//graph" position="inside">
|
||||
<field name="reveal_iap_credits" invisible="1"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
</odoo>
|
||||
|
||||
@@ -43,7 +43,7 @@ var GraphView = AbstractView.extend({
|
||||
let measure;
|
||||
const measures = {};
|
||||
const measureStrings = {};
|
||||
const groupBys = [];
|
||||
let groupBys = [];
|
||||
const groupableFields = {};
|
||||
this.fields.__count__ = { string: _t("Count"), type: 'integer' };
|
||||
|
||||
@@ -100,6 +100,20 @@ var GraphView = AbstractView.extend({
|
||||
}
|
||||
}
|
||||
|
||||
// Remove invisible fields from the measures
|
||||
this.arch.children.forEach(field => {
|
||||
let fieldName = field.attrs.name;
|
||||
if (field.attrs.invisible && py.eval(field.attrs.invisible)) {
|
||||
groupBys = groupBys.filter(groupBy => groupBy !== fieldName);
|
||||
if (fieldName in groupableFields) {
|
||||
delete groupableFields[fieldName];
|
||||
}
|
||||
if (!additionalMeasures.includes(fieldName)) {
|
||||
delete measures[fieldName];
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const sortedMeasures = Object.values(measures).sort((a, b) => {
|
||||
const descA = a.description.toLowerCase();
|
||||
const descB = b.description.toLowerCase();
|
||||
|
||||
@@ -67,11 +67,15 @@ odoo.define('web.PivotView', function (require) {
|
||||
|
||||
this.arch.children.forEach(field => {
|
||||
let name = field.attrs.name;
|
||||
|
||||
// Remove invisible fields from the measures
|
||||
// Remove invisible fields from the measures if not in additionalMeasures
|
||||
if (field.attrs.invisible && py.eval(field.attrs.invisible)) {
|
||||
delete measures[name];
|
||||
return;
|
||||
if (name in groupableFields) {
|
||||
delete groupableFields[name];
|
||||
}
|
||||
if (!additionalMeasures.includes(name)) {
|
||||
delete measures[name];
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (field.attrs.interval) {
|
||||
name += ':' + field.attrs.interval;
|
||||
|
||||
@@ -97,16 +97,17 @@ QUnit.module('Views', {
|
||||
product_id: {string: "Product", type: "many2one", relation: 'product', store: true},
|
||||
color_id: {string: "Color", type: "many2one", relation: 'color'},
|
||||
date: {string: "Date", type: 'date', store: true, sortable: true},
|
||||
revenue: {string: "Revenue", type: 'integer', store: true},
|
||||
},
|
||||
records: [
|
||||
{id: 1, foo: 3, bar: true, product_id: 37, date: "2016-01-01"},
|
||||
{id: 2, foo: 53, bar: true, product_id: 37, color_id: 7, date: "2016-01-03"},
|
||||
{id: 3, foo: 2, bar: true, product_id: 37, date: "2016-03-04"},
|
||||
{id: 4, foo: 24, bar: false, product_id: 37, date: "2016-03-07"},
|
||||
{id: 5, foo: 4, bar: false, product_id: 41, date: "2016-05-01"},
|
||||
{id: 1, foo: 3, bar: true, product_id: 37, date: "2016-01-01", revenue: 1},
|
||||
{id: 2, foo: 53, bar: true, product_id: 37, color_id: 7, date: "2016-01-03", revenue: 2},
|
||||
{id: 3, foo: 2, bar: true, product_id: 37, date: "2016-03-04", revenue: 3},
|
||||
{id: 4, foo: 24, bar: false, product_id: 37, date: "2016-03-07", revenue: 4},
|
||||
{id: 5, foo: 4, bar: false, product_id: 41, date: "2016-05-01", revenue: 5},
|
||||
{id: 6, foo: 63, bar: false, product_id: 41},
|
||||
{id: 7, foo: 42, bar: false, product_id: 41},
|
||||
{id: 8, foo: 48, bar: false, product_id: 41, date: "2016-04-01"},
|
||||
{id: 8, foo: 48, bar: false, product_id: 41, date: "2016-04-01", revenue: 8},
|
||||
]
|
||||
},
|
||||
product: {
|
||||
@@ -1216,6 +1217,47 @@ QUnit.module('Views', {
|
||||
graph.destroy();
|
||||
});
|
||||
|
||||
QUnit.test('graph view without invisible attribute on field', async function (assert) {
|
||||
assert.expect(4);
|
||||
|
||||
const graph = await createView({
|
||||
View: GraphView,
|
||||
model: "foo",
|
||||
data: this.data,
|
||||
arch: `<graph string="Partners"></graph>`,
|
||||
});
|
||||
|
||||
await testUtils.dom.click(graph.$('.btn-group:first button'));
|
||||
assert.containsN(graph, 'li.o_menu_item', 3,
|
||||
"there should be three menu item in the measures dropdown (count, revenue and foo)");
|
||||
assert.containsOnce(graph, 'li.o_menu_item a:contains("Revenue")');
|
||||
assert.containsOnce(graph, 'li.o_menu_item a:contains("Foo")');
|
||||
assert.containsOnce(graph, 'li.o_menu_item a:contains("Count")');
|
||||
|
||||
graph.destroy();
|
||||
});
|
||||
|
||||
QUnit.test('graph view with invisible attribute on field', async function (assert) {
|
||||
assert.expect(2);
|
||||
|
||||
const graph = await createView({
|
||||
View: GraphView,
|
||||
model: "foo",
|
||||
data: this.data,
|
||||
arch: `
|
||||
<graph string="Partners">
|
||||
<field name="revenue" invisible="1"/>
|
||||
</graph>`,
|
||||
});
|
||||
|
||||
await testUtils.dom.click(graph.$('.btn-group:first button'));
|
||||
assert.containsN(graph, 'li.o_menu_item', 2,
|
||||
"there should be only two menu item in the measures dropdown (count and foo)");
|
||||
assert.containsNone(graph, 'li.o_menu_item a:contains("Revenue")');
|
||||
|
||||
graph.destroy();
|
||||
});
|
||||
|
||||
QUnit.test('graph view sort by measure', async function (assert) {
|
||||
assert.expect(18);
|
||||
|
||||
|
||||
@@ -192,7 +192,7 @@ QUnit.module('Views', {
|
||||
});
|
||||
|
||||
QUnit.test('pivot rendering with invisible attribute on field', async function (assert) {
|
||||
assert.expect(2);
|
||||
assert.expect(3);
|
||||
// when invisible, a field should neither be an active measure,
|
||||
// nor be a selectable measure.
|
||||
_.extend(this.data.partner.fields, {
|
||||
@@ -214,6 +214,9 @@ QUnit.module('Views', {
|
||||
assert.containsOnce(pivot, '.o_pivot_measure_row');
|
||||
// there should be only one measure besides count, as the other one is invisible
|
||||
assert.containsN(pivot, '.o_cp_bottom_left .dropdown-item', 2);
|
||||
// the invisible field souldn't be in the groupable fields neither
|
||||
await testUtils.dom.click(pivot.$('.o_pivot_header_cell_closed:first'));
|
||||
assert.containsNone(pivot, '.o_pivot_field_menu a[data-field="foo2"]');
|
||||
|
||||
pivot.destroy();
|
||||
});
|
||||
|
||||
@@ -89,4 +89,51 @@
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="crm_lead_view_pivot" model="ir.ui.view">
|
||||
<field name="name">crm.lead.view.pivot.inherit.partner.assign</field>
|
||||
<field name="model">crm.lead</field>
|
||||
<field name="inherit_id" ref="crm.crm_lead_view_pivot"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//pivot" position="inside">
|
||||
<field name="partner_latitude" invisible="1"/>
|
||||
<field name="partner_longitude" invisible="1"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="crm_lead_view_graph" model="ir.ui.view">
|
||||
<field name="name">crm.lead.view.graph.inherit.partner.assign</field>
|
||||
<field name="model">crm.lead</field>
|
||||
<field name="inherit_id" ref="crm.crm_lead_view_graph"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//graph" position="inside">
|
||||
<field name="partner_latitude" invisible="1"/>
|
||||
<field name="partner_longitude" invisible="1"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="crm_lead_view_graph_report_opportunity" model="ir.ui.view">
|
||||
<field name="name">crm.lead.view.graph.report.opportunity.inherit.partner.assign</field>
|
||||
<field name="model">crm.lead</field>
|
||||
<field name="inherit_id" ref="crm.crm_opportunity_report_view_graph"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//graph" position="inside">
|
||||
<field name="partner_latitude" invisible="1"/>
|
||||
<field name="partner_longitude" invisible="1"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="crm_lead_view_graph_report_lead" model="ir.ui.view">
|
||||
<field name="name">crm.lead.view.graph.report.lead.inherit.partner.assign</field>
|
||||
<field name="model">crm.lead</field>
|
||||
<field name="inherit_id" ref="crm.crm_opportunity_report_view_graph_lead"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//graph" position="inside">
|
||||
<field name="partner_latitude" invisible="1"/>
|
||||
<field name="partner_longitude" invisible="1"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
</odoo>
|
||||
|
||||
@@ -497,6 +497,19 @@ attributes:
|
||||
A field that can be aggregated. This field will be used to compute the values
|
||||
for each cell. If not set, the cohort view will count the number of occurrences.
|
||||
|
||||
``<field>`` (optional)
|
||||
allows to specify a particular field in order to manage it from the available measures, it's
|
||||
main use is for hiding a field from the selectable measures:
|
||||
* ``name`` (required)
|
||||
the name of the field to use in the view.
|
||||
* ``string`` (optional)
|
||||
the name that would be used to display the field in the cohort view, overrides the
|
||||
default python String attribute of the field.
|
||||
* ``invisible`` (optional)
|
||||
if true, the field will not appear either in the active measures nor in the selectable
|
||||
measures (useful for fields that do not make sense aggregated, such as fields in different
|
||||
units, e.g. € and $).
|
||||
|
||||
.. _reference/views/dashboard:
|
||||
|
||||
Dashboard
|
||||
@@ -1109,6 +1122,10 @@ following attributes:
|
||||
``title`` (optional)
|
||||
string displayed on the top of the graph.
|
||||
|
||||
``invisible`` (optional)
|
||||
if true, the field will not appear either in the active measures nor in the
|
||||
selectable measures.
|
||||
|
||||
``type``
|
||||
indicates whether the field should be used as a grouping criteria or as an
|
||||
aggregated value within a group. Possible values are:
|
||||
|
||||
Reference in New Issue
Block a user