[IMP] pos_self_order: add carousel on kiosk landing page
Carousel is a slideshow for cycling through a series of images. It is a dynamic display of content that can be used to show a rotating series of pictures, articles, or advertisements. Following the specifications, the carousel is displayed on the landing page of the kiosk mode. Images of carousel can be configured from the settings (ir.attachement). Used carousel is a bootstrap carousel. closes odoo/odoo#133760 Taskid: 3484170 Signed-off-by: Adrien Guilliams (adgu) <adgu@odoo.com>
This commit is contained in:
@@ -26,7 +26,6 @@
|
||||
# Assets
|
||||
"pos_self_order.assets_common": [
|
||||
"pos_self_order/static/src/kiosk/bootstrap_overridden.scss",
|
||||
"web/static/lib/jquery/jquery.js",
|
||||
("include", "web._assets_helpers"),
|
||||
("include", "web._assets_backend_helpers"),
|
||||
("include", "web._assets_primary_variables"),
|
||||
|
||||
@@ -69,12 +69,10 @@ class PosConfig(models.Model):
|
||||
[("code", "=", self.env.lang)], limit=1
|
||||
),
|
||||
)
|
||||
self_order_kiosk_image_home = fields.Image(
|
||||
string="Self Order Kiosk Image Home",
|
||||
self_order_kiosk_image_home_ids = fields.Many2many(
|
||||
'ir.attachment',
|
||||
string="Home Images",
|
||||
help="Image to display on the self order screen",
|
||||
max_width=1080,
|
||||
max_height=1920,
|
||||
default=_self_order_default_image,
|
||||
)
|
||||
self_order_kiosk_image_eat = fields.Image(
|
||||
string="Self Order Kiosk Image Eat",
|
||||
@@ -89,11 +87,6 @@ class PosConfig(models.Model):
|
||||
max_width=1200,
|
||||
max_height=250,
|
||||
)
|
||||
self_order_kiosk_image_home_name = fields.Char(
|
||||
string="Self Order Kiosk Image Home Name",
|
||||
help="Name of the image to display on the self order screen",
|
||||
default=_self_order_default_image_name,
|
||||
)
|
||||
self_order_kiosk_image_eat_name = fields.Char(
|
||||
string="Self Order Kiosk Image Eat Name",
|
||||
help="Name of the image to display on the self order screen",
|
||||
@@ -163,6 +156,17 @@ class PosConfig(models.Model):
|
||||
pos_config_ids = super().create(vals_list)
|
||||
|
||||
for pos_config_id in pos_config_ids:
|
||||
for image_name in ['landing_01.jpg', 'landing_02.jpg', 'landing_03.jpg']:
|
||||
image_path = modules.get_module_resource("pos_self_order", "static/img", image_name)
|
||||
attachment = self.env['ir.attachment'].create({
|
||||
'name': image_name,
|
||||
'datas': base64.b64encode(file_open(image_path, "rb").read()),
|
||||
'res_model': 'pos.config',
|
||||
'res_id': pos_config_id.id,
|
||||
'type': 'binary',
|
||||
})
|
||||
pos_config_id.self_order_kiosk_image_home_ids = [(4, attachment.id)]
|
||||
|
||||
if pos_config_id.module_pos_restaurant:
|
||||
pos_config_id.self_order_view_mode = True
|
||||
pos_config_id.self_order_table_mode = True
|
||||
@@ -348,7 +352,7 @@ class PosConfig(models.Model):
|
||||
"kiosk_mode": self.self_order_kiosk_mode,
|
||||
"kiosk_takeaway": self.self_order_kiosk_takeaway,
|
||||
"kiosk_alternative_fp": self.self_order_kiosk_alternative_fp_id.id,
|
||||
"kiosk_image_home": self._get_kiosk_image(self.self_order_kiosk_image_home),
|
||||
"kiosk_image_home": self._get_kiosk_attachment(self.self_order_kiosk_image_home_ids),
|
||||
"kiosk_image_eat": self._get_kiosk_image(self.self_order_kiosk_image_eat),
|
||||
"kiosk_image_brand": self._get_kiosk_image(self.self_order_kiosk_image_brand),
|
||||
"kiosk_default_language": default_language[0] if default_language else [],
|
||||
@@ -359,6 +363,15 @@ class PosConfig(models.Model):
|
||||
image = Image.open(io.BytesIO(base64.b64decode(image))) if image else False
|
||||
return image_to_base64(image, 'PNG').decode('utf-8') if image else False
|
||||
|
||||
def _get_kiosk_attachment(self, images):
|
||||
encoded_images = []
|
||||
for image in images:
|
||||
encoded_images.append({
|
||||
'id': image.id,
|
||||
'data': image.datas.decode('utf-8'),
|
||||
})
|
||||
return encoded_images
|
||||
|
||||
def _split_qr_codes_list(self, floors: List[Dict], cols: int) -> List[Dict]:
|
||||
"""
|
||||
:floors: the list of floors
|
||||
|
||||
@@ -12,10 +12,9 @@ class ResConfigSettings(models.TransientModel):
|
||||
pos_self_order_kiosk_mode = fields.Selection(related="pos_config_id.self_order_kiosk_mode", readonly=False)
|
||||
pos_self_order_kiosk_takeaway = fields.Boolean(related="pos_config_id.self_order_kiosk_takeaway", readonly=False)
|
||||
pos_self_order_kiosk_alternative_fp_id = fields.Many2one(related="pos_config_id.self_order_kiosk_alternative_fp_id", readonly=False)
|
||||
pos_self_order_kiosk_image_home = fields.Image(related="pos_config_id.self_order_kiosk_image_home", readonly=False)
|
||||
pos_self_order_kiosk_image_home_ids = fields.Many2many(related="pos_config_id.self_order_kiosk_image_home_ids", readonly=False)
|
||||
pos_self_order_kiosk_image_eat = fields.Image(related="pos_config_id.self_order_kiosk_image_eat", readonly=False)
|
||||
pos_self_order_kiosk_image_brand = fields.Image(related="pos_config_id.self_order_kiosk_image_brand", readonly=False)
|
||||
pos_self_order_kiosk_image_home_name = fields.Char(related="pos_config_id.self_order_kiosk_image_home_name", readonly=False)
|
||||
pos_self_order_kiosk_image_eat_name = fields.Char(related="pos_config_id.self_order_kiosk_image_eat_name", readonly=False)
|
||||
pos_self_order_kiosk_image_brand_name = fields.Char(related="pos_config_id.self_order_kiosk_image_brand_name", readonly=False)
|
||||
pos_self_order_kiosk_available_language_ids = fields.Many2many(related="pos_config_id.self_order_kiosk_available_language_ids", readonly=False)
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 91 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 83 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 96 KiB |
@@ -1,11 +1,13 @@
|
||||
/** @odoo-module */
|
||||
/* global Carousel */
|
||||
|
||||
import { Component, onWillStart } from "@odoo/owl";
|
||||
import { Component, onMounted, onWillStart, onWillUnmount, useRef } from "@odoo/owl";
|
||||
import { useselfOrder } from "@pos_self_order/kiosk/self_order_kiosk_service";
|
||||
import { useService } from "@web/core/utils/hooks";
|
||||
import { KioskTemplate } from "@pos_self_order/kiosk/template/kiosk_template";
|
||||
import { LanguagePopup } from "@pos_self_order/kiosk/components/language_popup/language_popup";
|
||||
import { Order } from "@pos_self_order/common/models/order";
|
||||
import { loadJS } from "@web/core/assets";
|
||||
|
||||
export class LandingPage extends Component {
|
||||
static template = "pos_self_order.LandingPage";
|
||||
@@ -15,10 +17,28 @@ export class LandingPage extends Component {
|
||||
this.selfOrder = useselfOrder();
|
||||
this.router = useService("router");
|
||||
this.dialog = useService("dialog");
|
||||
this.carouselRef = useRef("carousel");
|
||||
this.activeSelected = false;
|
||||
this.carouselInterval = null;
|
||||
|
||||
onWillStart(() => {
|
||||
this.selfOrder.currentOrder = new Order({});
|
||||
this.tablePadNumber = null;
|
||||
|
||||
return loadJS("/web/static/lib/bootstrap/js/dist/carousel.js");
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
// used to init carousel after components mount / unmount
|
||||
const carousel = new Carousel(this.carouselRef.el);
|
||||
|
||||
this.carouselInterval = setInterval(() => {
|
||||
carousel.next();
|
||||
}, 5000);
|
||||
});
|
||||
|
||||
onWillUnmount(() => {
|
||||
clearInterval(this.carouselInterval);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -41,4 +61,12 @@ export class LandingPage extends Component {
|
||||
get languages() {
|
||||
return this.selfOrder.kiosk_available_languages;
|
||||
}
|
||||
|
||||
get activeImage() {
|
||||
if (!this.activeSelected) {
|
||||
this.activeSelected = true;
|
||||
return "active";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,12 +7,11 @@
|
||||
<img class="rounded" t-attf-src="{{currentLanguage.flag_image_url}}" />
|
||||
<span t-esc="currentLanguage.display_name" class="ms-3"></span>
|
||||
</div>
|
||||
<div t-if="selfOrder.kiosk_image_home" t-on-click="start" class="o_kiosk_home_page d-flex flex-column vh-100 align-items-center overflow-hidden">
|
||||
<!-- Carousel ready, just need to add a way to add more than 1 image in the setting. -->
|
||||
<div id="imageCarousel" class="carousel slide h-100" data-bs-ride="carousel">
|
||||
<div t-if="selfOrder.kiosk_image_home.length > 0" t-on-click="start" class="o_kiosk_home_page d-flex flex-column vh-100 align-items-center overflow-hidden">
|
||||
<div id="carouselAutoplaying" t-ref="carousel" class="carousel slide h-100" data-bs-ride="true">
|
||||
<div class="carousel-inner h-100">
|
||||
<div class="carousel-item active h-100">
|
||||
<img t-attf-src="data:image/png;base64,{{selfOrder.kiosk_image_home}}" class="o_kiosk-landing_image d-block h-100 w-100" />
|
||||
<div t-foreach="selfOrder.kiosk_image_home" t-as="image" t-key="image.id" t-attf-class="carousel-item h-100 {{activeImage}}">
|
||||
<img t-attf-src="data:image/png;base64,{{image.data}}" class="o_kiosk-landing_image d-block h-100 w-100" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -58,9 +58,8 @@
|
||||
<setting string="Kiosk Images" help="Allow customers to customize kiosk images" invisible="not is_kiosk_mode">
|
||||
<div class="content-group mt-3">
|
||||
<div class="d-flex flex-column align-items-start">
|
||||
<field name="pos_self_order_kiosk_image_home_name" invisible ="1"/>
|
||||
<label for="pos_self_order_image" string="Home background"/>
|
||||
<field name="pos_self_order_kiosk_image_home" class="w-100" filename="pos_self_order_kiosk_image_home_name"/>
|
||||
<field name="pos_self_order_kiosk_image_home_ids" class="w-100" widget="many2many_binary" />
|
||||
</div>
|
||||
<div class="d-flex flex-column align-items-start">
|
||||
<field name="pos_self_order_kiosk_image_eat_name" invisible ="1"/>
|
||||
|
||||
Reference in New Issue
Block a user