summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnh Thao Pham (pta) <pta@odoo.com>2020-03-18 07:29:31 +0000
committerYannick Tivisse <yti@odoo.com>2020-04-30 11:40:39 +0000
commit8b6b09fc26dc35f57a68584a668940e1d8bde1ff (patch)
tree45a020f829e1a26b9743800af71219cd74559a5d
parent918a5f2cc022994ee08bead25dd79072bf3fba87 (diff)
[IMP] lunch: add list view for lunch.product.report
- Move code from kanban view that is common with list view in common files - Add action to add selected products to cart - Add/update tests closes odoo/odoo#47556 Taskid: 2160048 Signed-off-by: Yannick Tivisse (yti) <yti@odoo.com>
-rw-r--r--addons/lunch/__manifest__.py2
-rw-r--r--addons/lunch/static/src/js/lunch_controller_common.js253
-rw-r--r--addons/lunch/static/src/js/lunch_kanban_controller.js243
-rw-r--r--addons/lunch/static/src/js/lunch_kanban_renderer.js2
-rw-r--r--addons/lunch/static/src/js/lunch_kanban_view.js4
-rw-r--r--addons/lunch/static/src/js/lunch_list_controller.js18
-rw-r--r--addons/lunch/static/src/js/lunch_list_renderer.js56
-rw-r--r--addons/lunch/static/src/js/lunch_list_view.js39
-rw-r--r--addons/lunch/static/src/js/lunch_mobile.js (renamed from addons/lunch/static/src/js/lunch_kanban_mobile.js)18
-rw-r--r--addons/lunch/static/src/js/lunch_model.js (renamed from addons/lunch/static/src/js/lunch_kanban_model.js)8
-rw-r--r--addons/lunch/static/src/js/lunch_widget.js (renamed from addons/lunch/static/src/js/lunch_kanban_widget.js)9
-rw-r--r--addons/lunch/static/src/scss/lunch_kanban.scss80
-rw-r--r--addons/lunch/static/src/scss/lunch_list.scss8
-rw-r--r--addons/lunch/static/src/scss/lunch_view.scss81
-rw-r--r--addons/lunch/static/src/xml/lunch_templates.xml (renamed from addons/lunch/static/src/xml/lunch_kanban.xml)8
-rw-r--r--addons/lunch/static/tests/lunch_kanban_mobile_tests.js38
-rw-r--r--addons/lunch/static/tests/lunch_kanban_tests.js46
-rw-r--r--addons/lunch/static/tests/lunch_list_tests.js267
-rw-r--r--addons/lunch/static/tests/lunch_test_utils.js6
-rw-r--r--addons/lunch/views/lunch_product_views.xml17
-rw-r--r--addons/lunch/views/lunch_templates.xml12
21 files changed, 822 insertions, 393 deletions
diff --git a/addons/lunch/__manifest__.py b/addons/lunch/__manifest__.py
index 0bf568e7550..ab9729eed45 100644
--- a/addons/lunch/__manifest__.py
+++ b/addons/lunch/__manifest__.py
@@ -38,7 +38,7 @@ If you want to save your employees' time and avoid them to always have coins in
'data/ir_cron_data.xml'
],
'demo': ['data/lunch_demo.xml'],
- 'qweb': ['static/src/xml/lunch_kanban.xml', ],
+ 'qweb': ['static/src/xml/lunch_templates.xml', ],
'installable': True,
'application': True,
'certificate': '001292377792581874189',
diff --git a/addons/lunch/static/src/js/lunch_controller_common.js b/addons/lunch/static/src/js/lunch_controller_common.js
new file mode 100644
index 00000000000..27ce66ec49c
--- /dev/null
+++ b/addons/lunch/static/src/js/lunch_controller_common.js
@@ -0,0 +1,253 @@
+odoo.define('lunch.LunchControllerCommon', function (require) {
+"use strict";
+
+/**
+ * This file defines the common events and functions used by Controllers for the Lunch view.
+ */
+
+var session = require('web.session');
+var core = require('web.core');
+var LunchWidget = require('lunch.LunchWidget');
+var LunchPaymentDialog = require('lunch.LunchPaymentDialog');
+
+var _t = core._t;
+
+var LunchControllerCommon = {
+ custom_events: {
+ add_product: '_onAddProduct',
+ change_location: '_onLocationChanged',
+ change_user: '_onUserChanged',
+ open_wizard: '_onOpenWizard',
+ order_now: '_onOrderNow',
+ remove_product: '_onRemoveProduct',
+ unlink_order: '_onUnlinkOrder',
+ },
+ /**
+ * @override
+ */
+ init: function () {
+ this._super.apply(this, arguments);
+ this.userId = null;
+ this.editMode = false;
+ this.updated = false;
+ this.widgetData = null;
+ this.context = session.user_context;
+ this.archiveEnabled = false;
+ },
+ /**
+ * @override
+ */
+ start: function () {
+ // create a div inside o_content that will be used to wrap the lunch
+ // banner and renderer (this is required to get the desired
+ // layout with the searchPanel to the left)
+ var self = this;
+ this.$('.o_content').append($('<div>').addClass('o_lunch_content'));
+ return this._super.apply(this, arguments).then(function () {
+ self.$('.o_lunch_content').append(self.$('.o_lunch_view'));
+ });
+ },
+
+ //--------------------------------------------------------------------------
+ // Private
+ //--------------------------------------------------------------------------
+
+ _fetchPaymentInfo: function () {
+ return this._rpc({
+ route: '/lunch/payment_message',
+ params: {
+ context: this.context,
+ },
+ });
+ },
+ _fetchWidgetData: function () {
+ var self = this;
+
+ return this._rpc({
+ route: '/lunch/infos',
+ params: {
+ user_id: this.userId,
+ context: this.context,
+ },
+ }).then(function (data) {
+ self.widgetData = data;
+ return self.model._updateLocation(data.user_location[0]);
+ });
+ },
+ /**
+ * Override to add the location domain (coming from the LunchWidget)
+ * to the searchDomain (coming from the controlPanel).
+ *
+ * @override
+ */
+ _getViewDomain: async function () {
+ return this.model.getLocationDomain();
+ },
+ /**
+ * Renders and appends the lunch banner widget.
+ *
+ * @private
+ */
+ _renderLunchWidget: function () {
+ var self = this;
+ var oldWidget = this.widget;
+ this.widgetData.wallet = parseFloat(this.widgetData.wallet).toFixed(2);
+ this.widget = new LunchWidget(this, _.extend(this.widgetData, {edit: this.editMode}));
+ return this.widget.appendTo(document.createDocumentFragment()).then(function () {
+ self.$('.o_lunch_content').prepend(self.widget.$el);
+ if (oldWidget) {
+ oldWidget.destroy();
+ }
+ });
+ },
+ _showPaymentDialog: function (title) {
+ var self = this;
+
+ title = title || '';
+
+ this._fetchPaymentInfo().then(function (data) {
+ var paymentDialog = new LunchPaymentDialog(self, _.extend(data, {title: title}));
+ paymentDialog.open();
+ });
+ },
+ /**
+ * Override to fetch and display the lunch data. Because of the presence of
+ * the searchPanel, also wrap the lunch widget and the renderer into
+ * a div, to get the desired layout.
+ *
+ * @override
+ * @private
+ */
+ _update: function () {
+ var def = this._fetchWidgetData().then(this._renderLunchWidget.bind(this));
+ return Promise.all([def, this._super.apply(this, arguments)]);
+ },
+
+ //--------------------------------------------------------------------------
+ // Handlers
+ //--------------------------------------------------------------------------
+
+ _onAddProduct: function (ev) {
+ var self = this;
+ ev.stopPropagation();
+
+ this._rpc({
+ model: 'lunch.order',
+ method: 'update_quantity',
+ args: [[ev.data.lineId], 1],
+ }).then(function () {
+ self.reload();
+ });
+ },
+ _onLocationChanged: function (ev) {
+ var self = this;
+
+ ev.stopPropagation();
+
+ this._rpc({
+ route: '/lunch/user_location_set',
+ params: {
+ user_id: this.userId,
+ location_id: ev.data.locationId,
+ context: this.context,
+ },
+ }).then(function () {
+ self.model._updateLocation(ev.data.locationId).then(function () {
+ self.reload();
+ });
+ });
+ },
+ _onOpenWizard: function (ev) {
+ var self = this;
+ ev.stopPropagation();
+
+ var ctx = this.userId ? {default_user_id: this.userId} : {};
+
+ var options = {
+ on_close: function () {
+ self.reload();
+ },
+ };
+
+ // YTI TODO Maybe don't always pass the default_product_id
+ var action = {
+ res_model: 'lunch.order',
+ name: _t('Configure Your Order'),
+ type: 'ir.actions.act_window',
+ views: [[false, 'form']],
+ target: 'new',
+ context: _.extend(ctx, {default_product_id: ev.data.productId}),
+ };
+
+ if (ev.data.lineId) {
+ action = _.extend(action, {
+ res_id: ev.data.lineId,
+ context: _.extend(action.context, {
+ active_id: ev.data.lineId,
+ }),
+ });
+ }
+
+ this.do_action(action, options);
+ },
+ _onOrderNow: function (ev) {
+ var self = this;
+ ev.stopPropagation();
+
+ this._rpc({
+ route: '/lunch/pay',
+ params: {
+ user_id: this.userId,
+ context: this.context,
+ },
+ }).then(function (isPaid) {
+ if (isPaid) {
+ // TODO: feedback?
+ self.reload();
+ } else {
+ self._showPaymentDialog(_t("Not enough money in your wallet"));
+ self.reload();
+ }
+ });
+ },
+ _onRemoveProduct: function (ev) {
+ var self = this;
+ ev.stopPropagation();
+
+ this._rpc({
+ model: 'lunch.order',
+ method: 'update_quantity',
+ args: [[ev.data.lineId], -1],
+ }).then(function () {
+ self.reload();
+ });
+ },
+ _onUserChanged: function (ev) {
+ ev.stopPropagation();
+
+ var self = this;
+
+ this.userId = ev.data.userId;
+ this.model._updateUser(ev.data.userId).then(function () {
+ self.reload();
+ });
+ },
+ _onUnlinkOrder: function (ev) {
+ var self = this;
+ ev.stopPropagation();
+
+ this._rpc({
+ route: '/lunch/trash',
+ params: {
+ user_id: this.userId,
+ context: this.context,
+ },
+ }).then(function () {
+ self.reload();
+ });
+ },
+};
+
+return LunchControllerCommon;
+
+});
diff --git a/addons/lunch/static/src/js/lunch_kanban_controller.js b/addons/lunch/static/src/js/lunch_kanban_controller.js
index 6e75d4839b3..dc370a46277 100644
--- a/addons/lunch/static/src/js/lunch_kanban_controller.js
+++ b/addons/lunch/static/src/js/lunch_kanban_controller.js
@@ -6,248 +6,11 @@ odoo.define('lunch.LunchKanbanController', function (require) {
* override of the KanbanController.
*/
-var session = require('web.session');
-var core = require('web.core');
var KanbanController = require('web.KanbanController');
-var LunchKanbanWidget = require('lunch.LunchKanbanWidget');
-var LunchPaymentDialog = require('lunch.LunchPaymentDialog');
+var LunchControllerCommon = require('lunch.LunchControllerCommon');
-var _t = core._t;
-
-var LunchKanbanController = KanbanController.extend({
- custom_events: _.extend({}, KanbanController.prototype.custom_events, {
- add_product: '_onAddProduct',
- change_location: '_onLocationChanged',
- change_user: '_onUserChanged',
- open_wizard: '_onOpenWizard',
- order_now: '_onOrderNow',
- remove_product: '_onRemoveProduct',
- unlink_order: '_onUnlinkOrder',
- }),
-
- /**
- * @override
- */
- init: function () {
- this.userId = null;
- this.editMode = false;
- this.updated = false;
- this.widgetData = null;
- this.context = session.user_context;
- return this._super.apply(this, arguments);
- },
- /**
- * @override
- */
- start: function () {
- // create a div inside o_content that will be used to wrap the lunch
- // banner and kanban renderer (this is required to get the desired
- // layout with the searchPanel to the left)
- var self = this;
- this.$('.o_content').append($('<div>').addClass('o_lunch_kanban'));
- return this._super.apply(this, arguments).then(function () {
- self.$('.o_lunch_kanban').append(self.$('.o_kanban_view'));
- });
- },
-
- //--------------------------------------------------------------------------
- // Private
- //--------------------------------------------------------------------------
-
- _fetchPaymentInfo: function () {
- return this._rpc({
- route: '/lunch/payment_message',
- params: {
- context: this.context,
- },
- });
- },
- _fetchWidgetData: function () {
- var self = this;
-
- return this._rpc({
- route: '/lunch/infos',
- params: {
- user_id: this.userId,
- context: this.context,
- },
- }).then(function (data) {
- self.widgetData = data;
- return self.model._updateLocation(data.user_location[0]);
- });
- },
- /**
- * Override to add the location domain (coming from the lunchKanbanWidget)
- * to the searchDomain (coming from the controlPanel).
- *
- * @override
- */
- _getViewDomain: async function () {
- return this.model.getLocationDomain();
- },
- /**
- * Renders and appends the lunch banner widget.
- *
- * @private
- */
- _renderLunchKanbanWidget: function () {
- var self = this;
- var oldWidget = this.widget;
- this.widgetData.wallet = parseFloat(this.widgetData.wallet).toFixed(2);
- this.widget = new LunchKanbanWidget(this, _.extend(this.widgetData, {edit: this.editMode}));
- return this.widget.appendTo(document.createDocumentFragment()).then(function () {
- self.$('.o_lunch_kanban').prepend(self.widget.$el);
- if (oldWidget) {
- oldWidget.destroy();
- }
- });
- },
- _showPaymentDialog: function (title) {
- var self = this;
-
- title = title || '';
-
- this._fetchPaymentInfo().then(function (data) {
- var paymentDialog = new LunchPaymentDialog(self, _.extend(data, {title: title}));
- paymentDialog.open();
- });
- },
- /**
- * Override to fetch and display the lunch data. Because of the presence of
- * the searchPanel, also wrap the lunch widget and the kanban renderer into
- * a div, to get the desired layout.
- *
- * @override
- * @private
- */
- _update: function () {
- var def = this._fetchWidgetData().then(this._renderLunchKanbanWidget.bind(this));
- return Promise.all([def, this._super.apply(this, arguments)]);
- },
-
- //--------------------------------------------------------------------------
- // Handlers
- //--------------------------------------------------------------------------
-
- _onAddProduct: function (ev) {
- var self = this;
- ev.stopPropagation();
-
- this._rpc({
- model: 'lunch.order',
- method: 'update_quantity',
- args: [[ev.data.lineId], 1],
- }).then(function () {
- self.reload();
- });
- },
- _onLocationChanged: function (ev) {
- var self = this;
-
- ev.stopPropagation();
-
- this._rpc({
- route: '/lunch/user_location_set',
- params: {
- user_id: this.userId,
- location_id: ev.data.locationId,
- context: this.context,
- },
- }).then(function () {
- self.model._updateLocation(ev.data.locationId).then(function () {
- self.reload();
- });
- });
- },
- _onOpenWizard: function (ev) {
- var self = this;
- ev.stopPropagation();
-
- var ctx = this.userId ? {default_user_id: this.userId} : {};
-
- var options = {
- on_close: function () {
- self.reload();
- },
- };
-
- // YTI TODO Maybe don't always pass the default_product_id
- var action = {
- res_model: 'lunch.order',
- name: _t('Configure Your Order'),
- type: 'ir.actions.act_window',
- views: [[false, 'form']],
- target: 'new',
- context: _.extend(ctx, {default_product_id: ev.data.productId}),
- };
-
- if (ev.data.lineId) {
- action = _.extend(action, {
- res_id: ev.data.lineId,
- context: _.extend(action.context, {
- active_id: ev.data.lineId,
- }),
- });
- }
-
- this.do_action(action, options);
- },
- _onOrderNow: function (ev) {
- var self = this;
- ev.stopPropagation();
-
- this._rpc({
- route: '/lunch/pay',
- params: {
- user_id: this.userId,
- context: this.context,
- },
- }).then(function (isPaid) {
- if (isPaid) {
- // TODO: feedback?
- self.reload();
- } else {
- self._showPaymentDialog(_t("Not enough money in your wallet"));
- self.reload();
- }
- });
- },
- _onRemoveProduct: function (ev) {
- var self = this;
- ev.stopPropagation();
-
- this._rpc({
- model: 'lunch.order',
- method: 'update_quantity',
- args: [[ev.data.lineId], -1],
- }).then(function () {
- self.reload();
- });
- },
- _onUserChanged: function (ev) {
- ev.stopPropagation();
-
- var self = this;
-
- this.userId = ev.data.userId;
- this.model._updateUser(ev.data.userId).then(function () {
- self.reload();
- });
- },
- _onUnlinkOrder: function (ev) {
- var self = this;
- ev.stopPropagation();
-
- this._rpc({
- route: '/lunch/trash',
- params: {
- user_id: this.userId,
- context: this.context,
- },
- }).then(function () {
- self.reload();
- });
- },
+var LunchKanbanController = KanbanController.extend(LunchControllerCommon , {
+ custom_events: _.extend({}, KanbanController.prototype.custom_events, LunchControllerCommon.custom_events),
});
return LunchKanbanController;
diff --git a/addons/lunch/static/src/js/lunch_kanban_renderer.js b/addons/lunch/static/src/js/lunch_kanban_renderer.js
index bffe639a655..bea87992928 100644
--- a/addons/lunch/static/src/js/lunch_kanban_renderer.js
+++ b/addons/lunch/static/src/js/lunch_kanban_renderer.js
@@ -19,7 +19,7 @@ var LunchKanbanRenderer = KanbanRenderer.extend({
* @override
*/
start: function () {
- this.$el.addClass('o_lunch_kanban_view position-relative align-content-start flex-grow-1 flex-shrink-1');
+ this.$el.addClass('o_lunch_view o_lunch_kanban_view position-relative align-content-start flex-grow-1 flex-shrink-1');
return this._super.apply(this, arguments);
},
});
diff --git a/addons/lunch/static/src/js/lunch_kanban_view.js b/addons/lunch/static/src/js/lunch_kanban_view.js
index 0b54497fc55..75fda433b2c 100644
--- a/addons/lunch/static/src/js/lunch_kanban_view.js
+++ b/addons/lunch/static/src/js/lunch_kanban_view.js
@@ -2,7 +2,7 @@ odoo.define('lunch.LunchKanbanView', function (require) {
"use strict";
var LunchKanbanController = require('lunch.LunchKanbanController');
-var LunchKanbanModel = require('lunch.LunchKanbanModel');
+var LunchModel = require('lunch.LunchModel');
var LunchKanbanRenderer = require('lunch.LunchKanbanRenderer');
var core = require('web.core');
@@ -14,7 +14,7 @@ var _lt = core._lt;
var LunchKanbanView = KanbanView.extend({
config: _.extend({}, KanbanView.prototype.config, {
Controller: LunchKanbanController,
- Model: LunchKanbanModel,
+ Model: LunchModel,
Renderer: LunchKanbanRenderer,
}),
display_name: _lt('Lunch Kanban'),
diff --git a/addons/lunch/static/src/js/lunch_list_controller.js b/addons/lunch/static/src/js/lunch_list_controller.js
new file mode 100644
index 00000000000..bdfbab6b107
--- /dev/null
+++ b/addons/lunch/static/src/js/lunch_list_controller.js
@@ -0,0 +1,18 @@
+odoo.define('lunch.LunchListController', function (require) {
+"use strict";
+
+/**
+ * This file defines the Controller for the Lunch List view, which is an
+ * override of the ListController.
+ */
+
+var ListController = require('web.ListController');
+var LunchControllerCommon = require('lunch.LunchControllerCommon');
+
+var LunchListController = ListController.extend(LunchControllerCommon, {
+ custom_events: _.extend({}, ListController.prototype.custom_events, LunchControllerCommon.custom_events),
+});
+
+return LunchListController;
+
+});
diff --git a/addons/lunch/static/src/js/lunch_list_renderer.js b/addons/lunch/static/src/js/lunch_list_renderer.js
new file mode 100644
index 00000000000..0ab0b5c9c13
--- /dev/null
+++ b/addons/lunch/static/src/js/lunch_list_renderer.js
@@ -0,0 +1,56 @@
+odoo.define('lunch.LunchListRenderer', function (require) {
+"use strict";
+
+/**
+ * This file defines the Renderer for the Lunch List view, which is an
+ * override of the ListRenderer.
+ */
+
+var ListRenderer = require('web.ListRenderer');
+
+var LunchListRenderer = ListRenderer.extend({
+ events: _.extend({}, ListRenderer.prototype.events, {
+ 'click .o_data_row': '_onClickListRow',
+ }),
+
+ /**
+ * @override
+ */
+ start: function () {
+ this.$el.addClass('o_lunch_view o_lunch_list_view');
+ return this._super.apply(this, arguments);
+ },
+ /**
+ * Override to add id of product_id in dataset.
+ *
+ * @override
+ */
+ _renderRow: function (record) {
+ var tr = this._super.apply(this, arguments);
+ tr.attr('data-product-id', record.data.id);
+ return tr;
+ },
+
+ //--------------------------------------------------------------------------
+ // Handlers
+ //--------------------------------------------------------------------------
+
+ /**
+ * Open the add product wizard
+ *
+ * @private
+ * @param {MouseEvent} ev Click event
+ */
+ _onClickListRow: function (ev) {
+ ev.preventDefault();
+ var productId = ev.currentTarget.dataset && ev.currentTarget.dataset.productId ? parseInt(ev.currentTarget.dataset.productId) : null;
+
+ if (productId) {
+ this.trigger_up('open_wizard', {productId: productId});
+ }
+ },
+});
+
+return LunchListRenderer;
+
+});
diff --git a/addons/lunch/static/src/js/lunch_list_view.js b/addons/lunch/static/src/js/lunch_list_view.js
new file mode 100644
index 00000000000..b49d4386ffb
--- /dev/null
+++ b/addons/lunch/static/src/js/lunch_list_view.js
@@ -0,0 +1,39 @@
+odoo.define('lunch.LunchListView', function (require) {
+"use strict";
+
+var LunchListController = require('lunch.LunchListController');
+var LunchModel = require('lunch.LunchModel');
+var LunchListRenderer = require('lunch.LunchListRenderer');
+
+var core = require('web.core');
+var ListView = require('web.ListView');
+var view_registry = require('web.view_registry');
+
+var _lt = core._lt;
+
+var LunchListView = ListView.extend({
+ config: _.extend({}, ListView.prototype.config, {
+ Controller: LunchListController,
+ Model: LunchModel,
+ Renderer: LunchListRenderer,
+ }),
+ display_name: _lt('Lunch List'),
+
+ //--------------------------------------------------------------------------
+ // Private
+ //--------------------------------------------------------------------------
+
+ /**
+ * @override
+ */
+ _getViewDomain: function (parent) {
+ const model = this.getModel(parent);
+ return model.getLocationDomain();
+ },
+});
+
+view_registry.add('lunch_list', LunchListView);
+
+return LunchListView;
+
+});
diff --git a/addons/lunch/static/src/js/lunch_kanban_mobile.js b/addons/lunch/static/src/js/lunch_mobile.js
index eddd22ac351..f6ad1e92081 100644
--- a/addons/lunch/static/src/js/lunch_kanban_mobile.js
+++ b/addons/lunch/static/src/js/lunch_mobile.js
@@ -1,16 +1,17 @@
-odoo.define('lunch.LunchKanbanMobile', function (require) {
+odoo.define('lunch.LunchMobile', function (require) {
"use strict";
var config = require('web.config');
-var LunchKanbanWidget = require('lunch.LunchKanbanWidget');
+var LunchWidget = require('lunch.LunchWidget');
var LunchKanbanController = require('lunch.LunchKanbanController');
+var LunchListController = require('lunch.LunchListController');
if (!config.device.isMobile) {
return;
}
-LunchKanbanWidget.include({
- template: "LunchKanbanWidgetMobile",
+LunchWidget.include({
+ template: "LunchWidgetMobile",
/**
* Override to set the toggle state allowing initially open it.
@@ -23,7 +24,7 @@ LunchKanbanWidget.include({
},
});
-LunchKanbanController.include({
+var mobileFunctions = {
/**
* @override
*/
@@ -42,7 +43,7 @@ LunchKanbanController.include({
* @override
* @private
*/
- _renderLunchKanbanWidget: function () {
+ _renderLunchWidget: function () {
this.widgetData.keepOpen = this.openWidget;
this.openWidget = false;
return this._super.apply(this, arguments);
@@ -69,6 +70,9 @@ LunchKanbanController.include({
this.openWidget = true;
this._super.apply(this, arguments);
},
-});
+};
+
+LunchKanbanController.include(mobileFunctions);
+LunchListController.include(mobileFunctions);
});
diff --git a/addons/lunch/static/src/js/lunch_kanban_model.js b/addons/lunch/static/src/js/lunch_model.js
index 07acbcd8b69..cd99b6ff834 100644
--- a/addons/lunch/static/src/js/lunch_kanban_model.js
+++ b/addons/lunch/static/src/js/lunch_model.js
@@ -1,4 +1,4 @@
-odoo.define('lunch.LunchKanbanModel', function (require) {
+odoo.define('lunch.LunchModel', function (require) {
"use strict";
/**
@@ -7,9 +7,9 @@ odoo.define('lunch.LunchKanbanModel', function (require) {
*/
var session = require('web.session');
-var KanbanModel = require('web.KanbanModel');
+var BasicModel = require('web.BasicModel');
-var LunchKanbanModel = KanbanModel.extend({
+var LunchModel = BasicModel.extend({
init: function () {
this.locationId = false;
this.userId = false;
@@ -125,6 +125,6 @@ var LunchKanbanModel = KanbanModel.extend({
}
});
-return LunchKanbanModel;
+return LunchModel;
});
diff --git a/addons/lunch/static/src/js/lunch_kanban_widget.js b/addons/lunch/static/src/js/lunch_widget.js
index 2080590acd1..ca0c497ceff 100644
--- a/addons/lunch/static/src/js/lunch_kanban_widget.js
+++ b/addons/lunch/static/src/js/lunch_widget.js
@@ -1,4 +1,4 @@
-odoo.define('lunch.LunchKanbanWidget', function (require) {
+odoo.define('lunch.LunchWidget', function (require) {
"use strict";
var core = require('web.core');
@@ -17,8 +17,8 @@ var LunchMany2One = FieldMany2One.extend({
}
});
-var LunchKanbanWidget = Widget.extend({
- template: 'LunchKanbanWidget',
+var LunchWidget = Widget.extend({
+ template: 'LunchWidget',
custom_events: {
field_changed: '_onFieldChanged',
},
@@ -125,7 +125,6 @@ var LunchKanbanWidget = Widget.extend({
_onAddProduct: function (ev) {
ev.preventDefault();
ev.stopPropagation();
-
this.trigger_up('add_product', {lineId: $(ev.currentTarget).data('id')});
},
_onOrderNow: function (ev) {
@@ -164,6 +163,6 @@ var LunchKanbanWidget = Widget.extend({
},
});
-return LunchKanbanWidget;
+return LunchWidget;
});
diff --git a/addons/lunch/static/src/scss/lunch_kanban.scss b/addons/lunch/static/src/scss/lunch_kanban.scss
index 7e660ae4b43..b4ffa97c8fe 100644
--- a/addons/lunch/static/src/scss/lunch_kanban.scss
+++ b/addons/lunch/static/src/scss/lunch_kanban.scss
@@ -1,86 +1,8 @@
-.o_lunch_kanban {
- display: flex;
- flex-direction: column; // display lunch widget above kanban renderer
- flex: 1 1 100%; // displayed to the right of the searchPanel
- min-width: 0; // prevent grouped kanban from horizontally overflowing
- height: 100%;
- .o_lunch_kanban_banner {
- flex: 0 0 auto;
- border-bottom: 1px solid #CED4DA;
- background-color: white;
- }
+.o_lunch_content {
.o_kanban_view {
flex: 1 1 100%;
&.o_kanban_grouped {
min-height: auto; // override min-height: 100%
}
}
-
- .o_lunch_purple {
- color: $o-brand-odoo;
- }
-
- .o_flex_basis_0 {
- flex-basis: 0;
- }
-
- .o_lunch_widget {
- min-height: 90px;
- max-height: 33vh;
- overflow-y: auto;
-
- .o_lunch_widget_info.card {
- &, .card-title, .card-body {
- color: $o-main-text-color;
- background-color: inherit !important;
- }
-
- .card-title {
- font-weight: bold;
- margin-bottom: 0;
- }
-
- .card-body {
- padding: 0.5rem 1rem;
- }
-
- .btn-link {
- padding: 0;
- &.o_lunch_open_wizard {
- color: $o-main-text-color;
- font-weight: normal;
- }
- }
- }
- }
-}
-
-.o_lunch_image {
- img {
- max-width: 128px;
- max-height: 128px !important;
- }
-}
-
-@include media-breakpoint-down(sm) {
- .o_lunch_kanban {
- details summary {
- // Hide the caret. For details see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/summary
- list-style-type: none;
- &::-webkit-details-marker {
- display: none
- }
- }
- .o_lunch_widget {
- max-height: 100%
- }
- }
-}
-
-.o_lunch_wizard {
- .col-10 {
- .o_form_label {
- font-weight: normal !important;
- }
- }
}
diff --git a/addons/lunch/static/src/scss/lunch_list.scss b/addons/lunch/static/src/scss/lunch_list.scss
index 2babc5e388e..b0afa58aeaf 100644
--- a/addons/lunch/static/src/scss/lunch_list.scss
+++ b/addons/lunch/static/src/scss/lunch_list.scss
@@ -1,5 +1,11 @@
-.o_lunch_list {
+.o_lunch_content {
.o_list_button {
width: 1px;
}
+
+ .o_lunch_list_view {
+ td:last-child {
+ padding-right: 16px;
+ }
+ }
} \ No newline at end of file
diff --git a/addons/lunch/static/src/scss/lunch_view.scss b/addons/lunch/static/src/scss/lunch_view.scss
new file mode 100644
index 00000000000..6b7056f96f7
--- /dev/null
+++ b/addons/lunch/static/src/scss/lunch_view.scss
@@ -0,0 +1,81 @@
+.o_lunch_content {
+ display: flex;
+ flex-direction: column; // display lunch widget above kanban renderer
+ flex: 1 1 100%; // displayed to the right of the searchPanel
+ min-width: 0; // prevent grouped kanban from horizontally overflowing
+ max-width: 100%;
+ height: 100%;
+ .o_lunch_banner {
+ flex: 0 0 auto;
+ border-bottom: 1px solid #CED4DA;
+ background-color: white;
+ }
+
+ .o_lunch_purple {
+ color: $o-brand-odoo;
+ }
+
+ .o_flex_basis_0 {
+ flex-basis: 0;
+ }
+
+ .o_lunch_widget {
+ min-height: 90px;
+ max-height: 33vh;
+ overflow-y: auto;
+
+ .o_lunch_widget_info.card {
+ &, .card-title, .card-body {
+ color: $o-main-text-color;
+ background-color: inherit !important;
+ }
+
+ .card-title {
+ font-weight: bold;
+ margin-bottom: 0;
+ }
+
+ .card-body {
+ padding: 0.5rem 1rem;
+ }
+
+ .btn-link {
+ padding: 0;
+ &.o_lunch_open_wizard {
+ color: $o-main-text-color;
+ font-weight: normal;
+ }
+ }
+ }
+ }
+}
+
+.o_lunch_image {
+ img {
+ max-width: 128px;
+ max-height: 128px !important;
+ }
+}
+
+@include media-breakpoint-down(sm) {
+ .o_lunch_content {
+ details summary {
+ // Hide the caret. For details see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/summary
+ list-style-type: none;
+ &::-webkit-details-marker {
+ display: none
+ }
+ }
+ .o_lunch_widget {
+ max-height: 100%
+ }
+ }
+}
+
+.o_lunch_wizard {
+ .col-10 {
+ .o_form_label {
+ font-weight: normal !important;
+ }
+ }
+}
diff --git a/addons/lunch/static/src/xml/lunch_kanban.xml b/addons/lunch/static/src/xml/lunch_templates.xml
index aab22eaf4ae..6cc7872189f 100644
--- a/addons/lunch/static/src/xml/lunch_kanban.xml
+++ b/addons/lunch/static/src/xml/lunch_templates.xml
@@ -1,12 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates>
- <span t-name="LunchKanbanWidget">
+ <span t-name="LunchWidget">
<t t-foreach="widget.alerts" t-as="alert">
<div class="alert alert-warning mb-0" role="alert">
<t t-raw="alert.message"/> <!-- alert.message is coming from a fields.Html so it should be safe -->
</div>
</t>
- <div class="o_lunch_kanban_banner container-fluid">
+ <div class="o_lunch_banner container-fluid">
<div class="o_lunch_widget row py-3 py-md-0">
<div class="o_lunch_widget_info col-12 col-md-4 card border-0">
<div class="card-body row no-gutters align-items-center">
@@ -116,7 +116,7 @@
<span t-esc="widget.message"/>
</div>
- <t t-name="LunchKanbanWidgetMobile">
+ <t t-name="LunchWidgetMobile">
<details class="fixed-bottom" t-attf-open="#{widget.keepOpen}">
<summary class="o_lunch_toggle_cart btn btn-primary w-100">
<i class="fa fa-fw fa-shopping-cart"/>
@@ -126,7 +126,7 @@
<t t-set="currency" t-value="widget.currency"/>
</t>)
</summary>
- <t t-call="LunchKanbanWidget"/>
+ <t t-call="LunchWidget"/>
</details>
</t>
</templates>
diff --git a/addons/lunch/static/tests/lunch_kanban_mobile_tests.js b/addons/lunch/static/tests/lunch_kanban_mobile_tests.js
index f17bef77f8c..1f2e61ff423 100644
--- a/addons/lunch/static/tests/lunch_kanban_mobile_tests.js
+++ b/addons/lunch/static/tests/lunch_kanban_mobile_tests.js
@@ -4,7 +4,7 @@ odoo.define('lunch.lunchKanbanMobileTests', function (require) {
const LunchKanbanView = require('lunch.LunchKanbanView');
const testUtils = require('web.test_utils');
-const {createLunchKanbanView, mockLunchRPC} = require('lunch.test_utils');
+const {createLunchView, mockLunchRPC} = require('lunch.test_utils');
QUnit.module('Views');
@@ -61,7 +61,7 @@ QUnit.module('LunchKanbanView Mobile', {
QUnit.test('basic rendering', async function (assert) {
assert.expect(7);
- const kanban = await createLunchKanbanView({
+ const kanban = await createLunchView({
View: LunchKanbanView,
model: 'product',
data: this.data,
@@ -84,27 +84,27 @@ QUnit.module('LunchKanbanView Mobile', {
"should have 1 records in the renderer");
// check view layout
- assert.containsOnce(kanban, '.o_content > .o_lunch_kanban',
+ assert.containsOnce(kanban, '.o_content > .o_lunch_content',
"should have a 'kanban lunch wrapper' column");
- assert.containsOnce(kanban, '.o_lunch_kanban > .o_kanban_view',
+ assert.containsOnce(kanban, '.o_lunch_content > .o_kanban_view',
"should have a 'classical kanban view' column");
assert.hasClass(kanban.$('.o_kanban_view'), 'o_lunch_kanban_view',
"should have classname 'o_lunch_kanban_view'");
- assert.containsOnce($('.o_lunch_kanban'), '> details',
+ assert.containsOnce($('.o_lunch_content'), '> details',
"should have a 'lunch kanban' details/summary discolure panel");
- assert.hasClass($('.o_lunch_kanban > details'), 'fixed-bottom',
+ assert.hasClass($('.o_lunch_content > details'), 'fixed-bottom',
"should have classname 'fixed-bottom'");
- assert.isNotVisible($('.o_lunch_kanban > details .o_lunch_kanban_banner'),
+ assert.isNotVisible($('.o_lunch_content > details .o_lunch_banner'),
"shouldn't have a visible 'lunch kanban' banner");
kanban.destroy();
});
- QUnit.module('LunchKanbanWidget', function () {
+ QUnit.module('LunchWidget', function () {
QUnit.test('toggle', async function (assert) {
assert.expect(6);
- const kanban = await createLunchKanbanView({
+ const kanban = await createLunchView({
View: LunchKanbanView,
model: 'product',
data: this.data,
@@ -125,8 +125,8 @@ QUnit.module('LunchKanbanView Mobile', {
}),
});
- const $details = $('.o_lunch_kanban > details');
- assert.isNotVisible($details.find('.o_lunch_kanban_banner'),
+ const $details = $('.o_lunch_content > details');
+ assert.isNotVisible($details.find('.o_lunch_banner'),
"shouldn't have a visible 'lunch kanban' banner");
assert.isVisible($details.find('> summary'),
"should hava a visible cart toggle button");
@@ -136,11 +136,11 @@ QUnit.module('LunchKanbanView Mobile', {
"should have '3.00' in the button text");
await testUtils.dom.click($details.find('> summary'));
- assert.isVisible($details.find('.o_lunch_kanban_banner'),
+ assert.isVisible($details.find('.o_lunch_banner'),
"should have a visible 'lunch kanban' banner");
await testUtils.dom.click($details.find('> summary'));
- assert.isNotVisible($details.find('.o_lunch_kanban_banner'),
+ assert.isNotVisible($details.find('.o_lunch_banner'),
"shouldn't have a visible 'lunch kanban' banner");
kanban.destroy();
@@ -149,7 +149,7 @@ QUnit.module('LunchKanbanView Mobile', {
QUnit.test('keep open when adding quantities', async function (assert) {
assert.expect(6);
- const kanban = await createLunchKanbanView({
+ const kanban = await createLunchView({
View: LunchKanbanView,
model: 'product',
data: this.data,
@@ -177,14 +177,14 @@ QUnit.module('LunchKanbanView Mobile', {
}),
});
- const $details = $('.o_lunch_kanban > details');
- assert.isNotVisible($details.find('.o_lunch_kanban_banner'),
+ const $details = $('.o_lunch_content > details');
+ assert.isNotVisible($details.find('.o_lunch_banner'),
"shouldn't have a visible 'lunch kanban' banner");
assert.isVisible($details.find('> summary'),
"should hava a visible cart toggle button");
await testUtils.dom.click($details.find('> summary'));
- assert.isVisible($details.find('.o_lunch_kanban_banner'),
+ assert.isVisible($details.find('.o_lunch_banner'),
"should have a visible 'lunch kanban' banner");
const $widgetSecondColumn = kanban.$('.o_lunch_widget .o_lunch_widget_info:eq(1)');
@@ -195,13 +195,13 @@ QUnit.module('LunchKanbanView Mobile', {
let $firstLine = $widgetSecondColumn.find('.o_lunch_widget_lines > li:first');
await testUtils.dom.click($firstLine.find('button.o_add_product'));
- assert.isVisible($('.o_lunch_kanban > details .o_lunch_kanban_banner'),
+ assert.isVisible($('.o_lunch_content > details .o_lunch_banner'),
"add quantity should keep 'lunch kanban' banner open");
$firstLine = kanban.$('.o_lunch_widget .o_lunch_widget_info:eq(1) .o_lunch_widget_lines > li:first');
await testUtils.dom.click($firstLine.find('button.o_remove_product'));
- assert.isVisible($('.o_lunch_kanban > details .o_lunch_kanban_banner'),
+ assert.isVisible($('.o_lunch_content > details .o_lunch_banner'),
"remove quantity should keep 'lunch kanban' banner open");
kanban.destroy();
diff --git a/addons/lunch/static/tests/lunch_kanban_tests.js b/addons/lunch/static/tests/lunch_kanban_tests.js
index bb2b0beb3f7..d4deade79bb 100644
--- a/addons/lunch/static/tests/lunch_kanban_tests.js
+++ b/addons/lunch/static/tests/lunch_kanban_tests.js
@@ -4,7 +4,7 @@ odoo.define('lunch.lunchKanbanTests', function (require) {
const LunchKanbanView = require('lunch.LunchKanbanView');
const testUtils = require('web.test_utils');
-const {createLunchKanbanView, mockLunchRPC} = require('lunch.test_utils');
+const {createLunchView, mockLunchRPC} = require('lunch.test_utils');
QUnit.module('Views');
@@ -89,7 +89,7 @@ QUnit.module('LunchKanbanView', {
QUnit.test('basic rendering', async function (assert) {
assert.expect(7);
- const kanban = await createLunchKanbanView({
+ const kanban = await createLunchView({
View: LunchKanbanView,
model: 'product',
data: this.data,
@@ -116,14 +116,14 @@ QUnit.module('LunchKanbanView', {
"should have 2 columns");
assert.containsOnce(kanban, '.o_content > div.o_search_panel',
"should have a 'lunch filters' column");
- assert.containsOnce(kanban, '.o_content > .o_lunch_kanban',
- "should have a 'kanban lunch wrapper' column");
- assert.containsOnce(kanban, '.o_lunch_kanban > .o_kanban_view',
+ assert.containsOnce(kanban, '.o_content > .o_lunch_content',
+ "should have a 'lunch wrapper' column");
+ assert.containsOnce(kanban, '.o_lunch_content > .o_kanban_view',
"should have a 'classical kanban view' column");
assert.hasClass(kanban.$('.o_kanban_view'), 'o_lunch_kanban_view',
"should have classname 'o_lunch_kanban_view'");
- assert.containsOnce(kanban, '.o_lunch_kanban > span > .o_lunch_kanban_banner',
- "should have a 'lunch kanban' banner");
+ assert.containsOnce(kanban, '.o_lunch_content > span > .o_lunch_banner',
+ "should have a 'lunch' banner");
kanban.destroy();
});
@@ -133,7 +133,7 @@ QUnit.module('LunchKanbanView', {
const self = this;
let infosProm = Promise.resolve();
- const kanban = await createLunchKanbanView({
+ const kanban = await createLunchView({
View: LunchKanbanView,
model: 'product',
data: this.data,
@@ -175,12 +175,12 @@ QUnit.module('LunchKanbanView', {
kanban.destroy();
});
- QUnit.module('LunchKanbanWidget', function () {
+ QUnit.module('LunchWidget', function () {
QUnit.test('empty cart', async function (assert) {
assert.expect(3);
- const kanban = await createLunchKanbanView({
+ const kanban = await createLunchView({
View: LunchKanbanView,
model: 'product',
data: this.data,
@@ -217,7 +217,7 @@ QUnit.module('LunchKanbanView', {
let locationId = this.data['lunch.location'].records[0].id;
const regularInfos = _.extend({}, this.regularInfos);
- const kanban = await createLunchKanbanView({
+ const kanban = await createLunchView({
View: LunchKanbanView,
model: 'product',
data: this.data,
@@ -285,7 +285,7 @@ QUnit.module('LunchKanbanView', {
assert.expect(10);
const regularInfos = _.extend({}, this.regularInfos);
- const kanban = await createLunchKanbanView({
+ const kanban = await createLunchView({
View: LunchKanbanView,
model: 'product',
data: this.data,
@@ -333,7 +333,7 @@ QUnit.module('LunchKanbanView', {
QUnit.test('non-empty cart', async function (assert) {
assert.expect(17);
- const kanban = await createLunchKanbanView({
+ const kanban = await createLunchView({
View: LunchKanbanView,
model: 'product',
data: this.data,
@@ -415,7 +415,7 @@ QUnit.module('LunchKanbanView', {
QUnit.test('ordered cart', async function (assert) {
assert.expect(15);
- const kanban = await createLunchKanbanView({
+ const kanban = await createLunchView({
View: LunchKanbanView,
model: 'product',
data: this.data,
@@ -491,7 +491,7 @@ QUnit.module('LunchKanbanView', {
QUnit.test('confirmed cart', async function (assert) {
assert.expect(15);
- const kanban = await createLunchKanbanView({
+ const kanban = await createLunchView({
View: LunchKanbanView,
model: 'product',
data: this.data,
@@ -567,7 +567,7 @@ QUnit.module('LunchKanbanView', {
QUnit.test('regular user', async function (assert) {
assert.expect(11);
- const kanban = await createLunchKanbanView({
+ const kanban = await createLunchView({
View: LunchKanbanView,
model: 'product',
data: this.data,
@@ -626,7 +626,7 @@ QUnit.module('LunchKanbanView', {
QUnit.test('manager user', async function (assert) {
assert.expect(12);
- const kanban = await createLunchKanbanView({
+ const kanban = await createLunchView({
View: LunchKanbanView,
model: 'product',
data: this.data,
@@ -690,7 +690,7 @@ QUnit.module('LunchKanbanView', {
QUnit.test('add a product', async function (assert) {
assert.expect(1);
- const kanban = await createLunchKanbanView({
+ const kanban = await createLunchView({
View: LunchKanbanView,
model: 'product',
data: this.data,
@@ -732,7 +732,7 @@ QUnit.module('LunchKanbanView', {
QUnit.test('add product quantity', async function (assert) {
assert.expect(3);
- const kanban = await createLunchKanbanView({
+ const kanban = await createLunchView({
View: LunchKanbanView,
model: 'product',
data: Object.assign({}, this.data, {
@@ -784,7 +784,7 @@ QUnit.module('LunchKanbanView', {
QUnit.test('remove product quantity', async function (assert) {
assert.expect(3);
- const kanban = await createLunchKanbanView({
+ const kanban = await createLunchView({
View: LunchKanbanView,
model: 'product',
data: Object.assign({}, this.data, {
@@ -837,7 +837,7 @@ QUnit.module('LunchKanbanView', {
assert.expect(1);
const self = this;
- const kanban = await createLunchKanbanView({
+ const kanban = await createLunchView({
View: LunchKanbanView,
model: 'product',
data: this.data,
@@ -883,7 +883,7 @@ QUnit.module('LunchKanbanView', {
assert.expect(1);
const self = this;
- const kanban = await createLunchKanbanView({
+ const kanban = await createLunchView({
View: LunchKanbanView,
model: 'product',
data: this.data,
@@ -929,7 +929,7 @@ QUnit.module('LunchKanbanView', {
assert.expect(5);
const self = this;
- const kanban = await createLunchKanbanView({
+ const kanban = await createLunchView({
View: LunchKanbanView,
model: 'product',
data: this.data,
diff --git a/addons/lunch/static/tests/lunch_list_tests.js b/addons/lunch/static/tests/lunch_list_tests.js
new file mode 100644
index 00000000000..cca644a52a9
--- /dev/null
+++ b/addons/lunch/static/tests/lunch_list_tests.js
@@ -0,0 +1,267 @@
+odoo.define('lunch.lunchListTests', function (require) {
+"use strict";
+
+const LunchListView = require('lunch.LunchListView');
+
+const testUtils = require('web.test_utils');
+const {createLunchView, mockLunchRPC} = require('lunch.test_utils');
+
+QUnit.module('Views');
+
+QUnit.module('LunchListView', {
+ beforeEach() {
+ const PORTAL_GROUP_ID = 1234;
+
+ this.data = {
+ 'product': {
+ fields: {
+ is_available_at: {string: 'Product Availability', type: 'many2one', relation: 'lunch.location'},
+ category_id: {string: 'Product Category', type: 'many2one', relation: 'lunch.product.category'},
+ supplier_id: {string: 'Vendor', type: 'many2one', relation: 'lunch.supplier'},
+ },
+ records: [
+ {id: 1, name: 'Tuna sandwich', is_available_at: 1},
+ ],
+ },
+ 'lunch.order': {
+ fields: {},
+ update_quantity() {
+ return Promise.resolve();
+ },
+ },
+ 'lunch.product.category': {
+ fields: {},
+ records: [],
+ },
+ 'lunch.supplier': {
+ fields: {},
+ records: [],
+ },
+ 'ir.model.data': {
+ fields: {},
+ xmlid_to_res_id() {
+ return Promise.resolve(PORTAL_GROUP_ID);
+ },
+ },
+ 'lunch.location': {
+ fields: {
+ name: {string: 'Name', type: 'char'},
+ },
+ records: [
+ {id: 1, name: "Office 1"},
+ {id: 2, name: "Office 2"},
+ ],
+ },
+ 'res.users': {
+ fields: {
+ name: {string: 'Name', type: 'char'},
+ groups_id: {string: 'Groups', type: 'many2many'},
+ },
+ records: [
+ {id: 1, name: "Mitchell Admin", groups_id: []},
+ {id: 2, name: "Marc Demo", groups_id: []},
+ {id: 3, name: "Jean-Luc Portal", groups_id: [PORTAL_GROUP_ID]},
+ ],
+ },
+ };
+ this.regularInfos = {
+ username: "Marc Demo",
+ wallet: 36.5,
+ is_manager: false,
+ currency: {
+ symbol: "\u20ac",
+ position: "after"
+ },
+ user_location: [2, "Office 2"],
+ };
+ },
+}, function () {
+ QUnit.test('basic rendering', async function (assert) {
+ assert.expect(6);
+
+ const list = await createLunchView({
+ View: LunchListView,
+ model: 'product',
+ data: this.data,
+ arch: `
+ <tree>
+ <field name="name"/>
+ </tree>
+ `,
+ mockRPC: mockLunchRPC({
+ infos: this.regularInfos,
+ userLocation: this.data['lunch.location'].records[0].id,
+ }),
+ });
+
+ // check view layout
+ assert.containsN(list, '.o_content > div', 2,
+ "should have 2 columns");
+ assert.containsOnce(list, '.o_content > div.o_search_panel',
+ "should have a 'lunch filters' column");
+ assert.containsOnce(list, '.o_content > .o_lunch_content',
+ "should have a 'lunch wrapper' column");
+ assert.containsOnce(list, '.o_lunch_content > .o_list_view',
+ "should have a 'classical list view' column");
+ assert.hasClass(list.$('.o_list_view'), 'o_lunch_list_view',
+ "should have classname 'o_lunch_list_view'");
+ assert.containsOnce(list, '.o_lunch_content > span > .o_lunch_banner',
+ "should have a 'lunch' banner");
+
+ list.destroy();
+ });
+
+ QUnit.module('LunchWidget', function () {
+
+ QUnit.test('search panel domain location', async function (assert) {
+ assert.expect(20);
+ let expectedLocation = 1;
+ let locationId = this.data['lunch.location'].records[0].id;
+ const regularInfos = _.extend({}, this.regularInfos);
+
+ const list = await createLunchView({
+ View: LunchListView,
+ model: 'product',
+ data: this.data,
+ arch: `
+ <tree>
+ <field name="name"/>
+ </tree>
+ `,
+ mockRPC: function (route, args) {
+ assert.step(route);
+
+ if (route.startsWith('/lunch')) {
+ if (route === '/lunch/user_location_set') {
+ locationId = args.location_id;
+ return Promise.resolve(true);
+ }
+ return mockLunchRPC({
+ infos: regularInfos,
+ userLocation: locationId,
+ }).apply(this, arguments);
+ }
+ if (args.method === 'search_panel_select_multi_range') {
+ assert.deepEqual(args.kwargs.search_domain, [["is_available_at", "in", [expectedLocation]]],
+ 'The initial domain of the search panel must contain the user location');
+ }
+ if (route === '/web/dataset/search_read') {
+ assert.deepEqual(args.domain, [["is_available_at", "in", [expectedLocation]]],
+ 'The domain for fetching actual data should be correct');
+ }
+ return this._super.apply(this, arguments);
+ },
+ });
+
+ expectedLocation = 2;
+ await testUtils.fields.many2one.clickOpenDropdown('locations');
+ await testUtils.fields.many2one.clickItem('locations', "Office 2");
+
+ assert.verifySteps([
+ // Initial state
+ '/lunch/user_location_get',
+ '/web/dataset/call_kw/product/search_panel_select_multi_range',
+ '/web/dataset/call_kw/product/search_panel_select_multi_range',
+ '/web/dataset/search_read',
+ '/lunch/infos',
+ '/web/dataset/call_kw/ir.model.data/xmlid_to_res_id',
+ // Click m2o
+ '/web/dataset/call_kw/lunch.location/name_search',
+ // Click new location
+ '/lunch/user_location_set',
+ '/web/dataset/call_kw/product/search_panel_select_multi_range',
+ '/web/dataset/call_kw/product/search_panel_select_multi_range',
+ '/web/dataset/search_read',
+ '/lunch/infos',
+ '/web/dataset/call_kw/ir.model.data/xmlid_to_res_id',
+ ]);
+
+ list.destroy();
+ });
+
+ QUnit.test('search panel domain location false: fetch products in all locations', async function (assert) {
+ assert.expect(10);
+ const regularInfos = _.extend({}, this.regularInfos);
+
+ const list = await createLunchView({
+ View: LunchListView,
+ model: 'product',
+ data: this.data,
+ arch: `
+ <tree>
+ <field name="name"/>
+ </tree>
+ `,
+ mockRPC: function (route, args) {
+ assert.step(route);
+
+ if (route.startsWith('/lunch')) {
+ return mockLunchRPC({
+ infos: regularInfos,
+ userLocation: false,
+ }).apply(this, arguments);
+ }
+ if (args.method === 'search_panel_select_multi_range') {
+ assert.deepEqual(args.kwargs.search_domain, [],
+ 'The domain should not exist since the location is false.');
+ }
+ if (route === '/web/dataset/search_read') {
+ assert.deepEqual(args.domain, [],
+ 'The domain for fetching actual data should be correct');
+ }
+ return this._super.apply(this, arguments);
+ }
+ });
+ assert.verifySteps([
+ '/lunch/user_location_get',
+ '/web/dataset/call_kw/product/search_panel_select_multi_range',
+ '/web/dataset/call_kw/product/search_panel_select_multi_range',
+ '/web/dataset/search_read',
+ '/lunch/infos',
+ '/web/dataset/call_kw/ir.model.data/xmlid_to_res_id',
+ ])
+
+ list.destroy();
+ });
+
+ QUnit.test('add a product', async function (assert) {
+ assert.expect(1);
+
+ const list = await createLunchView({
+ View: LunchListView,
+ model: 'product',
+ data: this.data,
+ arch: `
+ <tree>
+ <field name="name"/>
+ </tree>
+ `,
+ mockRPC: mockLunchRPC({
+ infos: this.regularInfos,
+ userLocation: this.data['lunch.location'].records[0].id,
+ }),
+ intercepts: {
+ do_action: function (ev) {
+ assert.deepEqual(ev.data.action, {
+ name: "Configure Your Order",
+ res_model: 'lunch.order',
+ type: 'ir.actions.act_window',
+ views: [[false, 'form']],
+ target: 'new',
+ context: {
+ default_product_id: 1,
+ },
+ },
+ "should open the wizard");
+ },
+ },
+ });
+
+ await testUtils.dom.click(list.$('.o_data_row:first'));
+
+ list.destroy();
+ });
+ });
+});
+
+});
diff --git a/addons/lunch/static/tests/lunch_test_utils.js b/addons/lunch/static/tests/lunch_test_utils.js
index beef94f80a5..a59328a05dd 100644
--- a/addons/lunch/static/tests/lunch_test_utils.js
+++ b/addons/lunch/static/tests/lunch_test_utils.js
@@ -6,11 +6,11 @@ const RamStorage = require('web.RamStorage');
const {createView} = require('web.test_utils');
/**
- * Helper to create a lunch kanban view with searchpanel
+ * Helper to create a lunch view with searchpanel
*
* @param {object} params
*/
-async function createLunchKanbanView(params) {
+async function createLunchView(params) {
params.archs = params.archs || {};
var searchArch = params.archs[`${params.model},false,search`] || '<search></search>';
var searchPanelArch = `
@@ -52,7 +52,7 @@ function mockLunchRPC({infos, userLocation}) {
}
return {
- createLunchKanbanView,
+ createLunchView,
mockLunchRPC,
};
diff --git a/addons/lunch/views/lunch_product_views.xml b/addons/lunch/views/lunch_product_views.xml
index 0c5fb5d0319..7764aa19b45 100644
--- a/addons/lunch/views/lunch_product_views.xml
+++ b/addons/lunch/views/lunch_product_views.xml
@@ -91,6 +91,21 @@
</form>
</field>
</record>
+ <record id="lunch_product_report_view_tree" model="ir.ui.view">
+ <field name="name">lunch.product.tree</field>
+ <field name="model">lunch.product.report</field>
+ <field name="priority">999</field>
+ <field name="arch" type="xml">
+ <tree js_class="lunch_list">
+ <field name="name"/>
+ <field name="category_id"/>
+ <field name="supplier_id"/>
+ <field name="description"/>
+ <field name="product_id" invisible="1"/>
+ <field name="price" widget="monetary"/>
+ </tree>
+ </field>
+ </record>
<record id="view_lunch_product_kanban_order" model="ir.ui.view">
<field name="name">lunch.product.kanban</field>
@@ -330,7 +345,7 @@
<record id="lunch_product_action_order" model="ir.actions.act_window">
<field name="name">Order Your Lunch</field>
<field name="res_model">lunch.product.report</field>
- <field name="view_mode">kanban</field>
+ <field name="view_mode">kanban,tree</field>
<field name="view_id" ref="view_lunch_product_kanban_order"/>
<field name="search_view_id" ref="lunch_product_report_view_search"/>
<field name="domain">[('supplier_id.available_today', '=', True), '|', ('user_id', '=', False), ('user_id', '=', uid)]</field>
diff --git a/addons/lunch/views/lunch_templates.xml b/addons/lunch/views/lunch_templates.xml
index 2fbdb1d3df0..2b2ea02973a 100644
--- a/addons/lunch/views/lunch_templates.xml
+++ b/addons/lunch/views/lunch_templates.xml
@@ -2,17 +2,22 @@
<odoo>
<template id="assets_backend" name="lunch assets" inherit_id="web.assets_backend">
<xpath expr="." position="inside">
+ <link rel="stylesheet" type="text/scss" href="/lunch/static/src/scss/lunch_view.scss"/>
<link rel="stylesheet" type="text/scss" href="/lunch/static/src/scss/lunch_kanban.scss"/>
<link rel="stylesheet" type="text/scss" href="/lunch/static/src/scss/lunch_list.scss"/>
- <script type="text/javascript" src="/lunch/static/src/js/lunch_kanban_widget.js"></script>
+ <script type="text/javascript" src="/lunch/static/src/js/lunch_controller_common.js"></script>
+ <script type="text/javascript" src="/lunch/static/src/js/lunch_model.js"></script>
+ <script type="text/javascript" src="/lunch/static/src/js/lunch_widget.js"></script>
+ <script type="text/javascript" src="/lunch/static/src/js/lunch_mobile.js"></script>
<script type="text/javascript" src="/lunch/static/src/js/lunch_payment_dialog.js"></script>
<script type="text/javascript" src="/lunch/static/src/js/lunch_kanban_view.js"></script>
<script type="text/javascript" src="/lunch/static/src/js/lunch_kanban_controller.js"></script>
<script type="text/javascript" src="/lunch/static/src/js/lunch_kanban_renderer.js"></script>
<script type="text/javascript" src="/lunch/static/src/js/lunch_kanban_record.js"></script>
- <script type="text/javascript" src="/lunch/static/src/js/lunch_kanban_model.js"></script>
- <script type="text/javascript" src="/lunch/static/src/js/lunch_kanban_mobile.js"></script>
+ <script type="text/javascript" src="/lunch/static/src/js/lunch_list_view.js"></script>
+ <script type="text/javascript" src="/lunch/static/src/js/lunch_list_controller.js"></script>
+ <script type="text/javascript" src="/lunch/static/src/js/lunch_list_renderer.js"></script>
</xpath>
</template>
@@ -20,6 +25,7 @@
<xpath expr="." position="inside">
<script type="text/javascript" src="/lunch/static/tests/lunch_test_utils.js"></script>
<script type="text/javascript" src="/lunch/static/tests/lunch_kanban_tests.js"></script>
+ <script type="text/javascript" src="/lunch/static/tests/lunch_list_tests.js"></script>
</xpath>
</template>