效果图:

实现代码:js:view的类型原来1个js给拆分成了4个: view, controller, renderer, model

1、viewAbstractView的子类,这是工厂类:类需要解析 arch字段并设置其它3个类

2、Renderer 渲染器,来自 AbstractRenderer:负责在用户界面中展示数据;

3、Controller一个控制器 (来看AbstractController):用于协调、与网页客户端对话

4、Model一个模型 (来自 AbstractModel):用于和服务端对话、加载数据并处理数据

步骤:一、二、三、四案例

一、MVCR:

var MapController = AbstractController.extend({});
var MapRenderer = AbstractRenderer.extend({});
var MapModel = AbstractModel.extend({});

var MapView = AbstractView.extend({
  config: {
    Model: MapModel,
    Controller: MapController,
    Renderer: MapRenderer,
  },
});

二、告知网页客户端视图名称和实际类之间的映射。
var viewRegistry = require('web.view_registry');
viewRegistry.add('helpdesk_dashboard', HelpdeskDashboardView);

三、现在我们需要告知网页客户端指定的 ir.ui.view需要使用我们的新类。注意这是一个网页客户端的具体考虑。

从服务端的视角来看,我们还是对应看板视图。这么做的相应方式是通过对框架的根节点使用特殊属性js_class

<record id="helpdesk_team_view_kanban" model="ir.ui.view" >
...
  <field name="arch" type="xml">
  <kanban js_class="helpdesk_dashboard">
...
</kanban>
</field>
</record>

案例:

odoo.define('purchase.dashboard', function (require) {
"use strict"; /**
* This file defines the Purchase Dashboard view (alongside its renderer, model
* and controller). This Dashboard is added to the top of list and kanban Purchase
* views, it extends both views with essentially the same code except for
* _onDashboardActionClicked function so we can apply filters without changing our
* current view.
*/ var core = require('web.core');

//这里是列表视图上的扩展:导入的模块
var ListController = require('web.ListController');
var ListModel = require('web.ListModel');
var ListRenderer = require('web.ListRenderer');
var ListView = require('web.ListView');

//这里是kanban视图上的扩展:
var KanbanController = require('web.KanbanController');
var KanbanModel = require('web.KanbanModel');
var KanbanRenderer = require('web.KanbanRenderer');
var KanbanView = require('web.KanbanView');

var SampleServer = require('web.SampleServer');
//注册模块
var view_registry = require('web.view_registry'); var QWeb = core.qweb; // Add mock of method 'retrieve_dashboard' in SampleServer, so that we can have
// the sample data in empty purchase kanban and list view
let dashboardValues;
SampleServer.mockRegistry.add('purchase.order/retrieve_dashboard', () => {
return Object.assign({}, dashboardValues);
}); //--------------------------------------------------------------------------
// List View
//--------------------------------------------------------------------------
//渲染renderer
var PurchaseListDashboardRenderer = ListRenderer.extend({
events:_.extend({}, ListRenderer.prototype.events, {
'click .o_dashboard_action': '_onDashboardActionClicked',
}),
/**
* @override
* @private
* @returns {Promise}
*/
_renderView: function () {
var self = this;
return this._super.apply(this, arguments).then(function () {
var values = self.state.dashboardValues;
var purchase_dashboard = QWeb.render('purchase.PurchaseDashboard', {
values: values,
});
self.$el.prepend(purchase_dashboard);
});
}, /**
* @private
* @param {MouseEvent}
*/
_onDashboardActionClicked: function (e) {
e.preventDefault();
var $action = $(e.currentTarget);
this.trigger_up('dashboard_open_action', {
action_name: $action.attr('name')+"_list",
action_context: $action.attr('context'),
});
},
});


//模型 model
var PurchaseListDashboardModel = ListModel.extend({
/**
* @override
*/
init: function () {
this.dashboardValues = {};
this._super.apply(this, arguments);
}, /**
* @override
*/
__get: function (localID) {
var result = this._super.apply(this, arguments);
if (_.isObject(result)) {
result.dashboardValues = this.dashboardValues[localID];
}
return result;
},
/**
* @override
* @returns {Promise}
*/
__load: function () {
return this._loadDashboard(this._super.apply(this, arguments));
},
/**
* @override
* @returns {Promise}
*/
__reload: function () {
return this._loadDashboard(this._super.apply(this, arguments));
}, /**
* @private
* @param {Promise} super_def a promise that resolves with a dataPoint id
* @returns {Promise -> string} resolves to the dataPoint id
*/
_loadDashboard: function (super_def) {
var self = this;
var dashboard_def = this._rpc({
model: 'purchase.order',
method: 'retrieve_dashboard',
});
return Promise.all([super_def, dashboard_def]).then(function(results) {
var id = results[0];
dashboardValues = results[1];
self.dashboardValues[id] = dashboardValues;
return id;
});
},
});

//控制器:controller
var PurchaseListDashboardController = ListController.extend({
custom_events: _.extend({}, ListController.prototype.custom_events, {
dashboard_open_action: '_onDashboardOpenAction',
}), /**
* @private
* @param {OdooEvent} e
*/
_onDashboardOpenAction: function (e) {
return this.do_action(e.data.action_name,
{additional_context: JSON.parse(e.data.action_context)});
},
});

//视图 view
var PurchaseListDashboardView = ListView.extend({
config: _.extend({}, ListView.prototype.config, {
Model: PurchaseListDashboardModel,
Renderer: PurchaseListDashboardRenderer,
Controller: PurchaseListDashboardController,
}),
});

//--------------------------------------------------------------------------
// Kanban View
//-------------------------------------------------------------------------- var PurchaseKanbanDashboardRenderer = KanbanRenderer.extend({
events:_.extend({}, KanbanRenderer.prototype.events, {
'click .o_dashboard_action': '_onDashboardActionClicked',
}),
/**
* @override
* @private
* @returns {Promise}
*/
_render: function () {
var self = this;
return this._super.apply(this, arguments).then(function () {
var values = self.state.dashboardValues;
var purchase_dashboard = QWeb.render('purchase.PurchaseDashboard', {
values: values,
});
self.$el.prepend(purchase_dashboard);
});
}, /**
* @private
* @param {MouseEvent}
*/
_onDashboardActionClicked: function (e) {
e.preventDefault();
var $action = $(e.currentTarget);
this.trigger_up('dashboard_open_action', {
action_name: $action.attr('name')+"_kanban",
action_context: $action.attr('context'),
});
},
}); var = KanbanModel.extend({
/**
* @override
*/
init: function () {
this.dashboardValues = {};
this._super.apply(this, arguments);
}, /**
* @override
*/
__get: function (localID) {
var result = this._super.apply(this, arguments);
if (_.isObject(result)) {
result.dashboardValues = this.dashboardValues[localID];
}
return result;
},
/**
* @override
* @returns {Promise}
*/
__load: function () {
return this._loadDashboard(this._super.apply(this, arguments));
},
/**
* @override
* @returns {Promise}
*/
__reload: function () {
return this._loadDashboard(this._super.apply(this, arguments));
}, /**
* @private
* @param {Promise} super_def a promise that resolves with a dataPoint id
* @returns {Promise -> string} resolves to the dataPoint id
*/
_loadDashboard: function (super_def) {
var self = this;
var dashboard_def = this._rpc({
model: 'purchase.order',
method: 'retrieve_dashboard',
});
return Promise.all([super_def, dashboard_def]).then(function(results) {
var id = results[0];
dashboardValues = results[1];
self.dashboardValues[id] = dashboardValues;
return id;
});
},
}); var PurchaseKanbanDashboardController = KanbanController.extend({
custom_events: _.extend({}, KanbanController.prototype.custom_events, {
dashboard_open_action: '_onDashboardOpenAction',
}), /**
* @private
* @param {OdooEvent} e
*/
_onDashboardOpenAction: function (e) {
return this.do_action(e.data.action_name,
{additional_context: JSON.parse(e.data.action_context)});
},
});

通过VIEW来设置它
var PurchaseKanbanDashboardView = KanbanView.extend({
config: _.extend({}, KanbanView.prototype.config, {
Model: PurchaseKanbanDashboardModel,
Renderer: PurchaseKanbanDashboardRenderer,
Controller: PurchaseKanbanDashboardController,
}),
});

//视图类型和实际类之间的映射需要进行更新
view_registry.add('purchase_list_dashboard', PurchaseListDashboardView);
view_registry.add('purchase_kanban_dashboard', PurchaseKanbanDashboardView); return {
PurchaseListDashboardModel: PurchaseListDashboardModel,
PurchaseListDashboardRenderer: PurchaseListDashboardRenderer,
PurchaseListDashboardController: PurchaseListDashboardController,
PurchaseKanbanDashboardModel: PurchaseKanbanDashboardModel,
PurchaseKanbanDashboardRenderer: PurchaseKanbanDashboardRenderer,
PurchaseKanbanDashboardController: PurchaseKanbanDashboardController
}; });

Dashboard的page的xml

<?xml version="1.0" encoding="UTF-8"?>
<templates>
<!-- This template is for a table at the top of purchase views that shows some KPIs. -->
<t t-name="purchase.PurchaseDashboard">
<div class="o_purchase_dashboard container">
<div class="row">
<div class="col-sm-5">
<table class="table table-sm">
<!-- thead needed to avoid list view rendering error for some reason -->
<thead>
<tr>
<!-- can't use th tag due to list rendering error when no values in list... -->
<td class="o_text">
<div>All RFQs</div>
</td>

<td class="o_main o_dashboard_action" title="All Draft RFQs" name="purchase.purchase_action_dashboard" context='{"search_default_draft_rfqs": true}'>
<a href="#"><t t-esc="values['all_to_send']"/><br/>To Send</a>
</td>
<td class="o_main o_dashboard_action" title="All Waiting RFQs" name="purchase.purchase_action_dashboard" context='{"search_default_waiting_rfqs": true}'>
<a href="#"><t t-esc="values['all_waiting']"/><br/>Waiting</a>
</td>
<td class="o_main o_dashboard_action" title="All Late RFQs" name="purchase.purchase_action_dashboard" context='{"search_default_late_rfqs": true}'>
<a href="#"><t t-esc="values['all_late']"/><br/>Late</a>
</td>
</tr>
</thead>
<tbody>
<tr>
<td class="o_text">
<div>My RFQs</div>
</td>
<td class="o_main o_dashboard_action" title="My Draft RFQs" name="purchase.purchase_action_dashboard" context='{"search_default_draft_rfqs": true, "search_default_my_purchases": true}'>
<a href="#"><t t-esc="values['my_to_send']"/></a>
</td>
<td class="o_main o_dashboard_action" title="My Waiting RFQs" name="purchase.purchase_action_dashboard" context='{"search_default_waiting_rfqs": true, "search_default_my_purchases": true}'>
<a href="#"><t t-esc="values['my_waiting']"/></a>
</td>
<td class="o_main o_dashboard_action" title="My Late RFQs" name="purchase.purchase_action_dashboard" context='{"search_default_late_rfqs": true, "search_default_my_purchases": true}'>
<a href="#"><t t-esc="values['my_late']"/></a>
</td>
</tr>
</tbody>
</table></div> <div class="col-sm-7">
<table class="table table-sm">
<!-- thead needed to avoid list view rendering error for some reason -->
<thead>
<tr>
<!-- can't use th tag due to list rendering error when no values in list... -->
<td class="o_text">Avg Order Value (<t t-esc="values['company_currency_symbol']"/>)</td>
<td><span><t t-esc="values['all_avg_order_value']"/></span></td>
<td class="o_text">Purchased Last 7 Days (<t t-esc="values['company_currency_symbol']"/>)</td>
<td><span><t t-esc="values['all_total_last_7_days']"/></span></td>
</tr>
</thead>
<tbody>
<tr>
<td class="o_text">Lead Time to Purchase</td>
<td><span><t t-esc="values['all_avg_days_to_purchase']"/>  Days</span></td>
<td class="o_text">RFQs Sent Last 7 Days</td>
<td><span><t t-esc="values['all_sent_rfqs']"/></span></td>
</tr>
</tbody>
</table></div>
</div></div>
</t>
</templates>

导入js

<?xml version="1.0"?>
<odoo>
<template id="assets_backend" name="purchase assets" inherit_id="web.assets_backend">
<xpath expr="." position="inside">
<link rel="stylesheet" type="text/scss" href="/purchase/static/src/scss/purchase.scss"/>
<script type="text/javascript" src="/purchase/static/src/js/purchase_dashboard.js"></script>
</xpath> </template> </odoo>

最后引用:

                <kanban class="o_kanban_mobile" js_class="purchase_kanban_dashboard" sample="1"></kanban>


          <tree  class="o_kanban_mobile" js_class="purchase_kanban_dashboard" sample="1"></tree>
 

odoo14在tree、kanban视图上添加dashboard的更多相关文章

  1. iOS开发如何在一个透明视图上添加不透明的子控件

    相信很多同学都会遇到过这个问题, 当我们弹出一个半透明的遮盖层时, 又想在遮盖层上加一些子视图, 这个时候如果你的遮盖层设置了alpha属性,  你会惊讶的发现, 加载遮盖层上的所有子控件都是透明了, ...

  2. IOS 在一个透明视图上添加不透明的子控件

    环境: 在一个透明的view中添加一个tableview,tableview也变透明了. 解决: 不要这样设置view的透明度 view.backgroundColor = [UIColor clea ...

  3. iOS处理视图上同时添加单击与双击手势的冲突问题

    _bgView.userInteractionEnabled = YES; //在cell上添加 bgView,给bgView添加两个手势检测方法 UITapGestureRecognizer *do ...

  4. 在TableView上添加悬浮按钮

    如果直接在TableVIewController上贴Button的话会导致这个会随之滚动,下面解决在TableView上实现位置固定悬浮按钮的两种方法: 1.在view上贴tableView,然后将悬 ...

  5. 如何在TableView上添加悬浮按钮

    如果直接在TableVIewController上贴Button的话会导致这个会随之滚动,下面解决在TableView上实现位置固定悬浮按钮的两种方法: 1.在view上贴tableView,然后将悬 ...

  6. PDF如何设置书签,怎么在PDF上添加书签

    PDF文件现在作为我们使用最多的一种办公文件,当然我们在使用PDF文件的同时还会需要编辑PDF文件,在使用一个PDF文件页数比较多的时候就需要添加书签,不然每次使用的时候都需要从头开始查找是很麻烦又头 ...

  7. Android自定义视图一:扩展现有的视图,添加新的XML属性

    这个系列是老外写的,干货!翻译出来一起学习.如有不妥,不吝赐教! Android自定义视图一:扩展现有的视图,添加新的XML属性 Android自定义视图二:如何绘制内容 Android自定义视图三: ...

  8. ASP.NET#在设计窗口上添加了一个SqlDataSource控件后,没有显示出来?

    在设计窗口上添加了一个SqlDataSource控件后,没有显示出来,但后台代码是有的 处理的办法:菜单栏->视图->可视辅助->ASP.NET非可视控件 (我用的是VS2012)

  9. django class类即视图类添加装饰器的几种方法

    根据别人发布整理,个人爱好收集(原文:https://blog.csdn.net/mydistance/article/details/83958655 ) 第一种:定义函数装饰器,在函数,类中使用函 ...

随机推荐

  1. H5简介(转)

    H5究竟是什么? "HTML5(WEB前端)技术由HTML(结构).CSS(样式).JavaScript(行为)组成.HTML5是WEB的未来,HTML5不仅在PC端,更是在移动端上也有广泛 ...

  2. 循序渐进BootstrapVue,开发公司门户网站(2)--- 使用wow.js动画组件以及自定义的CSS样式处理动态效果

    在我们开发的页面中,让页面有一些动画效果,可以让页面更加有吸引力,只要不是处理太过,一般人还是希望有一些动态效果,如滚动动画加载,悬停处理变化等效果,本篇随笔介绍使用wow.js动画组件以及自定义的C ...

  3. Linux常见信号介绍

    1.信号 首先信号我们要和信号量区分开来,虽然两者都是操作系统进程通信的方式.可以简单的理解,信号是用来通知进程发生了什么需要做什么,信号量一般是用作进程同步(pv操作) 2.常见信号量 (以下数字标 ...

  4. sql数据库新建作业,新建步骤时报错从 IClassFactory 为 CLSID 为 {AA40D1D6-CAEF-4A56-B9BB-D0D3DC976BA2} 的 COM 组件创建实例失败,原因是出现以下错误: c001f011。 (Microsoft.SqlServer.ManagedDTS)

    简单粗暴的重启sql数据库 其他网上找的方法 32位操作系统: 打开运行(命令提示符), 一.输入 cd c:\windows\system32 进入到c:\windows\system32路径中 二 ...

  5. iOS-block本质是什么?

    一: block的原理是怎样的?本质是什么? block本质上也是一个OC对象,因为它的内部也有个isa指针 block是封装了函数调用以及函数调用环境的OC对象 接下来我们将通过底层源码来论证上诉两 ...

  6. [.NET大牛之路 002] 什么是 .NET

    .NET 是一个开发平台,或者叫开发者平台.使用 .NET 你可以创建不同类型的应用程序,使用多种开发语言.编辑器和工具库创建网页.手机.桌面以及游戏等应用.其核心特点是:免费.开源和跨平台. 语言和 ...

  7. Go语言中slice作为参数传递时遇到的一些“坑”

    前言 相信看到这个题目,可能大家都觉得是一个老生常谈的月经topic了.一直以来其实把握一个"值传递"基本上就能理解各种情况了,不过最近遇到了更深一点的"小坑" ...

  8. 运行cmd时提示你可能没有适当的权限访问该项目

    Windows无法访问指定设备.路径或文件.你可能没有适当的权限访问该项目.   方法/步骤   在C:\Windows\System32目录下中找到cmd.exe文件   右键点击 "属性 ...

  9. idea debug无法启动 Error running 'Tomcat8': Unable to open debugger port (127.0.0.1:50168): java.net.SocketException "socket closed

    在日志里显示在 event log 里的 Error running 'server_web': Address localhost:1099 is already in use 显示1099单口已被 ...

  10. POJ 3449 Geometric Shapes 判断多边形相交

    题意不难理解,给出多个多边形,输出多边形间的相交情况(嵌套不算相交),思路也很容易想到.枚举每一个图形再枚举每一条边 恶心在输入输出,不过还好有sscanf(),不懂可以查看cplusplus网站 根 ...