odoo14在tree、kanban视图上添加dashboard
阅读原文时间:2023年07月08日阅读:1

效果图:

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

**1、view**:**AbstractView**的子类,这是工厂类:类需要解析 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








案例:

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













                    <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'\]"/> &nbsp;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>  

导入js



All RFQs