[REF] *: adapt all client actions

to ControlPanel/Search view refactoring.

The ControlPanel being now inside the DOM of client actions, those
existing widgets needed to be adapted (in the way they define if
and how they want a ControlPanel, and in the way the manipulate
their DOM as it slightly changed). Tests needed to be adapted as
well.

Part of task 1893568

Co-authored-by: Mathieu Duckerts-Antoine <dam@odoo.com>
Co-authored-by: Martin Geubelle <mge@odoo.com>
This commit is contained in:
Aaron Bohy
2018-12-07 13:16:07 +00:00
committed by Géry Debongnie
co-authored by Mathieu Duckerts-Antoine Martin Geubelle
parent 40dd121938
commit b1ef0001f6
19 changed files with 111 additions and 282 deletions
@@ -4,18 +4,16 @@ odoo.define('account.ReconciliationClientAction', function (require) {
var AbstractAction = require('web.AbstractAction');
var ReconciliationModel = require('account.ReconciliationModel');
var ReconciliationRenderer = require('account.ReconciliationRenderer');
var ControlPanelMixin = require('web.ControlPanelMixin');
var Widget = require('web.Widget');
var core = require('web.core');
var _t = core._t;
/**
* Widget used as action for 'account.bank.statement' reconciliation
*/
var StatementAction = AbstractAction.extend(ControlPanelMixin, {
var StatementAction = AbstractAction.extend({
hasControlPanel: true,
title: core._t('Bank Reconciliation'),
template: 'reconciliation',
contentTemplate: 'reconciliation',
custom_events: {
change_mode: '_onAction',
change_filter: '_onAction',
@@ -34,7 +32,7 @@ var StatementAction = AbstractAction.extend(ControlPanelMixin, {
load_more: '_onLoadMore',
reload: 'reload',
},
config: {
config: _.extend({}, AbstractAction.prototype.config, {
// used to instantiate the model
Model: ReconciliationModel.StatementModel,
// used to instantiate the action interface
@@ -47,7 +45,7 @@ var StatementAction = AbstractAction.extend(ControlPanelMixin, {
defaultDisplayQty: 10,
// number of moves lines displayed in 'match' mode
limitMoveLines: 15,
},
}),
/**
* @override
@@ -65,9 +63,6 @@ var StatementAction = AbstractAction.extend(ControlPanelMixin, {
limitMoveLines: params.params && params.params.limitMoveLines || this.config.limitMoveLines,
});
this.widgets = [];
if (!this.action_manager) {
this.set_cp_bus(new Widget());
}
// Adding values from the context is necessary to put this information in the url via the action manager so that
// you can retrieve it if the person shares his url or presses f5
_.each(params.params, function (value, name) {
@@ -90,13 +85,14 @@ var StatementAction = AbstractAction.extend(ControlPanelMixin, {
var self = this;
var def = this.model.load(this.params.context).then(this._super.bind(this));
return def.then(function () {
self.title = self.model.bank_statement_id ? self.model.bank_statement_id.display_name : self.title;
var title = self.model.bank_statement_id && self.model.bank_statement_id.display_name;
self._setTitle(title);
self.renderer = new self.config.ActionRenderer(self, self.model, {
'bank_statement_id': self.model.bank_statement_id,
'valuenow': self.model.valuenow,
'valuemax': self.model.valuemax,
'defaultDisplayQty': self.model.defaultDisplayQty,
'title': self.title,
'title': title,
});
});
},
@@ -124,9 +120,6 @@ var StatementAction = AbstractAction.extend(ControlPanelMixin, {
start: function () {
var self = this;
this.set("title", this.title);
this.update_control_panel({search_view_hidden: true}, {clear: true});
this.renderer.prependTo(self.$('.o_form_sheet'));
this._renderLines();
@@ -141,6 +134,8 @@ var StatementAction = AbstractAction.extend(ControlPanelMixin, {
this.renderer._renderNotifications(this.model.statement.notifications);
this._openFirstLine();
}
return this._super.apply(this, arguments);
},
/**
@@ -151,7 +146,7 @@ var StatementAction = AbstractAction.extend(ControlPanelMixin, {
do_show: function () {
this._super.apply(this, arguments);
if (this.action_manager) {
this.update_control_panel({search_view_hidden: true}, {clear: true});
this.updateControlPanel({clear: true});
this.action_manager.do_push_state({
action: this.params.tag,
active_id: this.params.res_id,
@@ -354,14 +349,14 @@ var StatementAction = AbstractAction.extend(ControlPanelMixin, {
*/
var ManualAction = StatementAction.extend({
title: core._t('Journal Items to Reconcile'),
config: {
config: _.extend({}, StatementAction.prototype.config, {
Model: ReconciliationModel.ManualModel,
ActionRenderer: ReconciliationRenderer.ManualRenderer,
LineRenderer: ReconciliationRenderer.ManualLineRenderer,
params: ['company_ids', 'mode', 'partner_ids', 'account_ids'],
defaultDisplayQty: 30,
limitMoveLines: 15,
},
}),
//--------------------------------------------------------------------------
// Handlers
@@ -700,7 +700,7 @@ QUnit.module('account', {
assert.ok(clientAction.widgets[1].$('.match div.load-more a:visible').length, "should display the 'load more' button");
assert.equal(clientAction.widgets[1].$('.match div.load-more span').text(), 3, "should display 3 items remaining");
clientAction.widgets[1].$('.match div.load-more a').trigger('click');
assert.containsN(clientAction.widgets[1], '.mv_line', 8, "should load 3 more records"),
assert.containsN(clientAction.widgets[1], '.mv_line', 8, "should load 3 more records");
assert.notOk(clientAction.widgets[1].$('.match div.load-more a:visible').length, "should not display the 'load more' button anymore");
assert.ok(clientAction.widgets[0].$('caption button.btn-secondary:visible').length, "should display the 'validate' button");
@@ -2,7 +2,6 @@ odoo.define('base_import.import', function (require) {
"use strict";
var AbstractAction = require('web.AbstractAction');
var ControlPanelMixin = require('web.ControlPanelMixin');
var core = require('web.core');
var session = require('web.session');
var time = require('web.time');
@@ -72,8 +71,9 @@ function dataFilteredQuery(q) {
q.callback({results: suggestions});
}
var DataImport = AbstractAction.extend(ControlPanelMixin, {
template: 'ImportView',
var DataImport = AbstractAction.extend({
hasControlPanel: true,
contentTemplate: 'ImportView',
opts: [
{name: 'encoding', label: _lt("Encoding:"), value: ''},
{name: 'separator', label: _lt("Separator:"), value: ''},
@@ -137,7 +137,7 @@ var DataImport = AbstractAction.extend(ControlPanelMixin, {
// import object id
this.id = null;
this.session = session;
action.display_name = _t('Import a File'); // Displayed in the breadcrumbs
this._title = _t('Import a File'); // Displayed in the breadcrumbs
this.do_not_change_match = false;
},
/**
@@ -145,13 +145,14 @@ var DataImport = AbstractAction.extend(ControlPanelMixin, {
*/
willStart: function () {
var self = this;
return this._rpc({
var def = this._rpc({
model: this.res_model,
method: 'get_import_templates',
context: this.parent_context,
}).then(function (result) {
self.importTemplates = result;
});
return $.when(this._super.apply(this, arguments), def);
},
start: function () {
var self = this;
@@ -170,7 +171,7 @@ var DataImport = AbstractAction.extend(ControlPanelMixin, {
var status = {
cp_content: {$buttons: self.$buttons},
};
self.update_control_panel(status);
self.updateControlPanel(status);
})
);
},
@@ -189,7 +190,7 @@ var DataImport = AbstractAction.extend(ControlPanelMixin, {
this.$buttons.filter('.o_import_import').on('click', this.import.bind(this));
this.$buttons.filter('.o_import_file_reload').on('click', this.loaded_file.bind(this));
this.$buttons.filter('.oe_import_file').on('click', function () {
self.$('.oe_import_file').click();
self.$('.o_content .oe_import_file').click();
});
this.$buttons.filter('.o_import_cancel').on('click', function(e) {
e.preventDefault();
@@ -8,7 +8,7 @@ var _t = core._t;
var GreetingMessage = AbstractAction.extend({
template: 'HrAttendanceGreetingMessage',
contentTemplate: 'HrAttendanceGreetingMessage',
events: {
"click .o_hr_attendance_button_dismiss": function() { this.do_action(this.next_action, {clear_breadcrumbs: true}); },
@@ -61,6 +61,7 @@ var GreetingMessage = AbstractAction.extend({
if (this.activeBarcode) {
core.bus.on('barcode_scanned', this, this._onBarcodeScanned);
}
return this._super.apply(this, arguments);
},
welcome_message: function() {
@@ -4,11 +4,9 @@ odoo.define('hr_attendance.my_attendances', function (require) {
var AbstractAction = require('web.AbstractAction');
var core = require('web.core');
var QWeb = core.qweb;
var _t = core._t;
var MyAttendances = AbstractAction.extend({
contentTemplate: 'HrAttendanceMyMainMenu',
events: {
"click .o_hr_attendance_sign_in_out_icon": function() {
this.$('.o_hr_attendance_sign_in_out_icon').attr("disabled", "disabled");
@@ -16,7 +14,7 @@ var MyAttendances = AbstractAction.extend({
},
},
start: function () {
willStart: function () {
var self = this;
var def = this._rpc({
@@ -26,7 +24,6 @@ var MyAttendances = AbstractAction.extend({
})
.then(function (res) {
self.employee = res.length && res[0];
self.$el.html(QWeb.render("HrAttendanceMyMainMenu", {widget: self}));
});
return $.when(def, this._super.apply(this, arguments));
@@ -57,7 +57,7 @@ QUnit.module('HR Attendance', {
assert.expect(1);
var $target = $('#qunit-fixture');
var clientAction = new MyAttendances(null);
var clientAction = new MyAttendances(null, {});
testUtils.mock.addMockEnvironment(clientAction, {
data: this.data,
session: {
@@ -78,7 +78,7 @@ QUnit.module('HR Attendance', {
var $target = $('#qunit-fixture');
var self = this;
var rpcCount = 0;
var clientAction = new KioskMode(null);
var clientAction = new KioskMode(null, {});
testUtils.mock.addMockEnvironment(clientAction, {
data: this.data,
session: {
@@ -121,7 +121,7 @@ QUnit.module('HR Attendance', {
},
next_action: "hr_attendance.hr_attendance_action_kiosk_mode",
barcode: barcode,
}
};
var clientAction = new GreetingMessage(null, action);
testUtils.mock.addMockEnvironment(clientAction, {
data: self.data,
@@ -146,7 +146,7 @@ QUnit.module('HR Attendance', {
clientAction.appendTo(target);
clientActions.push(clientAction);
};
}
// init - mock coming from kiosk
createGreetingMessage ($target, 1);
+17 -51
View File
@@ -7,13 +7,9 @@ var ThreadWidget = require('mail.widget.Thread');
var AbstractAction = require('web.AbstractAction');
var config = require('web.config');
var ControlPanelMixin = require('web.ControlPanelMixin');
var core = require('web.core');
var data = require('web.data');
var Dialog = require('web.Dialog');
var dom = require('web.dom');
var pyUtils = require('web.py_utils');
var SearchView = require('web.SearchView');
var session = require('web.session');
var QWeb = core.qweb;
@@ -240,8 +236,8 @@ var ModeratorRejectMessageDialog = Dialog.extend({
},
});
var Discuss = AbstractAction.extend(ControlPanelMixin, {
template: 'mail.discuss',
var Discuss = AbstractAction.extend({
contentTemplate: 'mail.discuss',
custom_events: {
discard_extended_composer: '_onDiscardExtendedComposer',
message_moderation: '_onMessageModeration',
@@ -258,6 +254,11 @@ var Discuss = AbstractAction.extend(ControlPanelMixin, {
'click .o_mail_partner_unpin': '_onUnpinChannel',
'input .o_discuss_sidebar_quick_search input': '_onInputSidebarQuickSearchInput',
},
hasControlPanel: true,
loadControlPanel: true,
withSearchBar: true,
searchMenuTypes: ['filter', 'favorite'],
/**
* @override
* @param {Object} [options]
@@ -268,8 +269,8 @@ var Discuss = AbstractAction.extend(ControlPanelMixin, {
this._super.apply(this, arguments);
this.action = action;
this.context = action.context;
this.action_manager = parent;
this.dataset = new data.DataSetSearch(this, 'mail.message');
this.domain = [];
this.options = options || {};
@@ -286,21 +287,14 @@ var Discuss = AbstractAction.extend(ControlPanelMixin, {
this._selectedMessage = null;
this._throttledUpdateThreads = _.throttle(
this._updateThreads.bind(this), 100, { leading: false });
this.controlPanelParams.modelName = 'mail.message';
},
/**
* @override
*/
willStart: function () {
var self = this;
var viewID = this.action &&
this.action.search_view_id &&
this.action.search_view_id[0];
var def = this
.loadFieldView(this.dataset, viewID, 'search')
.then(function (fieldsView) {
self.fields_view = fieldsView;
});
return $.when(this._super(), this.call('mail_service', 'isReady'), def);
return $.when(this._super(), this.call('mail_service', 'isReady'));
},
/**
* @override
@@ -332,11 +326,11 @@ var Discuss = AbstractAction.extend(ControlPanelMixin, {
this._basicComposer.appendTo(this.$('.o_mail_discuss_content')));
defs.push(
this._extendedComposer.appendTo(this.$('.o_mail_discuss_content')));
defs.push(this._renderSearchView());
defs.push(this._super.apply(this, arguments));
return this.alive($.when.apply($, defs))
return $.when.apply($, defs)
.then(function () {
return self.alive(self._setThread(self._defaultThreadID));
return self._setThread(self._defaultThreadID);
})
.then(function () {
self._initThreads();
@@ -742,26 +736,6 @@ var Discuss = AbstractAction.extend(ControlPanelMixin, {
.on('click', '.o_mail_discuss_button_select_all', this._onSelectAllClicked.bind(this))
.on('click', '.o_mail_discuss_button_unselect_all', this._onUnselectAllClicked.bind(this));
},
/**
* @private
* @returns {Deferred}
*/
_renderSearchView: function () {
var self = this;
var options = {
$buttons: $('<div>'),
action: this.action,
disable_groupby: true,
};
this.searchview = new SearchView(this, this.dataset, this.fields_view, options);
return this.alive(this.searchview.appendTo($('<div>')))
.then(function () {
self.$searchview_buttons = self.searchview.$buttons;
// manually call do_search to generate the initial domain and filter
// the messages in the default thread
self.searchview.do_search();
});
},
/**
* Render the sidebar of discuss app
*
@@ -982,7 +956,7 @@ var Discuss = AbstractAction.extend(ControlPanelMixin, {
// Update control panel before focusing the composer, otherwise
// focus is on the searchview
self.set("title", self._thread.getTitle());
self._setTitle('#' + self._thread.getName());
self._updateControlPanel();
self._updateControlPanelButtons(self._thread);
@@ -1106,13 +1080,10 @@ var Discuss = AbstractAction.extend(ControlPanelMixin, {
* @private
*/
_updateControlPanel: function () {
this.update_control_panel({
this.updateControlPanel({
cp_content: {
$buttons: this.$buttons,
$searchview: this.searchview.$el,
$searchview_buttons: this.$searchview_buttons,
},
searchview: this.searchview,
});
},
/**
@@ -1532,12 +1503,7 @@ var Discuss = AbstractAction.extend(ControlPanelMixin, {
*/
_onSearch: function (ev) {
ev.stopPropagation();
var session = this.getSession();
var result = pyUtils.eval_domains_and_contexts({
domains: ev.data.domains,
contexts: [session.user_context],
});
this.domain = result.domain;
this.domain = ev.data.domain;
if (this._thread) {
// initially (when _onSearch is called manually), there is no
// thread set yet, so don't try to fetch and render the thread as
+11 -94
View File
@@ -1,11 +1,9 @@
odoo.define('mail.discuss_test', function (require) {
"use strict";
var Discuss = require('mail.Discuss');
var mailTestUtils = require('mail.testUtils');
var concurrency = require('web.concurrency');
var SearchView = require('web.SearchView');
var testUtils = require('web.test_utils');
var createDiscuss = mailTestUtils.createDiscuss;
@@ -108,7 +106,7 @@ QUnit.test('basic rendering', function (assert) {
});
QUnit.test('searchview options visibility', function (assert) {
assert.expect(4);
assert.expect(5);
var done = assert.async();
createDiscuss({
@@ -119,17 +117,17 @@ QUnit.test('searchview options visibility', function (assert) {
services: this.services,
})
.then(function (discuss) {
var $searchviewOptions = $('.o_search_options > div');
var $searchviewOptionsToggler = $('.o_searchview_more.fa.fa-search-minus');
assert.strictEqual($searchviewOptions.length, 1,
assert.containsOnce(discuss, '.o_control_panel .o_search_options',
"should have search options");
assert.strictEqual($searchviewOptionsToggler.length, 1,
assert.hasClass(discuss.$('.o_control_panel .o_searchview_more.fa'), 'fa-search-minus',
"should have a button to toggle search options");
assert.strictEqual($searchviewOptions.css('display'), 'block',
"search options should be visible by default");
testUtils.dom.click($searchviewOptionsToggler);
assert.strictEqual($searchviewOptions.css('display'), 'none',
assert.isVisible(discuss.$('.o_control_panel .o_search_options'),
"search options should be visible by default");
testUtils.dom.click(discuss.$('.o_control_panel .o_searchview_more.fa'));
assert.hasClass(discuss.$('.o_control_panel .o_searchview_more.fa'), 'fa-search-plus',
"should have a button to toggle search options");
assert.isNotVisible(discuss.$('.o_control_panel .o_search_options'),
"search options should be hidden after clicking on search option toggler");
discuss.destroy();
@@ -181,7 +179,7 @@ QUnit.test('searchview filter messages', function (assert) {
// interact with searchview so that there is only once message
$('.o_searchview_input').val("ab").trigger('keyup');
$('.o_searchview').trigger($.Event('keydown', { which: $.ui.keyCode.ENTER }));
$('.o_searchview_input_container').trigger($.Event('keydown', { which: $.ui.keyCode.ENTER }));
assert.strictEqual($('.o_searchview_facet').length, 1,
"the searchview should have a facet");
@@ -193,7 +191,7 @@ QUnit.test('searchview filter messages', function (assert) {
// interact with search view so that there are no matching messages
testUtils.dom.click($('.o_facet_remove'));
$('.o_searchview_input').val("abcd").trigger('keyup');
$('.o_searchview').trigger($.Event('keydown', { which: $.ui.keyCode.ENTER }));
$('.o_searchview_input_container').trigger($.Event('keydown', { which: $.ui.keyCode.ENTER }));
assert.strictEqual($('.o_searchview_facet').length, 1,
"the searchview should have a facet");
@@ -798,87 +796,6 @@ QUnit.test('"Unstar all" button should reset the starred counter', function (ass
});
});
QUnit.test('do not crash when destroyed before start is completed', function (assert) {
assert.expect(3);
var discuss;
testUtils.mock.patch(Discuss, {
init: function () {
discuss = this;
this._super.apply(this, arguments);
},
});
createDiscuss({
id: 1,
context: {},
params: {},
data: this.data,
services: this.services,
mockRPC: function (route, args) {
if (args.method) {
assert.step(args.method);
}
var result = this._super.apply(this, arguments);
if (args.method === 'message_fetch') {
discuss.destroy();
}
return result;
},
});
assert.verifySteps([
"load_views",
"message_fetch"
]);
testUtils.mock.unpatch(Discuss);
});
QUnit.test('do not crash when destroyed between start en end of _renderSearchView', function (assert) {
assert.expect(2);
var discuss;
testUtils.mock.patch(Discuss, {
init: function () {
discuss = this;
this._super.apply(this, arguments);
},
});
var def = $.Deferred();
testUtils.mock.patch(SearchView, {
willStart: function () {
var result = this._super.apply(this, arguments);
return def.then($.when(result));
},
});
createDiscuss({
id: 1,
context: {},
params: {},
data: this.data,
services: this.services,
mockRPC: function (route, args) {
if (args.method) {
assert.step(args.method);
}
return this._super.apply(this, arguments);
},
});
discuss.destroy();
def.resolve();
assert.verifySteps([
"load_views",
]);
testUtils.mock.unpatch(Discuss);
testUtils.mock.unpatch(SearchView);
});
QUnit.test('confirm dialog when administrator leave (not chat) channel', function (assert) {
assert.expect(2);
var done = assert.async();
@@ -8,7 +8,7 @@ var MailService = require('mail.Service');
var AbstractStorageService = require('web.AbstractStorageService');
var Class = require('web.Class');
var ControlPanel = require('web.ControlPanel');
var ControlPanelView = require('web.ControlPanelView');
var RamStorage = require('web.RamStorage');
var testUtils = require('web.test_utils');
var Widget = require('web.Widget');
@@ -37,10 +37,7 @@ function createDiscuss(params) {
};
testUtils.mock.addMockEnvironment(parent, params);
var discuss = new Discuss(parent, params);
discuss.set_cp_bus(new Widget());
var selector = params.debug ? 'body' : '#qunit-fixture';
var controlPanel = new ControlPanel(parent);
controlPanel.appendTo($(selector));
// override 'destroy' of discuss so that it calls 'destroy' on the parent
// instead, which is the parent of discuss and the mockServer.
@@ -51,9 +48,6 @@ function createDiscuss(params) {
parent.destroy();
};
// link the view to the control panel
discuss.set_cp_bus(controlPanel.get_bus());
return discuss.appendTo($(selector)).then(function () {
return discuss;
});
@@ -493,7 +493,7 @@ QUnit.test('do not autofocus chat window on receiving new direct message', funct
}
});
var $formInput = form.$('input');
var $formInput = form.$('input[name=display_name]');
$formInput.focus();
assert.equal(document.activeElement, $formInput[0],
+3 -3
View File
@@ -34,7 +34,7 @@ var MrpBomReport = stock_report_generic.extend({
set_html: function() {
var self = this;
return this._super().then(function () {
self.$el.html(self.data.lines);
self.$('.o_content').html(self.data.lines);
self.renderSearch();
self.update_cp();
});
@@ -103,7 +103,7 @@ var MrpBomReport = stock_report_generic.extend({
$searchview_buttons: this.$searchView
},
};
return this.update_control_panel(status);
return this.updateControlPanel(status);
},
renderSearch: function () {
this.$buttonPrint = $(QWeb.render('mrp.button'));
@@ -187,7 +187,7 @@ var MrpBomReport = stock_report_generic.extend({
_reload: function () {
var self = this;
return this.get_html().then(function () {
self.$el.html(self.data.lines);
self.$('.o_content').html(self.data.lines);
self._reload_report_type();
});
},
@@ -2,16 +2,15 @@ odoo.define('sale_timesheet.ProjectPlan', function (require) {
'use strict';
var AbstractAction = require('web.AbstractAction');
var ControlPanelMixin = require('web.ControlPanelMixin');
var core = require('web.core');
var data = require('web.data');
var pyUtils = require('web.py_utils');
var SearchView = require('web.SearchView');
var _t = core._t;
var QWeb = core.qweb;
var ProjectPlan = AbstractAction.extend(ControlPanelMixin, {
var ProjectPlan = AbstractAction.extend({
custom_events: {
search: '_onSearch',
},
events: {
"click a[type='action']": "_onClickAction",
"click .o_timesheet_plan_redirect": '_onRedirect',
@@ -19,64 +18,31 @@ var ProjectPlan = AbstractAction.extend(ControlPanelMixin, {
"click .o_timesheet_plan_non_billable_task": "_onClickNonBillableTask",
"click .o_timesheet_plan_sale_timesheet_people_time .progress-bar": '_onClickEmployeeProgressbar',
},
hasControlPanel: true,
loadControlPanel: true,
withSearchBar: true,
searchMenuTypes: ['filter', 'favorite'],
/**
* @override
*/
init: function (parent, action) {
init: function (parent, action) {
this._super.apply(this, arguments);
this.action = action;
this.context = action.context;
this.action_manager = parent;
this.set('title', action.name || _t('Overview'));
this._title = action.name || _t('Overview');
this.project_ids = [];
},
/**
* @override
*/
willStart: function () {
var self = this;
var view_id = this.action && this.action.search_view_id && this.action.search_view_id[0];
var def = this
.loadViews('project.project', this.action.context || {}, [[view_id, 'search']])
.then(function (result) {
self.fields_view = result.search;
});
return $.when(this._super(), def);
this.controlPanelParams.modelName = 'project.project';
},
/**
* @override
*/
start: function () {
var self = this;
// find default search from context
var search_defaults = {};
var context = this.action.context || [];
_.each(context, function (value, key) {
var match = /^search_default_(.*)$/.exec(key);
if (match) {
search_defaults[match[1]] = value;
}
});
// create searchview
var options = {
$buttons: $("<div>"),
action: this.action,
disable_groupby: true,
search_defaults: search_defaults,
};
var dataset = new data.DataSetSearch(this, 'project.project');
this.searchview = new SearchView(this, dataset, this.fields_view, options);
this.searchview.on('search', this, this._onSearch);
var def1 = this._super.apply(this, arguments);
var def2 = this.searchview.appendTo($("<div>")).then(function () {
self.$searchview_buttons = self.searchview.$buttons.contents();
});
return $.when(def1, def2).then(function(){
self.searchview.do_search();
return this._super.apply(this, arguments).then(function () {
// TODO: maybe not the correct way
return self._controlPanel._reportNewQueryAndRender();
});
},
@@ -89,7 +55,7 @@ var ProjectPlan = AbstractAction.extend(ControlPanelMixin, {
*/
do_show: function () {
this._super.apply(this, arguments);
this.searchview.do_search();
this._updateControlPanel();
this.action_manager.do_push_state({
action: this.action.id,
active_id: this.action.context.active_id,
@@ -107,7 +73,7 @@ var ProjectPlan = AbstractAction.extend(ControlPanelMixin, {
* @param {string|html} dom
*/
_refreshPlan: function (dom) {
this.$el.html(dom);
this.$('.o_content').html(dom);
},
/**
@@ -136,17 +102,14 @@ var ProjectPlan = AbstractAction.extend(ControlPanelMixin, {
if (this.$buttons) {
this.$buttons.off().destroy();
}
var buttons = buttons || [];
buttons = buttons || [];
this.$buttons = $(QWeb.render("project.plan.ControlButtons", {'buttons': buttons}));
this.$buttons.on('click', '.o_timesheet_plan_btn_action', this._onClickControlButton.bind(this));
// refresh control panel
this.update_control_panel({
this.updateControlPanel({
cp_content: {
$buttons: this.$buttons,
$searchview: this.searchview.$el,
$searchview_buttons: this.$searchview_buttons,
},
searchview: this.searchview,
});
},
@@ -245,9 +208,9 @@ var ProjectPlan = AbstractAction.extend(ControlPanelMixin, {
var parameters = {
domain: data.domain || [],
res_model: data.resModel,
}
};
if (data.resId) {
parameters['res_id'] = data.resId;
parameters.res_id = data.resId;
}
return this._rpc({
route:"/timesheet/plan/action",
@@ -260,8 +223,7 @@ var ProjectPlan = AbstractAction.extend(ControlPanelMixin, {
* @private
* @param {MouseEvent} event
*/
_onClickNonBillableTask: function (event) {
var self = this;
_onClickNonBillableTask: function () {
this.do_action({
name: _t('Non Billable Tasks'),
type: 'ir.actions.act_window',
@@ -299,14 +261,7 @@ var ProjectPlan = AbstractAction.extend(ControlPanelMixin, {
*/
_onSearch: function (event) {
event.stopPropagation();
var session = this.getSession();
// group by are disabled, so we don't take care of them
var result = pyUtils.eval_domains_and_contexts({
domains: event.data.domains,
contexts: [session.user_context].concat(event.data.contexts)
});
this._fetchPlan(result.domain);
this._fetchPlan(event.data.domain);
},
});
@@ -64,8 +64,8 @@ QUnit.module('Timesheet Plan', {
"/web/dataset/call_kw/project.project",
"/timesheet/plan"
]);
assert.strictEqual(plan.$el.text(), 'Banach-Tarski', 'should have rendered html content');
assert.strictEqual(plan.get('title'), 'Overview',
assert.strictEqual(plan.$('.o_content').text(), 'Banach-Tarski', 'should have rendered html content');
assert.strictEqual(plan.$('.o_control_panel .breadcrumb-item').text(), 'Overview',
'default title should be set');
plan.destroy();
});
@@ -86,7 +86,7 @@ QUnit.module('Timesheet Plan', {
return this._super.apply(this, arguments);
},
});
assert.strictEqual(plan.get('title'), 'Fibonacci',
assert.strictEqual(plan.$('.o_control_panel .breadcrumb-item').text(), 'Fibonacci',
'title should be set from the action name');
plan.destroy();
});
@@ -4,17 +4,18 @@ odoo.define('stock.stock_report_generic', function (require) {
var AbstractAction = require('web.AbstractAction');
var core = require('web.core');
var session = require('web.session');
var ControlPanelMixin = require('web.ControlPanelMixin');
var session = require('web.session');
var ReportWidget = require('stock.ReportWidget');
var framework = require('web.framework');
var crash_manager = require('web.crash_manager');
var QWeb = core.qweb;
var stock_report_generic = AbstractAction.extend(ControlPanelMixin, {
var stock_report_generic = AbstractAction.extend({
hasControlPanel: true,
// Stores all the parameters of the action.
init: function(parent, action) {
this._super.apply(this, arguments);
this.actionManager = parent;
this.given_context = session.user_context;
this.controller_url = action.context.url;
@@ -26,17 +27,16 @@ var stock_report_generic = AbstractAction.extend(ControlPanelMixin, {
this.given_context.ttype = action.context.ttype || false;
this.given_context.auto_unfold = action.context.auto_unfold || false;
this.given_context.lot_name = action.context.lot_name || false;
return this._super.apply(this, arguments);
},
willStart: function() {
return this.get_html();
return $.when(this._super.apply(this, arguments), this.get_html());
},
set_html: function() {
var self = this;
var def = $.when();
if (!this.report_widget) {
this.report_widget = new ReportWidget(this, this.given_context);
def = this.report_widget.appendTo(this.$el);
def = this.report_widget.appendTo(this.$('.o_content'));
}
return def.then(function () {
self.report_widget.$el.html(self.html);
@@ -78,7 +78,7 @@ var stock_report_generic = AbstractAction.extend(ControlPanelMixin, {
var status = {
cp_content: {$buttons: this.$buttons},
};
return this.update_control_panel(status);
return this.updateControlPanel(status);
},
renderButtons: function() {
var self = this;
+2 -2
View File
@@ -11,7 +11,7 @@ var _t = core._t;
var apps_client = null;
var Apps = AbstractAction.extend({
template: 'EmptyComponent',
contentTemplate: 'EmptyComponent',
remote_action_tag: 'loempia.embed',
failback_action_id: 'base.open_module_tree',
@@ -141,7 +141,7 @@ var Apps = AbstractAction.extend({
self.on('message:unblockUI', self, function() { framework.unblockUI(); });
self.on('message:warn', self, function(m) {self.do_warn(m.title, m.message, m.sticky); });
self.$ifr.appendTo(self.$el).css(css).addClass('apps-client');
self.$ifr.appendTo(self.$('.o_content')).css(css).addClass('apps-client');
def.resolve();
}, function() {
@@ -23,6 +23,8 @@
}
.o_control_panel {
flex: 0 0 auto;
.o_panel {
display: flex;
flex-flow: row wrap;
@@ -5,14 +5,13 @@ var AbstractAction = require('web.AbstractAction');
var config = require('web.config');
var core = require('web.core');
var framework = require('web.framework');
var session = require('web.session');
var Widget = require('web.Widget');
var QWeb = core.qweb;
var _t = core._t;
var Dashboard = AbstractAction.extend({
template: 'DashboardMain',
contentTemplate: 'DashboardMain',
init: function(){
this.all_dashboards = ['apps', 'invitations', 'share', 'translations', 'company'];
@@ -20,7 +19,8 @@ var Dashboard = AbstractAction.extend({
},
start: function(){
return this.load(this.all_dashboards);
var superDef = this._super.apply(this, arguments);
return $.when(superDef, this.load(this.all_dashboards));
},
load: function(dashboards){
@@ -10,7 +10,9 @@ var Dashboard = webSettingsDashboard.Dashboard;
function createDashboard(params) {
var widget = new Widget();
var dashboard = new Dashboard(widget);
// action content not used in tests apparently
var action = {};
var dashboard = new Dashboard(widget, action);
dashboard.all_dashboards = params.dashboards || ['invitations']; // test only user invitations
testUtils.mock.addMockEnvironment(widget, params);
@@ -3,7 +3,6 @@ odoo.define('website.backend.dashboard', function (require) {
var AbstractAction = require('web.AbstractAction');
var ajax = require('web.ajax');
var ControlPanelMixin = require('web.ControlPanelMixin');
var core = require('web.core');
var Dialog = require('web.Dialog');
var field_utils = require('web.field_utils');
@@ -13,8 +12,9 @@ var web_client = require('web.web_client');
var _t = core._t;
var QWeb = core.qweb;
var Dashboard = AbstractAction.extend(ControlPanelMixin, {
template: 'website.WebsiteDashboardMain',
var Dashboard = AbstractAction.extend({
hasControlPanel: true,
contentTemplate: 'website.WebsiteDashboardMain',
cssLibs: [
'/web/static/lib/nvd3/nv.d3.css'
],
@@ -55,7 +55,6 @@ var Dashboard = AbstractAction.extend(ControlPanelMixin, {
return this._super().then(function() {
self.update_cp();
self.render_graphs();
self.$el.parent().addClass('oe_background_grey');
});
},
@@ -320,7 +319,7 @@ var Dashboard = AbstractAction.extend(ControlPanelMixin, {
self.on_website_button($(ev.target).data('website-id'));
});
}
this.update_control_panel({
this.updateControlPanel({
cp_content: {
$searchview: this.$searchview,
$buttons: QWeb.render("website.GoToButtons"),