forked from Techsystech/web
[IMP] web_dashboard_tile: black, isort, prettier
parent
ffe3f9f5f0
commit
0d15ce1df8
|
@ -0,0 +1 @@
|
||||||
|
../../../../web_dashboard_tile
|
|
@ -0,0 +1,6 @@
|
||||||
|
import setuptools
|
||||||
|
|
||||||
|
setuptools.setup(
|
||||||
|
setup_requires=['setuptools-odoo'],
|
||||||
|
odoo_addon=True,
|
||||||
|
)
|
|
@ -2,14 +2,13 @@
|
||||||
# @author: Sylvain LE GAL (https://twitter.com/legalsylvain)
|
# @author: Sylvain LE GAL (https://twitter.com/legalsylvain)
|
||||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
||||||
|
|
||||||
from odoo.http import Controller, route, request
|
from odoo.http import Controller, request, route
|
||||||
|
|
||||||
|
|
||||||
class WebDashboardTile(Controller):
|
class WebDashboardTile(Controller):
|
||||||
|
@route("/web_dashboard_tile/create_tile", type="json", auth="user")
|
||||||
@route('/web_dashboard_tile/create_tile', type='json', auth='user')
|
|
||||||
def create_tile(self, model_name, *args, **kwargs):
|
def create_tile(self, model_name, *args, **kwargs):
|
||||||
IrModel = request.env['ir.model']
|
IrModel = request.env["ir.model"]
|
||||||
model = IrModel.search([('model', '=', model_name)])
|
model = IrModel.search([("model", "=", model_name)])
|
||||||
kwargs.update({'model_id': model.id})
|
kwargs.update({"model_id": model.id})
|
||||||
return request.env['tile.tile'].create(kwargs)
|
return request.env["tile.tile"].create(kwargs)
|
||||||
|
|
|
@ -6,7 +6,9 @@
|
||||||
<field name="category_id" ref="category_module" />
|
<field name="category_id" ref="category_module" />
|
||||||
<field name="model_id" ref="base.model_ir_module_module" />
|
<field name="model_id" ref="base.model_ir_module_module" />
|
||||||
<field name="action_id" ref="base.open_module_tree" />
|
<field name="action_id" ref="base.open_module_tree" />
|
||||||
<field name="domain">[['state', 'in', ['installed', 'to upgrade', 'to remove']]]</field>
|
<field
|
||||||
|
name="domain"
|
||||||
|
>[['state', 'in', ['installed', 'to upgrade', 'to remove']]]</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="installed_OCA_modules" model="tile.tile">
|
<record id="installed_OCA_modules" model="tile.tile">
|
||||||
|
@ -14,7 +16,9 @@
|
||||||
<field name="category_id" ref="category_module" />
|
<field name="category_id" ref="category_module" />
|
||||||
<field name="model_id" ref="base.model_ir_module_module" />
|
<field name="model_id" ref="base.model_ir_module_module" />
|
||||||
<field name="action_id" ref="base.open_module_tree" />
|
<field name="action_id" ref="base.open_module_tree" />
|
||||||
<field name="domain">[['state', 'in', ['installed', 'to upgrade', 'to remove']], ['author', 'ilike', 'Odoo Community Association (OCA)']]</field>
|
<field
|
||||||
|
name="domain"
|
||||||
|
>[['state', 'in', ['installed', 'to upgrade', 'to remove']], ['author', 'ilike', 'Odoo Community Association (OCA)']]</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="all_currency_with_rate" model="tile.tile">
|
<record id="all_currency_with_rate" model="tile.tile">
|
||||||
|
|
|
@ -13,17 +13,15 @@ def migrate(cr, version):
|
||||||
|
|
||||||
# categories was optional in previous versions
|
# categories was optional in previous versions
|
||||||
# affecting all tiles without categories
|
# affecting all tiles without categories
|
||||||
tiles_without_category = env["tile.tile"].search(
|
tiles_without_category = env["tile.tile"].search([("category_id", "=", False)])
|
||||||
[('category_id', '=', False)])
|
|
||||||
if tiles_without_category:
|
if tiles_without_category:
|
||||||
default_category = env["tile.category"].create({
|
default_category = env["tile.category"].create(
|
||||||
|
{
|
||||||
"name": "Default Category",
|
"name": "Default Category",
|
||||||
})
|
}
|
||||||
tiles_without_category.write({
|
)
|
||||||
'category_id': default_category.id
|
tiles_without_category.write({"category_id": default_category.id})
|
||||||
})
|
|
||||||
|
|
||||||
# Enable all categories, to generate actions and menus
|
# Enable all categories, to generate actions and menus
|
||||||
categories = env['tile.category'].with_context(
|
categories = env["tile.category"].with_context(active_test=False).search([])
|
||||||
active_test=False).search([])
|
categories.write({"active": True})
|
||||||
categories.write({'active': True})
|
|
||||||
|
|
|
@ -17,23 +17,24 @@ class TileCategory(models.Model):
|
||||||
active = fields.Boolean(default=True)
|
active = fields.Boolean(default=True)
|
||||||
|
|
||||||
action_id = fields.Many2one(
|
action_id = fields.Many2one(
|
||||||
string='Odoo Action', comodel_name='ir.actions.act_window',
|
string="Odoo Action", comodel_name="ir.actions.act_window", readonly=True
|
||||||
readonly=True)
|
)
|
||||||
|
|
||||||
menu_id = fields.Many2one(
|
menu_id = fields.Many2one(
|
||||||
string='Odoo Menu', comodel_name='ir.ui.menu', readonly=True)
|
string="Odoo Menu", comodel_name="ir.ui.menu", readonly=True
|
||||||
|
)
|
||||||
|
|
||||||
tile_ids = fields.One2many(
|
tile_ids = fields.One2many(
|
||||||
string='Tiles', comodel_name='tile.tile',
|
string="Tiles", comodel_name="tile.tile", inverse_name="category_id"
|
||||||
inverse_name='category_id')
|
)
|
||||||
|
|
||||||
tile_qty = fields.Integer(
|
tile_qty = fields.Integer(
|
||||||
string='Tiles Quantity',
|
string="Tiles Quantity",
|
||||||
compute='_compute_tile_qty',
|
compute="_compute_tile_qty",
|
||||||
store=True,
|
store=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
@api.depends('tile_ids')
|
@api.depends("tile_ids")
|
||||||
def _compute_tile_qty(self):
|
def _compute_tile_qty(self):
|
||||||
for category in self:
|
for category in self:
|
||||||
category.tile_qty = len(category.tile_ids)
|
category.tile_qty = len(category.tile_ids)
|
||||||
|
@ -41,34 +42,36 @@ class TileCategory(models.Model):
|
||||||
def _prepare_action(self):
|
def _prepare_action(self):
|
||||||
self.ensure_one()
|
self.ensure_one()
|
||||||
return {
|
return {
|
||||||
'name': self.name,
|
"name": self.name,
|
||||||
'res_model': 'tile.tile',
|
"res_model": "tile.tile",
|
||||||
'type': 'ir.actions.act_window',
|
"type": "ir.actions.act_window",
|
||||||
'view_mode': 'kanban',
|
"view_mode": "kanban",
|
||||||
'domain': """[
|
"domain": """[
|
||||||
('hidden', '=', False),
|
('hidden', '=', False),
|
||||||
'|', ('user_id', '=', False), ('user_id', '=', uid),
|
'|', ('user_id', '=', False), ('user_id', '=', uid),
|
||||||
('category_id', '=', {self.id})
|
('category_id', '=', {self.id})
|
||||||
]""".format(self=self),
|
]""".format(
|
||||||
|
self=self
|
||||||
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
def _prepare_menu(self):
|
def _prepare_menu(self):
|
||||||
self.ensure_one()
|
self.ensure_one()
|
||||||
return {
|
return {
|
||||||
'name': self.name,
|
"name": self.name,
|
||||||
'parent_id': self.env.ref(
|
"parent_id": self.env.ref("web_dashboard_tile.menu_dashboard_tile").id,
|
||||||
'web_dashboard_tile.menu_dashboard_tile').id,
|
"action": "ir.actions.act_window,%d" % self.action_id.id,
|
||||||
'action': 'ir.actions.act_window,%d' % self.action_id.id,
|
"sequence": self.sequence,
|
||||||
'sequence': self.sequence,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def _create_ui(self):
|
def _create_ui(self):
|
||||||
IrUiMenu = self.env['ir.ui.menu']
|
IrUiMenu = self.env["ir.ui.menu"]
|
||||||
IrActionsActWindows = self.env['ir.actions.act_window']
|
IrActionsActWindows = self.env["ir.actions.act_window"]
|
||||||
for category in self:
|
for category in self:
|
||||||
if not category.action_id:
|
if not category.action_id:
|
||||||
category.action_id = IrActionsActWindows.create(
|
category.action_id = IrActionsActWindows.create(
|
||||||
category._prepare_action())
|
category._prepare_action()
|
||||||
|
)
|
||||||
if not category.menu_id:
|
if not category.menu_id:
|
||||||
category.menu_id = IrUiMenu.create(category._prepare_menu())
|
category.menu_id = IrUiMenu.create(category._prepare_menu())
|
||||||
|
|
||||||
|
@ -88,16 +91,16 @@ class TileCategory(models.Model):
|
||||||
|
|
||||||
def write(self, vals):
|
def write(self, vals):
|
||||||
res = super().write(vals)
|
res = super().write(vals)
|
||||||
if 'active' in vals.keys():
|
if "active" in vals.keys():
|
||||||
if vals.get('active'):
|
if vals.get("active"):
|
||||||
self._create_ui()
|
self._create_ui()
|
||||||
else:
|
else:
|
||||||
self._delete_ui()
|
self._delete_ui()
|
||||||
if 'sequence' in vals.keys():
|
if "sequence" in vals.keys():
|
||||||
self.mapped('menu_id').write({'sequence': vals['sequence']})
|
self.mapped("menu_id").write({"sequence": vals["sequence"]})
|
||||||
if 'name' in vals.keys():
|
if "name" in vals.keys():
|
||||||
self.mapped('menu_id').write({'name': vals['name']})
|
self.mapped("menu_id").write({"name": vals["name"]})
|
||||||
self.mapped('action_id').write({'name': vals['name']})
|
self.mapped("action_id").write({"name": vals["name"]})
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def unlink(self):
|
def unlink(self):
|
||||||
|
|
|
@ -5,15 +5,15 @@
|
||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
import time
|
import time
|
||||||
from statistics import median
|
|
||||||
from dateutil.relativedelta import relativedelta
|
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
|
from statistics import median
|
||||||
|
|
||||||
|
from dateutil.relativedelta import relativedelta
|
||||||
|
|
||||||
from odoo import api, fields, models
|
from odoo import api, fields, models
|
||||||
|
from odoo.exceptions import ValidationError, except_orm
|
||||||
from odoo.tools.safe_eval import safe_eval as eval
|
from odoo.tools.safe_eval import safe_eval as eval
|
||||||
from odoo.tools.translate import _
|
from odoo.tools.translate import _
|
||||||
from odoo.exceptions import ValidationError, except_orm
|
|
||||||
|
|
||||||
|
|
||||||
FIELD_FUNCTIONS = OrderedDict(
|
FIELD_FUNCTIONS = OrderedDict(
|
||||||
[
|
[
|
||||||
|
@ -81,8 +81,11 @@ class TileTile(models.Model):
|
||||||
sequence = fields.Integer(default=0, required=True)
|
sequence = fields.Integer(default=0, required=True)
|
||||||
|
|
||||||
category_id = fields.Many2one(
|
category_id = fields.Many2one(
|
||||||
string="Category", comodel_name="tile.category", required=True,
|
string="Category",
|
||||||
ondelete="CASCADE")
|
comodel_name="tile.category",
|
||||||
|
required=True,
|
||||||
|
ondelete="CASCADE",
|
||||||
|
)
|
||||||
|
|
||||||
user_id = fields.Many2one(string="User", comodel_name="res.users")
|
user_id = fields.Many2one(string="User", comodel_name="res.users")
|
||||||
|
|
||||||
|
@ -98,9 +101,7 @@ class TileTile(models.Model):
|
||||||
"(that is, when User field is left empty)",
|
"(that is, when User field is left empty)",
|
||||||
)
|
)
|
||||||
|
|
||||||
model_id = fields.Many2one(
|
model_id = fields.Many2one(comodel_name="ir.model", string="Model", required=True)
|
||||||
comodel_name="ir.model", string="Model", required=True
|
|
||||||
)
|
|
||||||
|
|
||||||
model_name = fields.Char(string="Model name", related="model_id.model")
|
model_name = fields.Char(string="Model name", related="model_id.model")
|
||||||
|
|
||||||
|
@ -108,26 +109,30 @@ class TileTile(models.Model):
|
||||||
|
|
||||||
action_id = fields.Many2one(
|
action_id = fields.Many2one(
|
||||||
comodel_name="ir.actions.act_window",
|
comodel_name="ir.actions.act_window",
|
||||||
string="Action", help="Let empty to use the default action related to"
|
string="Action",
|
||||||
" the selected model.",
|
help="Let empty to use the default action related to" " the selected model.",
|
||||||
domain="[('res_model', '=', model_name)]")
|
domain="[('res_model', '=', model_name)]",
|
||||||
|
)
|
||||||
|
|
||||||
active = fields.Boolean(
|
active = fields.Boolean(
|
||||||
compute="_compute_active", search="_search_active", readonly=True
|
compute="_compute_active", search="_search_active", readonly=True
|
||||||
)
|
)
|
||||||
|
|
||||||
hide_if_null = fields.Boolean(
|
hide_if_null = fields.Boolean(
|
||||||
string="Hide if null", help="If checked, the item will be hidden"
|
string="Hide if null",
|
||||||
" if the primary value is null.")
|
help="If checked, the item will be hidden" " if the primary value is null.",
|
||||||
|
)
|
||||||
|
|
||||||
hidden = fields.Boolean(
|
hidden = fields.Boolean(
|
||||||
string="Hidden", compute="_compute_data",
|
string="Hidden", compute="_compute_data", search="_search_hidden"
|
||||||
search="_search_hidden")
|
)
|
||||||
|
|
||||||
# Primary Value
|
# Primary Value
|
||||||
primary_function = fields.Selection(
|
primary_function = fields.Selection(
|
||||||
string="Primary Function", required=True,
|
string="Primary Function",
|
||||||
selection=FIELD_FUNCTION_SELECTION, default="count",
|
required=True,
|
||||||
|
selection=FIELD_FUNCTION_SELECTION,
|
||||||
|
default="count",
|
||||||
)
|
)
|
||||||
|
|
||||||
primary_field_id = fields.Many2one(
|
primary_field_id = fields.Many2one(
|
||||||
|
@ -143,19 +148,20 @@ class TileTile(models.Model):
|
||||||
"ie: '{:,} Kgs' will output '1,000 Kgs' if value is 1000.",
|
"ie: '{:,} Kgs' will output '1,000 Kgs' if value is 1000.",
|
||||||
)
|
)
|
||||||
|
|
||||||
primary_value = fields.Float(
|
primary_value = fields.Float(string="Primary Value", compute="_compute_data")
|
||||||
string="Primary Value", compute="_compute_data")
|
|
||||||
|
|
||||||
primary_formated_value = fields.Char(
|
primary_formated_value = fields.Char(
|
||||||
string="Primary Formated Value", compute="_compute_data")
|
string="Primary Formated Value", compute="_compute_data"
|
||||||
|
)
|
||||||
|
|
||||||
primary_helper = fields.Char(
|
primary_helper = fields.Char(
|
||||||
string="Primary Helper", compute="_compute_helper",
|
string="Primary Helper", compute="_compute_helper", store=True
|
||||||
store=True)
|
)
|
||||||
|
|
||||||
# Secondary Value
|
# Secondary Value
|
||||||
secondary_function = fields.Selection(
|
secondary_function = fields.Selection(
|
||||||
string="Secondary Function", selection=FIELD_FUNCTION_SELECTION,
|
string="Secondary Function",
|
||||||
|
selection=FIELD_FUNCTION_SELECTION,
|
||||||
)
|
)
|
||||||
|
|
||||||
secondary_field_id = fields.Many2one(
|
secondary_field_id = fields.Many2one(
|
||||||
|
@ -171,16 +177,14 @@ class TileTile(models.Model):
|
||||||
"ie: '{:,} Kgs' will output '1,000 Kgs' if value is 1000.",
|
"ie: '{:,} Kgs' will output '1,000 Kgs' if value is 1000.",
|
||||||
)
|
)
|
||||||
|
|
||||||
secondary_value = fields.Float(
|
secondary_value = fields.Float(string="Secondary Value", compute="_compute_data")
|
||||||
string="Secondary Value", compute="_compute_data")
|
|
||||||
|
|
||||||
secondary_formated_value = fields.Char(
|
secondary_formated_value = fields.Char(
|
||||||
string="Secondary Formated Value", compute="_compute_data"
|
string="Secondary Formated Value", compute="_compute_data"
|
||||||
)
|
)
|
||||||
|
|
||||||
secondary_helper = fields.Char(
|
secondary_helper = fields.Char(
|
||||||
string="Secondary Helper", compute="_compute_helper",
|
string="Secondary Helper", compute="_compute_helper", store=True
|
||||||
store=True
|
|
||||||
)
|
)
|
||||||
|
|
||||||
error = fields.Char(string="Error Details", compute="_compute_data")
|
error = fields.Char(string="Error Details", compute="_compute_data")
|
||||||
|
@ -198,19 +202,14 @@ class TileTile(models.Model):
|
||||||
count = model.search_count(eval(domain, eval_context))
|
count = model.search_count(eval(domain, eval_context))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
tile.primary_value = 0.0
|
tile.primary_value = 0.0
|
||||||
tile.primary_formated_value =\
|
tile.primary_formated_value = tile.secondary_formated_value = _("Error")
|
||||||
tile.secondary_formated_value = _("Error")
|
|
||||||
tile.error = str(e)
|
tile.error = str(e)
|
||||||
return
|
return
|
||||||
fields = [
|
fields = [
|
||||||
f.name
|
f.name for f in [tile.primary_field_id, tile.secondary_field_id] if f
|
||||||
for f in [tile.primary_field_id, tile.secondary_field_id]
|
|
||||||
if f
|
|
||||||
]
|
]
|
||||||
read_vals = (
|
read_vals = (
|
||||||
fields
|
fields and model.search_read(eval(domain, eval_context), fields) or []
|
||||||
and model.search_read(eval(domain, eval_context), fields)
|
|
||||||
or []
|
|
||||||
)
|
)
|
||||||
for f in ["primary_", "secondary_"]:
|
for f in ["primary_", "secondary_"]:
|
||||||
f_function = f + "function"
|
f_function = f + "function"
|
||||||
|
@ -231,8 +230,9 @@ class TileTile(models.Model):
|
||||||
value = func(vals or [0.0])
|
value = func(vals or [0.0])
|
||||||
try:
|
try:
|
||||||
tile[f_value] = value
|
tile[f_value] = value
|
||||||
tile[f_formated_value] = (
|
tile[f_formated_value] = (tile[f_format] or "{:,}").format(
|
||||||
tile[f_format] or "{:,}").format(value)
|
value
|
||||||
|
)
|
||||||
if tile.hide_if_null and not value:
|
if tile.hide_if_null and not value:
|
||||||
tile.hidden = True
|
tile.hidden = True
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
|
@ -274,8 +274,9 @@ class TileTile(models.Model):
|
||||||
def _search_hidden(self, operator, operand):
|
def _search_hidden(self, operator, operand):
|
||||||
items = self.search([])
|
items = self.search([])
|
||||||
hidden_tile_ids = [x.id for x in items if x.hidden]
|
hidden_tile_ids = [x.id for x in items if x.hidden]
|
||||||
if (operator == "=" and operand is False) or\
|
if (operator == "=" and operand is False) or (
|
||||||
(operator == "!=" and operand is True):
|
operator == "!=" and operand is True
|
||||||
|
):
|
||||||
domain = [("id", "not in", hidden_tile_ids)]
|
domain = [("id", "not in", hidden_tile_ids)]
|
||||||
else:
|
else:
|
||||||
domain = [("id", "in", hidden_tile_ids)]
|
domain = [("id", "in", hidden_tile_ids)]
|
||||||
|
@ -346,12 +347,14 @@ class TileTile(models.Model):
|
||||||
"target": "current",
|
"target": "current",
|
||||||
"domain": self.domain,
|
"domain": self.domain,
|
||||||
}
|
}
|
||||||
action.update({
|
action.update(
|
||||||
|
{
|
||||||
"name": self.name,
|
"name": self.name,
|
||||||
"display_name": self.name,
|
"display_name": self.name,
|
||||||
"context": dict(self.env.context, group_by=False),
|
"context": dict(self.env.context, group_by=False),
|
||||||
"domain": self.domain,
|
"domain": self.domain,
|
||||||
})
|
}
|
||||||
|
)
|
||||||
return action
|
return action
|
||||||
|
|
||||||
@api.model
|
@api.model
|
||||||
|
@ -359,9 +362,7 @@ class TileTile(models.Model):
|
||||||
if "model_id" in vals and not vals["model_id"].isdigit():
|
if "model_id" in vals and not vals["model_id"].isdigit():
|
||||||
# need to replace model_name with its id
|
# need to replace model_name with its id
|
||||||
vals["model_id"] = (
|
vals["model_id"] = (
|
||||||
self.env["ir.model"]
|
self.env["ir.model"].search([("model", "=", vals["model_id"])]).id
|
||||||
.search([("model", "=", vals["model_id"])])
|
|
||||||
.id
|
|
||||||
)
|
)
|
||||||
self.create(vals)
|
self.create(vals)
|
||||||
|
|
||||||
|
|
|
@ -30,4 +30,3 @@ You can optionally define a secondary value, for that purpose :
|
||||||
* You can define a specific format. (``.format()`` python syntax)
|
* You can define a specific format. (``.format()`` python syntax)
|
||||||
|
|
||||||
.. image:: ../static/description/tile_tile_form_secondary_value.png
|
.. image:: ../static/description/tile_tile_form_secondary_value.png
|
||||||
|
|
||||||
|
|
|
@ -12,4 +12,3 @@
|
||||||
* Restore original Domain + Filter when an action is set.
|
* Restore original Domain + Filter when an action is set.
|
||||||
* Posibility to hide the tile based on a field expression.
|
* Posibility to hide the tile based on a field expression.
|
||||||
* Posibility to set the background color based on a field expression.
|
* Posibility to set the background color based on a field expression.
|
||||||
|
|
||||||
|
|
|
@ -1,14 +1,18 @@
|
||||||
<?xml version="1.0" encoding="utf-8" ?>
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
<odoo>
|
<odoo>
|
||||||
|
|
||||||
<menuitem id="menu_dashboard_tile"
|
<menuitem
|
||||||
|
id="menu_dashboard_tile"
|
||||||
parent="base.menu_board_root"
|
parent="base.menu_board_root"
|
||||||
name="Overview"
|
name="Overview"
|
||||||
sequence="0"/>
|
sequence="0"
|
||||||
|
/>
|
||||||
|
|
||||||
<menuitem id="menu_dashboard_tile_settings"
|
<menuitem
|
||||||
|
id="menu_dashboard_tile_settings"
|
||||||
parent="base.menu_board_root"
|
parent="base.menu_board_root"
|
||||||
name="Settings"
|
name="Settings"
|
||||||
sequence="100"/>
|
sequence="100"
|
||||||
|
/>
|
||||||
|
|
||||||
</odoo>
|
</odoo>
|
||||||
|
|
|
@ -3,7 +3,10 @@
|
||||||
|
|
||||||
<template id="assets_backend" inherit_id="web.assets_backend">
|
<template id="assets_backend" inherit_id="web.assets_backend">
|
||||||
<xpath expr="." position="inside">
|
<xpath expr="." position="inside">
|
||||||
<link rel="stylesheet" href="/web_dashboard_tile/static/src/css/web_dashboard_tile.css"/>
|
<link
|
||||||
|
rel="stylesheet"
|
||||||
|
href="/web_dashboard_tile/static/src/css/web_dashboard_tile.css"
|
||||||
|
/>
|
||||||
</xpath>
|
</xpath>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
|
@ -15,11 +15,25 @@
|
||||||
<form>
|
<form>
|
||||||
<sheet>
|
<sheet>
|
||||||
<div class="oe_button_box" name="button_box">
|
<div class="oe_button_box" name="button_box">
|
||||||
<button name="toggle_active" type="object" class="oe_stat_button" icon="fa-archive">
|
<button
|
||||||
<field name="active" widget="boolean_button" options="{"terminology": "archive"}"/>
|
name="toggle_active"
|
||||||
|
type="object"
|
||||||
|
class="oe_stat_button"
|
||||||
|
icon="fa-archive"
|
||||||
|
>
|
||||||
|
<field
|
||||||
|
name="active"
|
||||||
|
widget="boolean_button"
|
||||||
|
options="{"terminology": "archive"}"
|
||||||
|
/>
|
||||||
</button>
|
</button>
|
||||||
<button class="oe_stat_button" type="action" name="%(web_dashboard_tile.action_category_2_tile)d"
|
<button
|
||||||
attrs="{'invisible': [('tile_qty', '=', 0)]}" icon="fa-list">
|
class="oe_stat_button"
|
||||||
|
type="action"
|
||||||
|
name="%(web_dashboard_tile.action_category_2_tile)d"
|
||||||
|
attrs="{'invisible': [('tile_qty', '=', 0)]}"
|
||||||
|
icon="fa-list"
|
||||||
|
>
|
||||||
<field string="Items" name="tile_qty" widget="statinfo" />
|
<field string="Items" name="tile_qty" widget="statinfo" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -56,8 +70,11 @@
|
||||||
<field name="context">{'active_test': False}</field>
|
<field name="context">{'active_test': False}</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<menuitem id="menu_tile_category"
|
<menuitem
|
||||||
|
id="menu_tile_category"
|
||||||
parent="menu_dashboard_tile_settings"
|
parent="menu_dashboard_tile_settings"
|
||||||
action="action_tile_category" sequence="50"/>
|
action="action_tile_category"
|
||||||
|
sequence="50"
|
||||||
|
/>
|
||||||
|
|
||||||
</odoo>
|
</odoo>
|
||||||
|
|
|
@ -53,17 +53,23 @@
|
||||||
<field name="domain" colspan="4" />
|
<field name="domain" colspan="4" />
|
||||||
<field name="model_name" invisible="1" />
|
<field name="model_name" invisible="1" />
|
||||||
<separator colspan="4" />
|
<separator colspan="4" />
|
||||||
<field name="error" attrs="{'invisible':[('error','=',False)]}"/>
|
<field
|
||||||
|
name="error"
|
||||||
|
attrs="{'invisible':[('error','=',False)]}"
|
||||||
|
/>
|
||||||
</group>
|
</group>
|
||||||
<notebook>
|
<notebook>
|
||||||
<page string="Settings">
|
<page string="Settings">
|
||||||
<group string="Main Value">
|
<group string="Main Value">
|
||||||
<group>
|
<group>
|
||||||
<field name="primary_function" />
|
<field name="primary_function" />
|
||||||
<field name="primary_field_id" attrs="{
|
<field
|
||||||
|
name="primary_field_id"
|
||||||
|
attrs="{
|
||||||
'invisible':[('primary_function','in',[False,'count'])],
|
'invisible':[('primary_function','in',[False,'count'])],
|
||||||
'required':[('primary_function','not in',[False,'count'])],
|
'required':[('primary_function','not in',[False,'count'])],
|
||||||
}"/>
|
}"
|
||||||
|
/>
|
||||||
</group>
|
</group>
|
||||||
<group>
|
<group>
|
||||||
<field name="primary_format" />
|
<field name="primary_format" />
|
||||||
|
@ -72,16 +78,22 @@
|
||||||
<group>
|
<group>
|
||||||
<field name="primary_helper" />
|
<field name="primary_helper" />
|
||||||
<field name="primary_value" />
|
<field name="primary_value" />
|
||||||
<field name="primary_formated_value" attrs="{'invisible':[('primary_value','=',False)]}"/>
|
<field
|
||||||
|
name="primary_formated_value"
|
||||||
|
attrs="{'invisible':[('primary_value','=',False)]}"
|
||||||
|
/>
|
||||||
</group>
|
</group>
|
||||||
</group>
|
</group>
|
||||||
<group string="Secondary Value">
|
<group string="Secondary Value">
|
||||||
<group>
|
<group>
|
||||||
<field name="secondary_function" />
|
<field name="secondary_function" />
|
||||||
<field name="secondary_field_id" attrs="{
|
<field
|
||||||
|
name="secondary_field_id"
|
||||||
|
attrs="{
|
||||||
'invisible':[('secondary_function','in',[False,'count'])],
|
'invisible':[('secondary_function','in',[False,'count'])],
|
||||||
'required':[('secondary_function','not in',[False,'count'])],
|
'required':[('secondary_function','not in',[False,'count'])],
|
||||||
}"/>
|
}"
|
||||||
|
/>
|
||||||
</group>
|
</group>
|
||||||
<group>
|
<group>
|
||||||
<field name="secondary_format" />
|
<field name="secondary_format" />
|
||||||
|
@ -89,7 +101,10 @@
|
||||||
<group>
|
<group>
|
||||||
<field name="secondary_helper" />
|
<field name="secondary_helper" />
|
||||||
<field name="secondary_value" />
|
<field name="secondary_value" />
|
||||||
<field name="secondary_formated_value" attrs="{'invisible':[('secondary_value','=',False)]}"/>
|
<field
|
||||||
|
name="secondary_formated_value"
|
||||||
|
attrs="{'invisible':[('secondary_value','=',False)]}"
|
||||||
|
/>
|
||||||
</group>
|
</group>
|
||||||
</group>
|
</group>
|
||||||
</page>
|
</page>
|
||||||
|
@ -120,25 +135,54 @@
|
||||||
|
|
||||||
<templates>
|
<templates>
|
||||||
<t t-name="kanban-box">
|
<t t-name="kanban-box">
|
||||||
<div t-attf-class="oe_dashboard_tile oe_kanban_global_click" t-attf-style="background-color:#{record.background_color.raw_value}" >
|
<div
|
||||||
|
t-attf-class="oe_dashboard_tile oe_kanban_global_click"
|
||||||
|
t-attf-style="background-color:#{record.background_color.raw_value}"
|
||||||
|
>
|
||||||
<div class="oe_kanban_content">
|
<div class="oe_kanban_content">
|
||||||
<a type="object" name="open_link" args="[]" t-attf-style="color:#{record.font_color.raw_value};">
|
<a
|
||||||
<div style="height:100%;" t-att-class="record.secondary_function.raw_value and 'with_secondary' or 'simple'">
|
type="object"
|
||||||
|
name="open_link"
|
||||||
|
args="[]"
|
||||||
|
t-attf-style="color:#{record.font_color.raw_value};"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style="height:100%;"
|
||||||
|
t-att-class="record.secondary_function.raw_value and 'with_secondary' or 'simple'"
|
||||||
|
>
|
||||||
<div class="tile_label">
|
<div class="tile_label">
|
||||||
<field name="name" />
|
<field name="name" />
|
||||||
</div>
|
</div>
|
||||||
<div class="tile_primary_value" t-att-title="record.primary_helper.raw_value">
|
<div
|
||||||
<t t-set="l" t-value="record.primary_formated_value.raw_value.length" />
|
class="tile_primary_value"
|
||||||
<t t-set="s" t-value="l>=12 and 35 or l>=10 and 45 or l>=8 and 55 or l>=6 and 75 or l>4 and 85 or 100"/>
|
t-att-title="record.primary_helper.raw_value"
|
||||||
<span t-attf-style="font-size: #{s}%;"><field name="primary_formated_value"/></span>
|
>
|
||||||
|
<t
|
||||||
|
t-set="l"
|
||||||
|
t-value="record.primary_formated_value.raw_value.length"
|
||||||
|
/>
|
||||||
|
<t
|
||||||
|
t-set="s"
|
||||||
|
t-value="l>=12 and 35 or l>=10 and 45 or l>=8 and 55 or l>=6 and 75 or l>4 and 85 or 100"
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
t-attf-style="font-size: #{s}%;"
|
||||||
|
><field
|
||||||
|
name="primary_formated_value"
|
||||||
|
/></span>
|
||||||
</div>
|
</div>
|
||||||
<div class="tile_secondary_value" t-att-title="record.secondary_helper.raw_value">
|
<div
|
||||||
<span><field name="secondary_formated_value"/></span>
|
class="tile_secondary_value"
|
||||||
|
t-att-title="record.secondary_helper.raw_value"
|
||||||
|
>
|
||||||
|
<span><field
|
||||||
|
name="secondary_formated_value"
|
||||||
|
/></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="oe_clear"></div>
|
<div class="oe_clear" />
|
||||||
</div>
|
</div>
|
||||||
</t>
|
</t>
|
||||||
</templates>
|
</templates>
|
||||||
|
@ -153,8 +197,11 @@
|
||||||
<field name="view_mode">tree,form,kanban</field>
|
<field name="view_mode">tree,form,kanban</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<menuitem id="menu_tile_tile"
|
<menuitem
|
||||||
|
id="menu_tile_tile"
|
||||||
parent="menu_dashboard_tile_settings"
|
parent="menu_dashboard_tile_settings"
|
||||||
action="action_tile_tile" sequence="10"/>
|
action="action_tile_tile"
|
||||||
|
sequence="10"
|
||||||
|
/>
|
||||||
|
|
||||||
</odoo>
|
</odoo>
|
||||||
|
|
Loading…
Reference in New Issue