Holger Brunn
5 years ago
committed by
GitHub
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 358 additions and 0 deletions
-
90web_pivot_zoom/README.rst
-
3web_pivot_zoom/__init__.py
-
21web_pivot_zoom/__openerp__.py
-
17web_pivot_zoom/demo/res_users.xml
-
BINweb_pivot_zoom/static/description/icon.png
-
9web_pivot_zoom/static/src/css/web_pivot_zoom.css
-
207web_pivot_zoom/static/src/js/web_pivot_zoom.js
-
11web_pivot_zoom/views/templates.xml
@ -0,0 +1,90 @@ |
|||
.. 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 |
|||
|
|||
=================== |
|||
Zoom in pivot views |
|||
=================== |
|||
|
|||
This module was written to allow your users to zoom into cells in pivot views |
|||
by simply clicking a cell in question. |
|||
|
|||
Installation |
|||
============ |
|||
|
|||
Don't install this module manually, it won't do anything. A module that uses it |
|||
will pull it as dependency. |
|||
|
|||
Usage |
|||
===== |
|||
|
|||
To use this module, you need to: |
|||
|
|||
#. depend on this module |
|||
#. in your measure elements in your pivot view, declare an options dictionary |
|||
as in |
|||
``<field name="field" type="measure" options="{'web_pivot_zoom': {}}" />`` |
|||
|
|||
The options dictionary must have a key ``model`` to inform the module which |
|||
model should be shown, and a key ``domain`` for the domain to be used. |
|||
The domain is subject to evaluation, so you can use the grouped values in |
|||
there. Note that if a field is not grouped, it will evaluate as ``None``, so |
|||
the ``=?`` is your friend for expressions refering to the grouped fields. |
|||
|
|||
Note that not all field types support the ``=?`` operator. For many2many |
|||
fields, you'd have to use a construction like |
|||
``('many2many_field', many2many_field and '=' or '!=', many2many_field)`` |
|||
to simulate this to some degree. |
|||
|
|||
Consult the demo data for an example, there, a graph view is added to the |
|||
users model, and clicking cells sends you to partners with the company in |
|||
question. |
|||
|
|||
Measures with a configuration enabling zooming will have a small link icon next to the column title. |
|||
|
|||
.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas |
|||
:alt: Try me on Runbot |
|||
:target: https://runbot.odoo-community.org/runbot/162/8.0 |
|||
|
|||
Roadmap |
|||
======= |
|||
|
|||
* it might be convenient to be able to pass a window action's id |
|||
|
|||
Bug Tracker |
|||
=========== |
|||
|
|||
Bugs are tracked on `GitHub Issues |
|||
<https://github.com/OCA/web/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 <https://github.com/OCA/maintainer-tools/blob/master/template/module/static/description/icon.svg>`_. |
|||
|
|||
Contributors |
|||
------------ |
|||
|
|||
* Holger Brunn <hbrunn@therp.nl> |
|||
|
|||
Do not contact contributors directly about help with questions or problems concerning this addon, but use the `community mailing list <mailto:community@mail.odoo.com>`_ or the `appropriate specialized mailinglist <https://odoo-community.org/groups>`_ for help, and the bug tracker linked in `Bug Tracker`_ above for technical issues. |
|||
|
|||
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. |
@ -0,0 +1,3 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# © 2016 Therp BV <http://therp.nl> |
|||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
@ -0,0 +1,21 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# © 2016 Therp BV <http://therp.nl> |
|||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
|||
{ |
|||
"name": "Zoom in pivot views", |
|||
"version": "8.0.1.0.0", |
|||
"author": "Therp BV,Odoo Community Association (OCA)", |
|||
"license": "AGPL-3", |
|||
"category": "Hidden/Dependency", |
|||
"summary": "Allows other modules to define windows actions for zooming in " |
|||
"pivot views", |
|||
"depends": [ |
|||
'web_graph', |
|||
], |
|||
"demo": [ |
|||
"demo/res_users.xml", |
|||
], |
|||
"data": [ |
|||
'views/templates.xml', |
|||
], |
|||
} |
@ -0,0 +1,17 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<openerp> |
|||
<data> |
|||
<record id="res_users_graph" model="ir.ui.view"> |
|||
<field name="model">res.users</field> |
|||
<field name="arch" type="xml"> |
|||
<graph type="pivot"> |
|||
<field name="color" type="measure" options="{'web_pivot_zoom': {'model': 'res.partner', 'domain': "[('company_id', '=?', company_id)]"}}" /> |
|||
<field name="company_id" type="row" /> |
|||
</graph> |
|||
</field> |
|||
</record> |
|||
<record id="base.action_res_users" model="ir.actions.act_window"> |
|||
<field name="view_mode">tree,form,graph</field> |
|||
</record> |
|||
</data> |
|||
</openerp> |
After Width: 128 | Height: 128 | Size: 9.2 KiB |
@ -0,0 +1,9 @@ |
|||
.graph_pivot_mode td.web_pivot_zoom |
|||
{ |
|||
cursor: pointer; |
|||
} |
|||
.graph_pivot_mode th.web_pivot_zoom:after |
|||
{ |
|||
font-family: FontAwesome; |
|||
content: ' \f0c1'; |
|||
} |
@ -0,0 +1,207 @@ |
|||
//-*- coding: utf-8 -*-
|
|||
//© 2016 Therp BV <http://therp.nl>
|
|||
//License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
|||
|
|||
openerp.web_pivot_zoom = function(instance) |
|||
{ |
|||
instance.web_graph.Graph.include({ |
|||
start: function() |
|||
{ |
|||
this.$el.on( |
|||
'click', 'td.web_pivot_zoom', |
|||
this.proxy('_web_pivot_zoom_on_click_cell') |
|||
); |
|||
return this._super.apply(this, arguments); |
|||
}, |
|||
draw_row: function (row, frozen_rows) |
|||
{ |
|||
var self = this, |
|||
$result = this._super.apply(this, arguments); |
|||
_.each(this.pivot_options.measures, function(measure, i) |
|||
{ |
|||
if(!_.isEmpty(self.graph_view._web_pivot_zoom[measure.field])) |
|||
{ |
|||
jQuery($result.children().get(i + 1)) |
|||
.addClass('web_pivot_zoom'); |
|||
} |
|||
}); |
|||
return $result; |
|||
}, |
|||
draw_measure_row: function(measure_row) |
|||
{ |
|||
this._super.apply(this, arguments); |
|||
var self = this, |
|||
$last_headers = this.$thead.children().last().children(); |
|||
_.each(this.pivot_options.measures, function(measure, i) |
|||
{ |
|||
if(!_.isEmpty(self.graph_view._web_pivot_zoom[measure.field])) |
|||
{ |
|||
jQuery($last_headers.get(i + 1)) |
|||
.addClass('web_pivot_zoom'); |
|||
} |
|||
}); |
|||
}, |
|||
get_measures: function() |
|||
{ |
|||
var self = this; |
|||
return _.filter( |
|||
this._super.apply(this, arguments), |
|||
function(field) |
|||
{ |
|||
return self.pivot_options.invisible_measures.indexOf( |
|||
field.field |
|||
) == -1; |
|||
} |
|||
); |
|||
}, |
|||
_web_pivot_zoom_on_click_cell: function(e) |
|||
{ |
|||
if(!e.currentTarget.cellIndex) |
|||
{ |
|||
return; |
|||
} |
|||
var self = this, |
|||
$current_row = jQuery(e.currentTarget).closest('tr'), |
|||
$col_row = jQuery(e.currentTarget).closest('table') |
|||
.find('thead tr:nth-last-child(2)'), |
|||
col_id = $col_row.find('[data-id]').eq( |
|||
Math.floor( |
|||
(e.currentTarget.cellIndex - 1) / |
|||
this.pivot.measures.length |
|||
) |
|||
).attr('data-id'), |
|||
row_id = $current_row.find('[data-id]').attr('data-id'), |
|||
current_field = this.pivot.measures[ |
|||
(e.currentTarget.cellIndex - 1) % |
|||
this.pivot.measures.length |
|||
], |
|||
row_header = this.pivot.get_header(row_id), |
|||
col_header = this.pivot.get_header(col_id), |
|||
// see https://github.com/OCA/OCB/blob/8.0/addons/web_graph/
|
|||
// static/src/js/pivot_table.js#L88
|
|||
measure_values = this.pivot.get_values( |
|||
Math.min(col_id, row_id), Math.max(col_id, row_id) |
|||
), |
|||
group_values = {}; |
|||
_.each(this.groupby_fields, function(field) |
|||
{ |
|||
group_values[field.field] = null; |
|||
}); |
|||
_.each(row_header.domain, function(leaf) |
|||
{ |
|||
group_values[leaf[0]] = leaf[2]; |
|||
}); |
|||
_.each(col_header.domain, function(leaf) |
|||
{ |
|||
group_values[leaf[0]] = leaf[2]; |
|||
}); |
|||
_.each(this.pivot_options.measures, function(measure, i) |
|||
{ |
|||
group_values[measure.field] = measure_values[i]; |
|||
}); |
|||
_.each(this.pivot_options.invisible_measures, function(measure, i) |
|||
{ |
|||
group_values[measure] = measure_values[ |
|||
i + self.pivot_options.measures.length |
|||
]; |
|||
}); |
|||
var model = this.graph_view._web_pivot_zoom[current_field.field] |
|||
.model, |
|||
domain = instance.web.pyeval.eval( |
|||
'domain', |
|||
this.graph_view._web_pivot_zoom[current_field.field] |
|||
.domain || [], |
|||
group_values |
|||
); |
|||
if(!model || !domain) |
|||
{ |
|||
return; |
|||
} |
|||
return this._web_pivot_zoom_action( |
|||
model, domain, current_field, row_header, col_header |
|||
); |
|||
}, |
|||
_web_pivot_zoom_action: function( |
|||
model, domain, current_field, row_header, col_header |
|||
) |
|||
{ |
|||
// we don't need to search again when clicking back
|
|||
this.graph_view.ViewManager.action.flags.auto_search = false; |
|||
return this.do_action({ |
|||
'type': 'ir.actions.act_window', |
|||
'res_model': model, |
|||
'domain': domain, |
|||
'views': [[false, 'list'], [false, 'form']], |
|||
'name': row_header.title + ': ' + current_field.string, |
|||
}); |
|||
}, |
|||
}); |
|||
instance.web_graph.GraphView.include({ |
|||
view_loading: function(fields_view_get) |
|||
{ |
|||
var self = this, |
|||
invisible_measures = [], |
|||
result; |
|||
this._web_pivot_zoom = {}; |
|||
for(var i=0; i < fields_view_get.arch.children.length; i++) |
|||
{ |
|||
var field = fields_view_get.arch.children[i]; |
|||
if(instance.web.py_eval(field.attrs.invisible || '0')) |
|||
{ |
|||
invisible_measures.push(field.attrs.name); |
|||
fields_view_get.arch.children.splice(i--, 1); |
|||
} |
|||
self._web_pivot_zoom[field.attrs.name] = instance.web.py_eval( |
|||
field.attrs.options || '{}' |
|||
).web_pivot_zoom || {}; |
|||
} |
|||
result = this._super.apply(this, arguments); |
|||
this.widget_config.invisible_measures = invisible_measures; |
|||
return result; |
|||
}, |
|||
}); |
|||
instance.web_graph.PivotTable.include({ |
|||
init: function(model, domain, fields, options) |
|||
{ |
|||
this.invisible_measures = options.invisible_measures; |
|||
return this._super.apply(this, arguments); |
|||
}, |
|||
get_groups: function(groupbys, fields, domain) |
|||
{ |
|||
return this._super( |
|||
groupbys, this.invisible_measures.concat(fields), domain |
|||
); |
|||
}, |
|||
make_headers_and_cell: function( |
|||
data_pts, row_headers, col_headers, index, prefix, expand |
|||
) |
|||
{ |
|||
var self = this; |
|||
this._super.apply(this, arguments); |
|||
if(!this.invisible_measures.length) |
|||
{ |
|||
return; |
|||
} |
|||
data_pts.forEach(function(group) |
|||
{ |
|||
var row_value = (prefix || []).concat( |
|||
group.attributes.value.slice(0, index) |
|||
), |
|||
col_value = group.attributes.value.slice(index), |
|||
row = self.find_or_create_header( |
|||
row_headers, row_value, group |
|||
), |
|||
col = self.find_or_create_header( |
|||
col_headers, col_value, group |
|||
), |
|||
values = self.get_values( |
|||
Math.min(col.id, row.id), Math.max(col.id, row.id) |
|||
); |
|||
_.each(self.invisible_measures, function(measure) |
|||
{ |
|||
values.push(group.attributes.aggregates[measure]); |
|||
}); |
|||
}); |
|||
}, |
|||
}); |
|||
}; |
@ -0,0 +1,11 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<openerp> |
|||
<data> |
|||
<template id="assets_backend" name="web_pivot_zoom assets" inherit_id="web.assets_backend"> |
|||
<xpath expr="." position="inside"> |
|||
<script type="text/javascript" src="/web_pivot_zoom/static/src/js/web_pivot_zoom.js"></script> |
|||
<link rel="stylesheet" href="/web_pivot_zoom/static/src/css/web_pivot_zoom.css"/> |
|||
</xpath> |
|||
</template> |
|||
</data> |
|||
</openerp> |
Write
Preview
Loading…
Cancel
Save
Reference in new issue