[IMP] pos_self_order, website_sale: add info popup to product card in self
This commit introduce the information button on the product card in the self order mode. This button open a popup with the newly created field "description_self_order" which is an HTML field allowing the user to have a very customizable description for the product. It also removes the description_ecommerce field from the product view form as it is a field used in the website and not adapted for the backend (css/js not compatible). closes odoo/odoo#138216 Task-id: 3512835 Signed-off-by: Joseph Caburnay (jcb) <jcb@odoo.com>
This commit is contained in:
@@ -63,6 +63,8 @@
|
||||
'web/static/lib/bootstrap/js/dist/scrollspy.js',
|
||||
"pos_self_order/static/src/app/**/*",
|
||||
"point_of_sale/static/src/app/store/models/product_custom_attribute.js",
|
||||
'web_editor/static/src/js/editor/odoo-editor/src/base_style.scss',
|
||||
'web_editor/static/src/scss/web_editor.common.scss',
|
||||
],
|
||||
# Assets tests
|
||||
"pos_self_order.assets_tests": [
|
||||
|
||||
@@ -15,6 +15,9 @@ class ProductTemplate(models.Model):
|
||||
help="If this product is available in the Self Order screens",
|
||||
default=True,
|
||||
)
|
||||
description_self_order = fields.Html(
|
||||
string="Product Description for Self Order",
|
||||
)
|
||||
|
||||
@api.onchange('available_in_pos')
|
||||
def _on_change_available_in_pos(self):
|
||||
@@ -141,7 +144,7 @@ class ProductProduct(models.Model):
|
||||
"attributes": self._get_attributes(pos_config),
|
||||
"name": self._get_name(),
|
||||
"id": self.id,
|
||||
"description_sale": self.description_sale,
|
||||
"description_self_order": self.description_self_order,
|
||||
"pos_categ_ids": self.pos_categ_ids.mapped("name") or ["Other"],
|
||||
"pos_combo_ids": self.combo_ids.mapped("id") or False,
|
||||
"is_pos_groupable": self.uom_id.is_pos_groupable,
|
||||
|
||||
@@ -4,6 +4,7 @@ import { Component, useRef } from "@odoo/owl";
|
||||
import { useSelfOrder } from "@pos_self_order/app/self_order_service";
|
||||
import { useService, useForwardRefToParent } from "@web/core/utils/hooks";
|
||||
import { Line } from "@pos_self_order/app/models/line";
|
||||
import { ProductInfoPopup } from "@pos_self_order/app/components/product_info_popup/product_info_popup";
|
||||
|
||||
export class ProductCard extends Component {
|
||||
static template = "pos_self_order.ProductCard";
|
||||
@@ -15,6 +16,7 @@ export class ProductCard extends Component {
|
||||
setup() {
|
||||
this.selfOrder = useSelfOrder();
|
||||
this.router = useService("router");
|
||||
this.dialog = useService("dialog");
|
||||
|
||||
useForwardRefToParent("currentProductCard");
|
||||
}
|
||||
@@ -112,4 +114,14 @@ export class ProductCard extends Component {
|
||||
await this.selfOrder.getPricesFromServer();
|
||||
}
|
||||
}
|
||||
|
||||
showProductInfo() {
|
||||
this.dialog.add(ProductInfoPopup, {
|
||||
product: this.props.product,
|
||||
title: this.props.product.name,
|
||||
addToCart: () => {
|
||||
this.selectProduct();
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,28 @@
|
||||
.self_order_product_card {
|
||||
position: relative
|
||||
}
|
||||
|
||||
.scale-up {
|
||||
transform: scale(1.2);
|
||||
transition: transform .75s ease-in-out;
|
||||
}
|
||||
|
||||
.product-information-tag {
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-style: solid;
|
||||
border-width: 0 34px 34px 0;
|
||||
border-color: transparent #9a9ea180 transparent transparent;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 17px;
|
||||
color: white;
|
||||
text-align: center;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.product-information-tag-logo {
|
||||
position: absolute;
|
||||
left: 22px;
|
||||
top: 4px;
|
||||
}
|
||||
|
||||
@@ -6,6 +6,9 @@
|
||||
t-att-title="props.product.name"
|
||||
t-on-click="selectProduct"
|
||||
t-ref="selfProductCard">
|
||||
<div t-if="props.product.description_self_order" class="product-information-tag" t-on-click.prevent.stop="showProductInfo">
|
||||
<i class="product-information-tag-logo fa fa-info fs-4" role="img" aria-label="Product Information" title="Product Information" />
|
||||
</div>
|
||||
<div
|
||||
class="ratio ratio-1x1 w-25 w-sm-50 w-md-100"
|
||||
t-att-class="{
|
||||
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
/** @odoo-module */
|
||||
|
||||
import { Component, useExternalListener } from "@odoo/owl";
|
||||
|
||||
export class ProductInfoPopup extends Component {
|
||||
static template = "pos_self_order.ProductInfoPopup";
|
||||
static props = ["product", "addToCart"];
|
||||
|
||||
setup() {
|
||||
useExternalListener(window, "click", this.props.close);
|
||||
}
|
||||
|
||||
addToCartAndClose() {
|
||||
this.props.addToCart();
|
||||
this.props.close();
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
.self_order_product_info_popup {
|
||||
.modal-dialog {
|
||||
height: auto !important;
|
||||
top: 20%;
|
||||
}
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<templates id="template" xml:space="preserve">
|
||||
<t t-name="pos_self_order.ProductInfoPopup" owl="1">
|
||||
<div class="self_order_product_info_popup o_dialog" t-att-id="id">
|
||||
<div role="dialog" class="modal d-block" tabindex="-1">
|
||||
<div class="modal-dialog" role="document" t-on-click.stop="">
|
||||
<div class="modal-content rounded">
|
||||
<div class="modal-header">
|
||||
<h1 class="modal-title fw-bolder" t-esc="props.product.name"/>
|
||||
<button type="button" class="btn-close" t-on-click.stop="() => this.props.close()"></button>
|
||||
</div>
|
||||
<span class="modal-body o_self_order_main_desc fs-3 p-4 ps-5 overflow-auto" t-out="props.product.description_self_order" />
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-primary" t-on-click.stop="() => this.addToCartAndClose()">Add to Cart</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</templates>
|
||||
@@ -9,7 +9,7 @@ export class Product extends Reactive {
|
||||
attributes,
|
||||
name,
|
||||
id,
|
||||
description_sale,
|
||||
description_self_order,
|
||||
pos_categ_ids,
|
||||
pos_combo_ids,
|
||||
is_pos_groupable,
|
||||
@@ -29,7 +29,7 @@ export class Product extends Reactive {
|
||||
this.has_image = product.has_image;
|
||||
this.attributes = product.attributes;
|
||||
this.name = product.name;
|
||||
this.description_sale = product.description_sale;
|
||||
this.description_self_order = product.description_self_order;
|
||||
this.pos_categ_ids = product.pos_categ_ids;
|
||||
this.pos_combo_ids = product.pos_combo_ids;
|
||||
this.is_pos_groupable = product.is_pos_groupable;
|
||||
|
||||
@@ -59,9 +59,9 @@
|
||||
</div>
|
||||
<div class="o-so-product-details-description">
|
||||
<h2 t-esc="state.selectedProduct.name"/>
|
||||
<small t-if="state.selectedProduct.description_sale"
|
||||
<small t-if="state.selectedProduct.description_self_order"
|
||||
class="o_self_order_main_desc d-block mb-3 text-muted"
|
||||
t-out="state.selectedProduct.description_sale"
|
||||
t-out="state.selectedProduct.description_self_order"
|
||||
/>
|
||||
<span class="fs-3" t-esc="selfOrder.formatMonetary(selfOrder.getProductDisplayPrice(state.selectedProduct))"/>
|
||||
</div>
|
||||
|
||||
@@ -25,9 +25,9 @@
|
||||
</div>
|
||||
<div class="o-so-product-details-description">
|
||||
<h2 t-esc="product.name"/>
|
||||
<small t-if="product.description_sale"
|
||||
<small t-if="product.description_self_order"
|
||||
class="o_self_order_main_desc d-block mb-3 text-muted"
|
||||
t-out="product.description_sale"
|
||||
t-out="product.description_self_order"
|
||||
/>
|
||||
<span class="fs-3" t-esc="selfOrder.formatMonetary(selfOrder.getProductDisplayPrice(product))"/>
|
||||
</div>
|
||||
|
||||
@@ -10,7 +10,7 @@ import { getColor } from "@web/core/colors/colors";
|
||||
import { categorySorter } from "@pos_self_order/app/utils";
|
||||
import { Order } from "@pos_self_order/app/models/order";
|
||||
import { batched } from "@web/core/utils/timing";
|
||||
import { useState } from "@odoo/owl";
|
||||
import { useState, markup } from "@odoo/owl";
|
||||
import { useService } from "@web/core/utils/hooks";
|
||||
import { registry } from "@web/core/registry";
|
||||
import { cookie } from "@web/core/browser/cookie";
|
||||
@@ -33,6 +33,8 @@ export class SelfOrder extends Reactive {
|
||||
...session.pos_self_order_data,
|
||||
});
|
||||
|
||||
this.markupDescriptions();
|
||||
|
||||
this.productsGroupedByCategory = {};
|
||||
this.lastEditedProductId = null;
|
||||
this.attributeValueById = {};
|
||||
@@ -78,6 +80,14 @@ export class SelfOrder extends Reactive {
|
||||
return this.editedOrder;
|
||||
}
|
||||
|
||||
markupDescriptions() {
|
||||
for (const product of this.products) {
|
||||
product.description_self_order = product.description_self_order
|
||||
? markup(product.description_self_order)
|
||||
: "";
|
||||
}
|
||||
}
|
||||
|
||||
initData() {
|
||||
this.currentLanguage = this.config.self_ordering_available_language_ids.find(
|
||||
(l) => l.code === cookie.get("frontend_lang")
|
||||
|
||||
@@ -22,6 +22,14 @@
|
||||
<xpath expr="//group[@name='pos']" position="inside">
|
||||
<field name="self_order_available" invisible="not available_in_pos"/>
|
||||
</xpath>
|
||||
<group name="upsell" position="after">
|
||||
<group string="Product Description for Self Order" name="description_self_order">
|
||||
<field name="description_self_order"
|
||||
placeholder="Information about your product for Self Order and Kiosk"
|
||||
nolabel="1"
|
||||
colspan="2"/>
|
||||
</group>
|
||||
</group>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
@@ -168,12 +168,6 @@
|
||||
<group name="product_template_images" string="Extra Product Media" invisible="not sale_ok">
|
||||
<field name="product_template_image_ids" class="o_website_sale_image_list" context="{'default_name': name}" mode="kanban" add-label="Add a Media" nolabel="1"/>
|
||||
</group>
|
||||
<group string="eCommerce Description">
|
||||
<field name="description_ecommerce"
|
||||
placeholder="This note is added to the product page on your eCommerce shop"
|
||||
nolabel="1"
|
||||
colspan="2"/>
|
||||
</group>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
Reference in New Issue
Block a user