You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
856 lines
53 KiB
856 lines
53 KiB
<?xml version="1.0" encoding="UTF-8" ?>
|
|
<odoo>
|
|
<template id="classic_product_header" inherit_id="website_sale.product"
|
|
active="True" customize_show="True"
|
|
name="Product Header">
|
|
<!-- Code for adding a breadcrumb section and a price list filter in the product header of the classic store layout. -->
|
|
<xpath expr="//div[hasclass('js_sale')]" position="before">
|
|
<section class="banner_search">
|
|
<div class="container">
|
|
<div class="row">
|
|
<div class="col-md-4 mt-3">
|
|
<ol class="breadcrumb">
|
|
<li class="breadcrumb-item">
|
|
<a t-att-href="keep(category=0)">Products
|
|
</a>
|
|
</li>
|
|
<li t-if="category" class="breadcrumb-item">
|
|
<a style="color: #763242 !important;"
|
|
t-att-href="keep('/shop/category/%s' % slug(category), category=0)"
|
|
t-field="category.name"/>
|
|
</li>
|
|
<li class="breadcrumb-item active">
|
|
<span t-field="product.name"/>
|
|
</li>
|
|
</ol>
|
|
</div>
|
|
<div class="col-md-8 mt-3">
|
|
<div class="form-inline justify-content-end">
|
|
<t t-call="website_sale.pricelist_list">
|
|
<t t-set="_classes" t-valuef="ml-3"/>
|
|
</t>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
</xpath>
|
|
</template>
|
|
<template id="product_price">
|
|
<!-- This is a template for displaying the price of a product in an e-commerce website. It uses the schema.org markup
|
|
for the product's offer, which can be beneficial for search engine optimization. The template includes a section
|
|
with a background color of #763242 and a centered text for displaying the product's price. -->
|
|
<!-- The price is displayed in two parts, the default price and the actual price with a discount if applicable.
|
|
The default price is shown in smaller text and is crossed out if there is a discount. The actual price is shown
|
|
in larger text and is highlighted in white. The price is also displayed in the website's currency. -->
|
|
<div itemprop="offers" itemscope="itemscope"
|
|
itemtype="http://schema.org/Offer" class="product_price mt16">
|
|
<div class="price_box"
|
|
style="background-color: #763242;text-align: center;padding: 30px;margin-bottom: 50px;">
|
|
<p style="color: #fff;font-size: 18px;font-weight: 600;padding-bottom: 5px;">
|
|
Price
|
|
</p>
|
|
<h4 class="oe_price_h4 css_editable_mode_hidden">
|
|
<span t-attf-class="text-danger oe_default_price {{'' if combination_info['has_discounted_price'] else 'd-none'}}"
|
|
style="color: #fff;font-size: 18px;font-weight: 600;padding-bottom: 5px;"
|
|
t-esc="combination_info['list_price']"
|
|
t-options="{'widget': 'monetary', 'display_currency': website.currency_id}"/>
|
|
<b class="oe_price"
|
|
style="color: #fff;font-size: 30px;font-weight: 600;padding-bottom: 5px;"
|
|
t-esc="combination_info['price']"
|
|
t-options="{'widget': 'monetary', 'display_currency': website.currency_id}"/>
|
|
<span itemprop="price" style="display:none;"
|
|
t-esc="combination_info['price']"/>
|
|
<span itemprop="priceCurrency" style="display:none;"
|
|
t-esc="website.currency_id.name"/>
|
|
</h4>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
<template id="product_quantity" inherit_id="website_sale.product"
|
|
customize_show="True" name="Select Quantity">
|
|
<!-- This code defines a template named "product_quantity" which renders a section for selecting the quantity
|
|
of a product to add to the cart. The section includes a quantity input field and two buttons for incrementing
|
|
or decrementing the quantity. -->
|
|
<xpath expr="//div[@id='add_to_cart_wrap']" position="before">
|
|
<div class="css_quantity input-group d-inline-flex mr-2 my-1 align-middle"
|
|
contenteditable="false">
|
|
<div class="input-group-prepend"
|
|
style="background-color:#763242;">
|
|
<a t-attf-href="#" class="btn btn-primary js_add_cart_json"
|
|
aria-label="Remove one" title="Remove one">
|
|
<i class="fa fa-minus"/>
|
|
</a>
|
|
</div>
|
|
<input type="text" class="form-control quantity" data-min="1"
|
|
name="add_qty" t-att-value="add_qty or 1"/>
|
|
<div class="input-group-append">
|
|
<a t-attf-href="#"
|
|
class="btn btn-primary float_left js_add_cart_json"
|
|
aria-label="Add one" title="Add one">
|
|
<i class="fa fa-plus"/>
|
|
</a>
|
|
</div>
|
|
</div>
|
|
<br/>
|
|
</xpath>
|
|
</template>
|
|
<template id="classic_product_view" inherit_id="website_sale.product"
|
|
name="Classic Store Products">
|
|
<!-- This template defines the structure and layout of a classic store product page.
|
|
It includes sections for displaying product information, images, pricing, description,
|
|
specifications, and customer reviews. It also implements Bootstrap tabs for organizing
|
|
the product details, specifications, and reviews. -->
|
|
<xpath expr="//div[hasclass('js_sale')]" position="replace">
|
|
<div itemscope="itemscope" itemtype="http://schema.org/Product"
|
|
id="wrap" class="js_sale">
|
|
<!-- The div uses the Odoo website framework and provides information such as the product name, price,
|
|
images, description, and customer reviews. It also provides functionality for adding the product
|
|
to the user's cart. -->
|
|
<div class="oe_structure oe_empty oe_structure_not_nearest"
|
|
id="oe_structure_website_sale_product_1"
|
|
data-editor-message="DROP BUILDING BLOCKS HERE TO MAKE THEM AVAILABLE ACROSS ALL PRODUCTS"/>
|
|
<section
|
|
t-attf-class="container py-4 oe_website_sale #{'discount' if combination_info['has_discounted_price'] else ''}"
|
|
id="product_detail"
|
|
t-att-data-view-track="view_track and '1' or '0'"
|
|
t-att-data-product-tracking-info="json.dumps(request.env['product.template'].get_google_analytics_data(combination_info))">
|
|
<div class="row">
|
|
<div class="col-md-6 mt-md-4">
|
|
<h1 itemprop="name" t-field="product.name">Product
|
|
Name
|
|
</h1>
|
|
<t t-call="website_sale.shop_product_carousel"/>
|
|
</div>
|
|
<div class="col-md-6 mt-md-4" id="product_details">
|
|
<t t-set="base_url"
|
|
t-value="product.get_base_url()"/>
|
|
<span itemprop="url" style="display:none;"
|
|
t-esc="base_url + product.website_url"/>
|
|
<span itemprop="image" style="display:none;"
|
|
t-esc="base_url + website.image_url(product, 'image_1920')"/>
|
|
<t t-if="is_view_active('website_sale.product_comment')">
|
|
<a href="#o_product_page_reviews"
|
|
class="o_product_page_reviews_link text-decoration-none">
|
|
<t t-call="portal_rating.rating_widget_stars_static">
|
|
<t t-set="rating_avg"
|
|
t-value="product.rating_avg"/>
|
|
<t t-set="trans_text_plural">%s
|
|
reviews
|
|
</t>
|
|
<t t-set="trans_text_singular">%s
|
|
review
|
|
</t>
|
|
<t t-set="rating_count"
|
|
t-value="(trans_text_plural if product.rating_count > 1 else trans_text_singular) % product.rating_count"/>
|
|
</t>
|
|
</a>
|
|
</t>
|
|
<form t-if="product._is_add_to_cart_possible()"
|
|
action="/shop/cart/update" method="POST">
|
|
<input type="hidden" name="csrf_token"
|
|
t-att-value="request.csrf_token()"/>
|
|
<div class="js_product js_main_product mb-3">
|
|
<div class="classic_price">
|
|
<div class="classic_price_text">
|
|
Price
|
|
</div>
|
|
<div class="classic_price_value">
|
|
<t t-call="website_sale.product_price"/>
|
|
</div>
|
|
</div>
|
|
<t t-placeholder="select">
|
|
<input type="hidden" class="product_id"
|
|
name="product_id"
|
|
t-att-value="product_variant.id"/>
|
|
<input type="hidden"
|
|
class="product_template_id"
|
|
name="product_template_id"
|
|
t-att-value="product.id"/>
|
|
<input t-if="product.public_categ_ids.ids"
|
|
type="hidden"
|
|
class="product_category_id"
|
|
name="product_category_id"
|
|
t-att-value="product.public_categ_ids.ids[0]"/>
|
|
<t t-if="combination"
|
|
t-call="sale.variants">
|
|
<t t-set="ul_class"
|
|
t-valuef="flex-column"/>
|
|
<t t-set="parent_combination"
|
|
t-value="None"/>
|
|
</t>
|
|
<t t-else="">
|
|
<ul class="d-none js_add_cart_variants"
|
|
t-att-data-attribute_exclusions="{'exclusions: []'}"/>
|
|
</t>
|
|
</t>
|
|
<p t-if="True"
|
|
class="css_not_available_msg alert alert-warning">
|
|
This combination does not exist.
|
|
</p>
|
|
<div id="add_to_cart_wrap"
|
|
class="d-inline">
|
|
<a data-animation-selector=".o_wsale_product_images"
|
|
role="button" id="add_to_cart"
|
|
class="btn btn-primary btn-lg js_check_product a-submit my-1 mr-1 px-5 font-weight-bold flex-grow-1"
|
|
href="#">
|
|
<i
|
|
class="fa fa-shopping-cart mr-2"/>
|
|
ADD TO CART
|
|
</a>
|
|
<br/>
|
|
<div id="product_option_block"
|
|
class="d-inline-block align-middle"/>
|
|
</div>
|
|
</div>
|
|
<p t-field="product.description_sale"
|
|
class="text-muted my-2"
|
|
placeholder="A short description that will also appear on documents."/>
|
|
</form>
|
|
<p t-elif="not product.active"
|
|
class="alert alert-warning">This product is no
|
|
longer available.
|
|
</p>
|
|
<p t-else="" class="alert alert-warning">This
|
|
product has no valid combination.
|
|
</p>
|
|
<div id="product_attributes_simple">
|
|
<t t-set="single_value_attributes"
|
|
t-value="product.valid_product_template_attribute_line_ids._prepare_single_value_for_display()"/>
|
|
<table t-attf-class="table table-sm text-muted {{'' if single_value_attributes else 'd-none'}}">
|
|
<t t-foreach="single_value_attributes"
|
|
t-as="attribute">
|
|
<tr>
|
|
<td>
|
|
<span t-field="attribute.name"/>
|
|
:
|
|
<t t-foreach="single_value_attributes[attribute]"
|
|
t-as="ptal">
|
|
<span t-field="ptal.product_template_value_ids._only_active().name"/>
|
|
<t t-if="not ptal_last">,
|
|
</t>
|
|
</t>
|
|
</td>
|
|
</tr>
|
|
</t>
|
|
</table>
|
|
</div>
|
|
<div id="o_product_terms_and_share">
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
<div itemprop="description"
|
|
t-field="product.website_description"
|
|
class="oe_structure oe_empty mt16"
|
|
id="product_full_description"/>
|
|
<div class="oe_structure oe_empty oe_structure_not_nearest mt16"
|
|
id="oe_structure_website_sale_product_2"
|
|
data-editor-message="DROP BUILDING BLOCKS HERE TO MAKE THEM AVAILABLE ACROSS ALL PRODUCTS"/>
|
|
</div>
|
|
<section class="product_single">
|
|
<!-- The section defines a template for a product page with three tabs: Product Details, Specification,
|
|
and Reviews. It uses Bootstrap's tab and collapse components to display the product information. -->
|
|
<div class="container">
|
|
<div class="row">
|
|
<div class="col-lg-8 col-12">
|
|
<div class="tabs">
|
|
<ul class="nav nav-pills mb-3" id="pills-tab"
|
|
role="tablist">
|
|
<li class="nav-item">
|
|
<a class="nav-link active"
|
|
id="pills-home-tab"
|
|
data-toggle="pill"
|
|
href="#pills-home"
|
|
role="tab"
|
|
aria-controls="pills-home"
|
|
aria-selected="true">Product Details
|
|
</a>
|
|
</li>
|
|
<li class="nav-item">
|
|
<a class="nav-link"
|
|
id="pills-profile-tab"
|
|
data-toggle="pill"
|
|
href="#pills-profile"
|
|
role="tab"
|
|
aria-controls="pills-profile"
|
|
aria-selected="false">Specification
|
|
</a>
|
|
</li>
|
|
<li class="nav-item">
|
|
<a class="nav-link"
|
|
id="pills-contact-tab"
|
|
data-toggle="pill"
|
|
href="#pills-contact"
|
|
role="tab"
|
|
aria-controls="pills-contact"
|
|
aria-selected="false">Reviews
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
<div class="tab-content" id="pills-tabContent">
|
|
<div class="tab-pane fade show active"
|
|
id="pills-home" role="tabpanel"
|
|
aria-labelledby="pills-home-tab">
|
|
<div class="p_details">
|
|
<h4>Product Description</h4>
|
|
<p>
|
|
<t t-esc="product.description_sale"/>
|
|
</p>
|
|
</div>
|
|
</div>
|
|
<div class="tab-pane fade"
|
|
id="pills-profile" role="tabpanel"
|
|
aria-labelledby="pills-profile-tab">
|
|
<div class="p_spec">
|
|
<h4>Product Specification</h4>
|
|
<section id="product_full_spec">
|
|
<t t-set="categories"
|
|
t-value="product.valid_product_template_attribute_line_ids._prepare_categories_for_display()"/>
|
|
<t t-if="categories">
|
|
<div class="row">
|
|
<div id='product_specifications'>
|
|
<table class='table table-bordered mt-5'>
|
|
<t t-foreach="categories"
|
|
t-as="category">
|
|
<t t-if="len(categories) > 1">
|
|
<tr class="clickable"
|
|
data-toggle="collapse"
|
|
t-att-data-target="'.o_ws_category_%d' % category.id">
|
|
<th class="text-left"
|
|
t-att-colspan="2">
|
|
<span t-if="category"
|
|
t-field="category.name"/>
|
|
<span t-else="">
|
|
Uncategorized
|
|
</span>
|
|
</th>
|
|
</tr>
|
|
</t>
|
|
<tr t-foreach="categories[category].filtered(lambda l: len(l.value_ids) > 1)"
|
|
t-as="ptal"
|
|
t-att-class="'collapse show o_ws_category_%d' % category.id">
|
|
<td>
|
|
<span t-field="ptal.attribute_id.name"/>
|
|
</td>
|
|
<td>
|
|
<t t-foreach="ptal.value_ids"
|
|
t-as="pav">
|
|
<span t-field="pav.name"/>
|
|
<t t-if="not pav_last">
|
|
or
|
|
</t>
|
|
</t>
|
|
</td>
|
|
</tr>
|
|
<t t-set="single_value_attributes"
|
|
t-value="categories[category]._prepare_single_value_for_display()"/>
|
|
<tr t-foreach="single_value_attributes"
|
|
t-as="attribute"
|
|
t-att-class="'collapse show o_ws_category_%d' % category.id">
|
|
<td>
|
|
<span t-field="attribute.name"/>
|
|
</td>
|
|
<td>
|
|
<t t-foreach="single_value_attributes[attribute]"
|
|
t-as="ptal">
|
|
<span t-field="ptal.product_template_value_ids._only_active().name"/>
|
|
<t t-if="not ptal_last">
|
|
,
|
|
</t>
|
|
</t>
|
|
</td>
|
|
</tr>
|
|
</t>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</t>
|
|
</section>
|
|
</div>
|
|
</div>
|
|
<div class="tab-pane fade"
|
|
id="pills-contact" role="tabpanel"
|
|
aria-labelledby="pills-contact-tab">
|
|
<div class="P_review">
|
|
<h4>
|
|
Product Review
|
|
</h4>
|
|
<t t-call="portal.message_thread">
|
|
<t t-set="object"
|
|
t-value="product"/>
|
|
<t t-set="display_rating"
|
|
t-value="True"/>
|
|
</t>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
</xpath>
|
|
</template>
|
|
<template id="classic_store_products_item"
|
|
name="Classic Store Products Items"
|
|
inherit_id="website_sale.products_item">
|
|
<!-- The template uses various attributes and fields to dynamically populate product information,
|
|
such as product_href for the product link, product.name for the product title, product.public_categ_ids.name
|
|
for the product category name, and website.currency_id for the currency used on the website. -->
|
|
<xpath expr="//form[hasclass('oe_product_cart')]" position="replace">
|
|
<form action="/shop/cart/update" method="post"
|
|
class="card oe_product_cart"
|
|
t-att-data-publish="product.website_published and 'on' or 'off'"
|
|
itemscope="itemscope" itemtype="http://schema.org/Product">
|
|
<a class="o_product_link css_editable_mode_hidden"
|
|
t-att-href="product_href"/>
|
|
<div class="card-body p-1 oe_product_image">
|
|
<input type="hidden" name="csrf_token"
|
|
t-att-value="request.csrf_token()"/>
|
|
<a t-att-href="product_href" class="d-block h-100"
|
|
itemprop="url">
|
|
<t t-set="image_holder"
|
|
t-value="product._get_image_holder()"/>
|
|
<span t-field="image_holder.image_1920"
|
|
t-options="{'widget': 'image', 'preview_image': 'image_1024' if product_image_big else 'image_256', 'itemprop': 'image'}"
|
|
class="d-flex h-100 justify-content-center align-items-center"/>
|
|
</a>
|
|
</div>
|
|
<div class="card-body p-0 o_wsale_product_information">
|
|
<div class="p-2 o_wsale_product_information_text">
|
|
<h6 class="o_wsale_products_item_title mb-1">
|
|
<a class="text-primary text-decoration-none"
|
|
itemprop="name" t-att-href="product_href"
|
|
t-att-content="product.name"
|
|
t-field="product.name"/>
|
|
<a role="button"
|
|
t-if="not product.website_published"
|
|
t-att-href="product_href"
|
|
class="btn btn-sm btn-danger"
|
|
title="This product is unpublished.">Unpublished
|
|
</a>
|
|
</h6>
|
|
<div>
|
|
<a>
|
|
<span class="fa fa-folder-open"/>
|
|
<t t-esc="product.public_categ_ids.name"/>
|
|
</a>
|
|
</div>
|
|
<div>
|
|
<t t-set="rating_avg"
|
|
t-value="product.rating_avg"/>
|
|
<t t-set="rating_avg"
|
|
t-value="round(rating_avg * 100) / 100"/>
|
|
<t t-set="val_decimal"
|
|
t-value="round(rating_avg % 1, 1)"/>
|
|
<t t-set="val_integer" t-value="int(rating_avg)"/>
|
|
<t t-set="empty_star"
|
|
t-value="5 - (val_integer+1) if val_decimal else 5 - val_integer"/>
|
|
<div class="o_website_rating_static"
|
|
t-att-style="inline_mode and 'display:inline'"
|
|
t-att-title="rating_avg">
|
|
<t t-foreach="range(0, val_integer)"
|
|
t-as="num">
|
|
<i class="fa fa-star"
|
|
style="font-size:18px;" role="img"/>
|
|
</t>
|
|
<t t-if="val_decimal">
|
|
<i class="fa fa-star-half-o"
|
|
style="font-size:18px;" role="img"/>
|
|
</t>
|
|
<t t-foreach="range(0, empty_star)" t-as="num">
|
|
<i class="fa fa-star text-black-25"
|
|
style="font-size:18px;" role="img"/>
|
|
</t>
|
|
</div>
|
|
</div>
|
|
<div class="product_price mb-1" itemprop="offers"
|
|
itemscope="itemscope"
|
|
itemtype="http://schema.org/Offer">
|
|
<span class="h5" t-if="combination_info['price']"
|
|
t-esc="combination_info['price']"
|
|
t-options="{'widget': 'monetary', 'display_currency': website.currency_id}"/>
|
|
<del t-attf-class="text-danger ml-1 h6 {{'' if combination_info['has_discounted_price'] else 'd-none'}}"
|
|
style="white-space: nowrap;"
|
|
t-esc="combination_info['list_price']"
|
|
t-options="{'widget': 'monetary', 'display_currency': website.currency_id}"/>
|
|
<span itemprop="price" style="display:none;"
|
|
t-esc="combination_info['price']"/>
|
|
<span itemprop="priceCurrency"
|
|
style="display:none;"
|
|
t-esc="website.currency_id.name"/>
|
|
</div>
|
|
</div>
|
|
<div class="o_wsale_product_btn pl-2"/>
|
|
</div>
|
|
<t t-set="bg_color"
|
|
t-value="td_product['ribbon']['bg_color'] or ''"/>
|
|
<t t-set="text_color"
|
|
t-value="td_product['ribbon']['text_color']"/>
|
|
<t t-set="bg_class"
|
|
t-value="td_product['ribbon']['html_class']"/>
|
|
<span t-attf-class="o_ribbon #{bg_class}"
|
|
t-attf-style="#{text_color and ('color: %s; ' % text_color)}#{bg_color and 'background-color:' + bg_color}"
|
|
t-out="td_product['ribbon']['html'] or ''"/>
|
|
</form>
|
|
</xpath>
|
|
</template>
|
|
<template id="classic_store_products" name="Classic Store Products"
|
|
inherit_id="website_sale.products">
|
|
<!-- The template has several features for displaying products in a store. It includes a breadcrumb,
|
|
a filter menu, a search results message, and an option to customize the header for each category.
|
|
It also has a grid table for displaying the products. The product items are included through a call
|
|
to the website_sale.products_item template. -->
|
|
<!-- If no products are defined, the template displays a message informing the user that no products
|
|
are defined, and if a search query is performed and no results are found, a message with the search
|
|
query is displayed. -->
|
|
<xpath expr="//div[@id='products_grid']" position="replace">
|
|
<div id="products_grid"
|
|
t-attf-class="col #{'o_wsale_layout_list' if layout_mode == 'list' else ''}">
|
|
<t t-call="website_sale.products_breadcrumb">
|
|
<t t-set="_classes" t-valuef="w-100"/>
|
|
</t>
|
|
<div class="products_header form-inline flex-md-nowrap justify-content-end mb-4 ">
|
|
<t t-call="website_sale.pricelist_list">
|
|
<t t-set="_classes" t-valuef="ml-3 mb-2"/>
|
|
</t>
|
|
</div>
|
|
<div t-if="original_search and bins"
|
|
class="alert alert-warning mt8">
|
|
No results found for '<span t-esc="original_search"/>'.
|
|
Showing results for '<span t-esc="search"/>'.
|
|
</div>
|
|
<t t-if="category">
|
|
<t t-set='editor_msg'>Drag building blocks here to
|
|
customize
|
|
the header for "<t t-esc='category.name'/>" category.
|
|
</t>
|
|
<div class="mb16" id="category_header"
|
|
t-att-data-editor-message="editor_msg"
|
|
t-field="category.website_description"/>
|
|
</t>
|
|
<div t-if="bins" class="o_wsale_products_grid_table_wrapper">
|
|
<table class="table table-borderless m-0"
|
|
t-att-data-ppg="ppg" t-att-data-ppr="ppr">
|
|
<colgroup t-ignore="true">
|
|
<!-- Force the number of columns (useful when only one row of (x < ppr) products) -->
|
|
<col t-foreach="ppr" t-as="p"/>
|
|
</colgroup>
|
|
<tbody>
|
|
<tr t-foreach="bins" t-as="tr_product">
|
|
<t t-foreach="tr_product" t-as="td_product">
|
|
<t t-if="td_product">
|
|
<t t-set="product"
|
|
t-value="td_product['product']"/>
|
|
<!-- We use t-attf-class here to allow easier customization -->
|
|
<td t-att-colspan="td_product['x'] != 1 and td_product['x']"
|
|
t-att-rowspan="td_product['y'] != 1 and td_product['y']"
|
|
t-attf-class="oe_product"
|
|
t-att-data-ribbon-id="td_product['ribbon'].id">
|
|
<div t-attf-class="o_wsale_product_grid_wrapper o_wsale_product_grid_wrapper_#{td_product['x']}_#{td_product['y']}">
|
|
<t t-call="website_sale.products_item">
|
|
<t t-set="product_image_big"
|
|
t-value="td_product['x'] + td_product['y'] > 2"/>
|
|
</t>
|
|
</div>
|
|
</td>
|
|
</t>
|
|
<td t-else=""/>
|
|
</t>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
<t t-else="">
|
|
<div class="text-center text-muted mt128 mb256">
|
|
<t t-if="not search">
|
|
<h3 class="mt8">No product defined</h3>
|
|
<p t-if="category">No product defined in category "
|
|
<strong t-esc="category.display_name"/>".
|
|
</p>
|
|
</t>
|
|
<t t-else="">
|
|
<h3 class="mt8">No results</h3>
|
|
<p>No results for "<strong t-esc='search'/>"
|
|
<t t-if="category">in category "<strong
|
|
t-esc="category.display_name"/>"
|
|
</t>
|
|
</p>
|
|
</t>
|
|
<p t-ignore="true"
|
|
groups="sales_team.group_sale_manager">Click <i>
|
|
'New'
|
|
</i> in the top-right corner to create your first
|
|
product.
|
|
</p>
|
|
</div>
|
|
</t>
|
|
<div class="products_pager form-inline justify-content-center py-3">
|
|
<t t-call="website.pager"/>
|
|
</div>
|
|
</div>
|
|
</xpath>
|
|
</template>
|
|
<template id="sort" inherit_id="website_sale.products"
|
|
customize_show="True"
|
|
name="Show Sort by">
|
|
<!-- Adds a "Sort By" dropdown menu to the product listing page, allowing users
|
|
to select different sorting options such as price, newest arrivals,
|
|
and name to customize the order in which products are displayed. -->
|
|
<xpath expr="//div[hasclass('products_header')]/t[@t-call='website_sale.pricelist_list']"
|
|
position="after">
|
|
<t t-set="list_price_asc_label">Price - Low to High</t>
|
|
<t t-set="list_price_desc_label">Price - High to Low</t>
|
|
<t t-set="newest_arrivals_desc_label">Newest arrivals</t>
|
|
<t t-set="name_asc_label">Name</t>
|
|
<t t-set="website_sale_sortable" t-value="[
|
|
(list_price_asc_label, 'list_price asc'),
|
|
(list_price_desc_label, 'list_price desc'),
|
|
(newest_arrivals_desc_label, 'create_date desc'),
|
|
(name_asc_label, 'name asc')
|
|
]"/>
|
|
<t t-set="website_sale_sortable_current"
|
|
t-value="[sort for sort in website_sale_sortable if sort[1]==request.params.get('order', '')]"/>
|
|
<div class="o_sortby_dropdown dropdown dropdown_sorty_by ml-3 pb-2">
|
|
<span class="d-none d-lg-inline font-weight-bold text-muted">
|
|
Sort By:
|
|
</span>
|
|
<a role="button" href="#"
|
|
class="dropdown-toggle btn btn-light border-0 px-0 text-muted align-baseline"
|
|
data-toggle="dropdown">
|
|
<span class="d-none d-lg-inline">
|
|
<t t-if='website_sale_sortable_current'>
|
|
<t t-esc="website_sale_sortable_current[0][0]"/>
|
|
</t>
|
|
<t t-else='1'>
|
|
Featured
|
|
</t>
|
|
</span>
|
|
<i class="fa fa-sort-amount-asc d-lg-none"/>
|
|
</a>
|
|
<div class="dropdown-menu dropdown-menu-right" role="menu">
|
|
<t t-foreach="website_sale_sortable" t-as="sortby">
|
|
<a role="menuitem" rel="noindex,nofollow"
|
|
t-att-href="keep('/shop', order=sortby[1])"
|
|
class="dropdown-item">
|
|
<span t-out="sortby[0]"/>
|
|
</a>
|
|
</t>
|
|
</div>
|
|
</div>
|
|
</xpath>
|
|
</template>
|
|
<template id="classic_store_topbar" name="Classic Store Topbar"
|
|
inherit_id="website_sale.products">
|
|
<!-- The template adds a search bar to the website's top bar. -->
|
|
<!-- The search bar is enclosed in a section tag with the class "banner_search", and it contains
|
|
a form with a search input field and a search button. The input field has the name "search"
|
|
and the class "search-query form-control oe_search_box", and it has several data attributes that
|
|
control how the search results are displayed. The search button has the class "btn btn-primary oe_search_button"
|
|
and the text "Search Now". -->
|
|
<xpath expr="//div[hasclass('container')]" position="before">
|
|
<section class="banner_search">
|
|
<div class="container">
|
|
<div class="row">
|
|
<div class="col-md-12">
|
|
<!-- Advance Search -->
|
|
<div class="advance-search">
|
|
<form>
|
|
<div class="form-row d-flex justify-content-center">
|
|
<div class="form-group col-md-9">
|
|
<input type="search" name="search"
|
|
class="search-query form-control oe_search_box"
|
|
data-limit="5"
|
|
data-display-description="true"
|
|
data-display-price="true"
|
|
data-display-image="true"
|
|
data-oe-model="ir.ui.view"
|
|
data-oe-id="3225"
|
|
data-oe-field="arch"
|
|
data-oe-xpath="/data/xpath[3]/form/t[1]/div[1]/input[1]"
|
|
placeholder="Search..."
|
|
value=""
|
|
autocomplete="off"/>
|
|
</div>
|
|
<div class="form-group col-md-2 text-left">
|
|
<button type="submit"
|
|
class="btn btn-primary oe_search_button"
|
|
aria-label="Search"
|
|
title="Search">
|
|
<a>Search Now</a>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
</xpath>
|
|
</template>
|
|
<template id="categories_recursive" name="Category list">
|
|
<!-- The template is used for displaying a recursive category list on a web page.
|
|
It includes a link for each category and the number of subcategories it contains. -->
|
|
<li>
|
|
<a t-attf-href="/shop/category/#{slug(c)}"
|
|
t-attf-class="nav-link #{'active' if c.id == category.id else ''}"
|
|
style="font-size: 18px; display: flex !important;justify-content: space-between !important; color: #565656; text-decoration: none;">
|
|
<t t-esc="c.name"/>
|
|
<span>
|
|
<t t-esc="c.category_count"/>
|
|
</span>
|
|
</a>
|
|
</li>
|
|
<ul t-if="c.child_id"
|
|
class="nav nav-pills flex-column nav-hierarchy pl-3">
|
|
<t t-foreach="c.child_id" t-as="c">
|
|
<t t-if="not search or c.id in search_categories_ids">
|
|
<t t-call="theme_classic_store.categories_recursive"/>
|
|
</t>
|
|
</t>
|
|
</ul>
|
|
</template>
|
|
<template id="classic_shop_categories" name="Classic Store Categories"
|
|
inherit_id="website_sale.products_categories"
|
|
customize_show="True" priority="1" active="True"
|
|
t-name="theme_classic_store">
|
|
<xpath expr="//div[@id='wsale_products_categories_collapse']"
|
|
position="replace">
|
|
<div class="col">
|
|
<div class="product_sidebar">
|
|
<div class="wrapper">
|
|
<div class="widget_header">
|
|
<hr/>
|
|
<a t-att-href="keep('/shop', category=0)"
|
|
t-attf-class="nav-link #{'' if category else 'active'} o_not_editable">
|
|
<h4 style="color:black; font-size: 20px; display: inline;">
|
|
All Category
|
|
</h4>
|
|
</a>
|
|
<hr/>
|
|
<t t-foreach="categories" t-as="c">
|
|
<div class="category_item">
|
|
<a t-att-href="keep('/shop', category=c.id)"
|
|
t-attf-class="nav-link #{'' if c.id == category else 'active'} o_not_editable">
|
|
<h4 style="color:black; font-size: 20px; display: inline;">
|
|
<t t-esc="c.name"/>
|
|
</h4>
|
|
<t t-if="c.child_id">
|
|
<span class="show_div">
|
|
<i class="fa fa-angle-down dropdown-arrow"/>
|
|
</span>
|
|
</t>
|
|
<span class="category_count">(<t
|
|
t-esc="c.category_count"/>)
|
|
</span>
|
|
</a>
|
|
<div class="subcategories"
|
|
t-if="c.child_id"
|
|
hidden="hidden" id="show_div">
|
|
<t t-foreach="c.child_id"
|
|
t-as="subcat">
|
|
<a t-att-href="keep('/shop', category=subcat.id)"
|
|
t-attf-class="nav-link #{'' if subcat.id == category else 'active'} o_not_editable">
|
|
<p>
|
|
<t t-esc="subcat.name"/>
|
|
<span class="subcategory_count">
|
|
(
|
|
<t t-esc="subcat.category_count"/>
|
|
)
|
|
</span>
|
|
</p>
|
|
</a>
|
|
</t>
|
|
</div>
|
|
</div>
|
|
</t>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</xpath>
|
|
</template>
|
|
<template id="classic_store_attributes" name="Classic Store Attributes"
|
|
inherit_id="website_sale.products_attributes"
|
|
customize_show="True" priority="20" active="True">
|
|
<!-- The template replaces a div with id "wsale_products_attributes_collapse" with a new div that contains
|
|
a form for selecting product attributes. The attributes are displayed as a list of options or checkboxes,
|
|
depending on their display type. The selected attributes are sent as parameters in a GET request when the
|
|
form is submitted. -->
|
|
<xpath expr="//div[@id='wsale_products_attributes_collapse']"
|
|
position="replace">
|
|
<div class="product_sidebar">
|
|
<div class="wrapper">
|
|
<div class="widget_header">
|
|
<form class="js_attributes mb-2" method="get">
|
|
<input t-if="category" type="hidden"
|
|
name="category"
|
|
t-att-value="category.id"/>
|
|
<input type="hidden" name="search"
|
|
t-att-value="search"/>
|
|
<ul class="nav nav-pills flex-column">
|
|
<t t-foreach="attributes" t-as="a">
|
|
<li t-if="a.value_ids and len(a.value_ids) > 1"
|
|
class="nav-item">
|
|
<div class="theme_classic_header">
|
|
<hr/>
|
|
<h4>
|
|
<t t-esc="a.name"/>
|
|
</h4>
|
|
<hr/>
|
|
</div>
|
|
<t t-if="a.display_type == 'select'">
|
|
<select class="form-control"
|
|
name="attrib">
|
|
<option value=""/>
|
|
<t t-foreach="a.value_ids"
|
|
t-as="v">
|
|
<option t-att-value="'%s-%s' % (a.id,v.id)"
|
|
t-esc="v.name"
|
|
t-att-selected="v.id in attrib_set"/>
|
|
</t>
|
|
</select>
|
|
</t>
|
|
<t t-if="a.display_type == 'radio'">
|
|
<ul class="nav nav-pills flex-column">
|
|
<t t-foreach="a.value_ids"
|
|
t-as="v">
|
|
<li class="nav-item">
|
|
<label style="padding: 0.25rem 0rem; margin: 0"
|
|
t-attf-class="nav-link#{' active' if v.id in attrib_set else ''}">
|
|
<input type="checkbox"
|
|
name="attrib"
|
|
t-att-value="'%s-%s' % (a.id,v.id)"
|
|
t-att-checked="'checked' if v.id in attrib_set else None"/>
|
|
<span style="font-weight: normal"
|
|
t-field="v.name"/>
|
|
</label>
|
|
</li>
|
|
</t>
|
|
</ul>
|
|
</t>
|
|
<t t-if="a.display_type == 'color'">
|
|
<t t-foreach="a.value_ids"
|
|
t-as="v">
|
|
<label t-attf-style="background-color:#{v.html_color or v.name}"
|
|
t-attf-class="css_attribute_color #{'active' if v.id in attrib_set else ''}">
|
|
<input type="checkbox"
|
|
name="attrib"
|
|
t-att-value="'%s-%s' % (a.id,v.id)"
|
|
t-att-checked="'checked' if v.id in attrib_set else None"
|
|
t-att-title="v.name"/>
|
|
</label>
|
|
</t>
|
|
</t>
|
|
</li>
|
|
</t>
|
|
</ul>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</xpath>
|
|
</template>
|
|
</odoo>
|
|
|