feat: (wip) Toggle Views
- Auto Height on Cards - Title with ellipses on length exceed - Changed namepaces - Moved product card rendering to JS - Added Image and List View Toggling buttons - Kept basic filters rendering just as before
This commit is contained in:
parent
f9929ed8a6
commit
48b3ce82b9
@ -22,7 +22,7 @@ class ProductQuery:
|
||||
def __init__(self):
|
||||
self.settings = frappe.get_doc("E Commerce Settings")
|
||||
self.page_length = self.settings.products_per_page or 20
|
||||
self.fields = ['wi.name', 'wi.item_name', 'wi.item_code', 'wi.website_image', 'wi.variant_of',
|
||||
self.fields = ['wi.web_item_name', 'wi.name', 'wi.item_name', 'wi.item_code', 'wi.website_image', 'wi.variant_of',
|
||||
'wi.has_variants', 'wi.item_group', 'wi.image', 'wi.web_long_description', 'wi.description',
|
||||
'wi.route', 'wi.website_warehouse']
|
||||
self.conditions = ""
|
||||
|
124
erpnext/e_commerce/product_view.js
Normal file
124
erpnext/e_commerce/product_view.js
Normal file
@ -0,0 +1,124 @@
|
||||
erpnext.ProductView = class {
|
||||
/* Options: View Type */
|
||||
constructor(options) {
|
||||
Object.assign(this, options);
|
||||
this.render_view_toggler();
|
||||
this.get_item_filter_data();
|
||||
this.render_list_view();
|
||||
this.render_grid_view();
|
||||
}
|
||||
|
||||
render_view_toggler() {
|
||||
["btn-list-view", "btn-grid-view"].forEach(view => {
|
||||
let icon = view === "btn-list-view" ? "list" : "image-view";
|
||||
this.products_section.append(`
|
||||
<div class="form-group mb-0" id="toggle-view">
|
||||
<button id="${icon}" class="btn ${view} mr-2">
|
||||
<span>
|
||||
<svg class="icon icon-md">
|
||||
<use href="#icon-${icon}"></use>
|
||||
</svg>
|
||||
</span>
|
||||
</button>
|
||||
</div>`);
|
||||
});
|
||||
|
||||
$("#list").click(function() {
|
||||
let $btn = $(this);
|
||||
$btn.removeClass('btn-primary');
|
||||
$btn.addClass('btn-primary');
|
||||
$(".btn-grid-view").removeClass('btn-primary');
|
||||
})
|
||||
|
||||
$("#image-view").click(function() {
|
||||
let $btn = $(this);
|
||||
$btn.removeClass('btn-primary');
|
||||
$btn.addClass('btn-primary');
|
||||
$(".btn-list-view").removeClass('btn-primary');
|
||||
});
|
||||
|
||||
this.products_area = this.products_section.append(`
|
||||
<br><br>
|
||||
<div id="products-area" class="row products-list mt-4"></div>
|
||||
`);
|
||||
}
|
||||
|
||||
get_item_filter_data() {
|
||||
// Get Items and Discount Filters to render
|
||||
let me = this;
|
||||
const filters = frappe.utils.get_query_params();
|
||||
let {field_filters, attribute_filters} = filters;
|
||||
|
||||
field_filters = field_filters ? JSON.parse(field_filters) : {};
|
||||
attribute_filters = attribute_filters ? JSON.parse(attribute_filters) : {};
|
||||
|
||||
frappe.call({
|
||||
method: 'erpnext.www.all-products.index.get_product_filter_data',
|
||||
args: {
|
||||
field_filters: field_filters,
|
||||
attribute_filters: attribute_filters,
|
||||
item_group: me.item_group
|
||||
},
|
||||
callback: function(result) {
|
||||
if (!result.exc) {
|
||||
me.render_filters(result.message[1]);
|
||||
|
||||
// Append pre-rendered products
|
||||
// TODO: get products as is and style via js
|
||||
me.products = result.message;
|
||||
$("#products-area").append(result.message[0]);
|
||||
|
||||
} else {
|
||||
$("#products-area").append(`
|
||||
<div class="d-flex justify-content-center p-3 text-muted">
|
||||
${__('No products found')}
|
||||
</div>`);
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
render_filters(filter_data) {
|
||||
this.get_discount_filter_html(filter_data.discount_filters);
|
||||
}
|
||||
|
||||
get_discount_filter_html(filter_data) {
|
||||
if (filter_data) {
|
||||
$("#product-filters").append(`
|
||||
<div id="discount-filters" class="mb-4 filter-block pb-5">
|
||||
<div class="filter-label mb-3">${__("Discounts")}</div>
|
||||
</div>
|
||||
`);
|
||||
|
||||
let html = `<div class="filter-options">`;
|
||||
filter_data.forEach(filter => {
|
||||
html += `
|
||||
<div class="checkbox">
|
||||
<label data-value="${filter[0]}">
|
||||
<input type="radio" class="product-filter discount-filter"
|
||||
name="discount" id="${filter[0]}"
|
||||
data-filter-name="discount" data-filter-value="${filter[0]}"
|
||||
>
|
||||
<span class="label-area" for="${filter[0]}">
|
||||
${filter[1]}
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
`;
|
||||
});
|
||||
html += `</div>`;
|
||||
|
||||
$("#discount-filters").append(html);
|
||||
}
|
||||
}
|
||||
|
||||
render_list_view() {
|
||||
// loop over data and add list html to it
|
||||
}
|
||||
|
||||
render_grid_view() {
|
||||
// loop over data and add grid html to it
|
||||
}
|
||||
|
||||
}
|
@ -66,5 +66,8 @@
|
||||
"js/hierarchy-chart.min.js": [
|
||||
"public/js/hierarchy_chart/hierarchy_chart_desktop.js",
|
||||
"public/js/hierarchy_chart/hierarchy_chart_mobile.js"
|
||||
],
|
||||
"js/e-commerce.min.js": [
|
||||
"e_commerce/product_view.js"
|
||||
]
|
||||
}
|
||||
|
@ -2,8 +2,8 @@
|
||||
// License: GNU General Public License v3. See license.txt
|
||||
|
||||
// shopping cart
|
||||
frappe.provide("erpnext.shopping_cart");
|
||||
var shopping_cart = erpnext.shopping_cart;
|
||||
frappe.provide("e_commerce.shopping_cart");
|
||||
var shopping_cart = e_commerce.shopping_cart;
|
||||
|
||||
var getParams = function (url) {
|
||||
var params = [];
|
||||
@ -214,7 +214,7 @@ $.extend(shopping_cart, {
|
||||
this.animate_add_to_cart($btn);
|
||||
|
||||
const item_code = $btn.data('item-code');
|
||||
erpnext.shopping_cart.update_cart({
|
||||
e_commerce.shopping_cart.update_cart({
|
||||
item_code,
|
||||
qty: 1
|
||||
});
|
||||
|
@ -1,8 +1,8 @@
|
||||
frappe.provide("erpnext.wishlist");
|
||||
var wishlist = erpnext.wishlist;
|
||||
frappe.provide("e_commerce.wishlist");
|
||||
var wishlist = e_commerce.wishlist;
|
||||
|
||||
frappe.provide("erpnext.shopping_cart");
|
||||
var shopping_cart = erpnext.shopping_cart;
|
||||
frappe.provide("e_commerce.shopping_cart");
|
||||
var shopping_cart = e_commerce.shopping_cart;
|
||||
|
||||
$.extend(wishlist, {
|
||||
set_wishlist_count: function() {
|
||||
@ -79,7 +79,7 @@ $.extend(wishlist, {
|
||||
let me = this;
|
||||
|
||||
let success_action = function() {
|
||||
erpnext.wishlist.set_wishlist_count();
|
||||
e_commerce.wishlist.set_wishlist_count();
|
||||
};
|
||||
|
||||
if ($wish_icon.hasClass('wished')) {
|
||||
|
@ -68,7 +68,6 @@ body.product-page {
|
||||
|
||||
.item-card-group-section {
|
||||
.card {
|
||||
height: 400px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
@ -779,3 +778,7 @@ body.product-page {
|
||||
padding: 6px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
#toggle-view {
|
||||
float: right;
|
||||
}
|
||||
|
@ -65,37 +65,14 @@ class ItemGroup(NestedSet, WebsiteGenerator):
|
||||
self.delete_child_item_groups_key()
|
||||
|
||||
def get_context(self, context):
|
||||
context.show_search=True
|
||||
context.show_search = True
|
||||
context.page_length = cint(frappe.db.get_single_value('E Commerce Settings', 'products_per_page')) or 6
|
||||
context.e_commerce_settings = frappe.get_cached_doc('E Commerce Settings', 'E Commerce Settings')
|
||||
context.search_link = '/product_search'
|
||||
|
||||
if frappe.form_dict:
|
||||
search = frappe.form_dict.search
|
||||
field_filters = frappe.parse_json(frappe.form_dict.field_filters)
|
||||
attribute_filters = frappe.parse_json(frappe.form_dict.attribute_filters)
|
||||
start = frappe.parse_json(frappe.form_dict.start)
|
||||
else:
|
||||
search = None
|
||||
attribute_filters = None
|
||||
field_filters = {}
|
||||
start = 0
|
||||
|
||||
if not field_filters:
|
||||
field_filters = {}
|
||||
|
||||
# Ensure the query remains within current item group
|
||||
field_filters['item_group'] = self.name
|
||||
|
||||
engine = ProductQuery()
|
||||
context.items, discounts = engine.query(attribute_filters, field_filters, search, start)
|
||||
|
||||
filter_engine = ProductFiltersBuilder(self.name)
|
||||
|
||||
context.field_filters = filter_engine.get_field_filters()
|
||||
context.attribute_filters = filter_engine.get_attribute_filters()
|
||||
if discounts:
|
||||
context.discount_filters = filter_engine.get_discount_filters(discounts)
|
||||
|
||||
context.update({
|
||||
"parents": get_parent_item_groups(self.parent_item_group),
|
||||
@ -124,6 +101,7 @@ class ItemGroup(NestedSet, WebsiteGenerator):
|
||||
|
||||
context.no_breadcrumbs = False
|
||||
context.title = self.website_title or self.name
|
||||
context.name = self.name
|
||||
|
||||
return context
|
||||
|
||||
|
@ -143,7 +143,7 @@
|
||||
const $btn = $(e.currentTarget);
|
||||
$btn.prop('disabled', true);
|
||||
const item_code = $btn.data('item-code');
|
||||
erpnext.shopping_cart.update_cart({
|
||||
e_commerce.shopping_cart.update_cart({
|
||||
item_code,
|
||||
qty: 1,
|
||||
callback(r) {
|
||||
@ -170,11 +170,11 @@
|
||||
};
|
||||
let success_action = function() {
|
||||
$btn.prop('disabled', false);
|
||||
erpnext.wishlist.set_wishlist_count();
|
||||
e_commerce.wishlist.set_wishlist_count();
|
||||
$('.btn-add-to-wishlist, .btn-view-in-wishlist').toggleClass('hidden');
|
||||
|
||||
};
|
||||
erpnext.wishlist.add_remove_from_wishlist("add", args, success_action, failure_action);
|
||||
e_commerce.wishlist.add_remove_from_wishlist("add", args, success_action, failure_action);
|
||||
});
|
||||
|
||||
$('.page_content').on('click', '.offer-details', (e) => {
|
||||
|
@ -247,7 +247,7 @@ class ItemConfigure {
|
||||
const additional_notes = Object.keys(this.range_values || {}).map(attribute => {
|
||||
return `${attribute}: ${this.range_values[attribute]}`;
|
||||
}).join('\n');
|
||||
erpnext.shopping_cart.update_cart({
|
||||
e_commerce.shopping_cart.update_cart({
|
||||
item_code,
|
||||
additional_notes,
|
||||
qty: 1
|
||||
|
@ -16,7 +16,8 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block page_content %}
|
||||
<div class="item-group-content" itemscope itemtype="http://schema.org/Product" data-item-group="{{ name }}">
|
||||
<div class="item-group-content" itemscope itemtype="http://schema.org/Product"
|
||||
data-item-group="{{ name }}">
|
||||
<div class="item-group-slideshow">
|
||||
{% if slideshow %}<!-- slideshow -->
|
||||
{{ web_block(
|
||||
@ -33,7 +34,7 @@
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-12 order-2 col-md-9 order-md-2 item-card-group-section">
|
||||
<div id="product-listing" class="col-12 order-2 col-md-9 order-md-2 item-card-group-section">
|
||||
{% if sub_categories %}
|
||||
<div class="sub-category-container">
|
||||
<div class="heading"> {{ _('Sub Categories') }} </div>
|
||||
@ -48,15 +49,9 @@
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="row products-list">
|
||||
{% if items %}
|
||||
{% for item in items %}
|
||||
{% include "erpnext/www/all-products/item_row.html" %}
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
{% include "erpnext/www/all-products/not_found.html" %}
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<!-- Products Rendered in all-products/index.js-->
|
||||
|
||||
</div>
|
||||
<div class="col-12 order-1 col-md-3 order-md-1">
|
||||
<div class="collapse d-md-block mr-4 filters-section" id="product-filters">
|
||||
@ -70,10 +65,6 @@
|
||||
<!-- attribute filters -->
|
||||
{{ attribute_filter_section(attribute_filters) }}
|
||||
|
||||
<!-- discount filters -->
|
||||
{% if discount_filters %}
|
||||
{{ discount_range_filters(discount_filters) }}
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<script>
|
||||
|
@ -4,8 +4,8 @@
|
||||
// js inside blog page
|
||||
|
||||
// shopping cart
|
||||
frappe.provide("erpnext.shopping_cart");
|
||||
var shopping_cart = erpnext.shopping_cart;
|
||||
frappe.provide("e_commerce.shopping_cart");
|
||||
var shopping_cart = e_commerce.shopping_cart;
|
||||
|
||||
$.extend(shopping_cart, {
|
||||
show_error: function(title, text) {
|
||||
|
@ -66,7 +66,8 @@
|
||||
'align-items-start': align == 'Left',
|
||||
}) -%}
|
||||
{%- set col_size = 3 if is_full_width else 4 -%}
|
||||
{%- set title = item.item_name or item.item_code -%}
|
||||
{%- set title = item.web_item_name or item.item_name or item.item_code -%}
|
||||
{%- set title = title[:50] + "..." if title|len > 50 else title -%}
|
||||
{%- set image = item.website_image or item.image -%}
|
||||
{%- set description = item.website_description or item.description-%}
|
||||
|
||||
@ -120,11 +121,13 @@
|
||||
<div class="card-body {{ align_class }}" style="width:100%">
|
||||
<div style="margin-top: 16px; display: flex;">
|
||||
<a href="/{{ item.route or '#' }}">
|
||||
<div class="product-title">{{ title or '' }}</div>
|
||||
<div class="product-title">
|
||||
{{ title or '' }}
|
||||
{% if item.in_stock %}
|
||||
<span class="indicator {{ item.in_stock }} card-indicator"></span>
|
||||
{% endif %}
|
||||
</div>
|
||||
</a>
|
||||
{% if item.in_stock %}
|
||||
<span class="indicator {{ item.in_stock }} card-indicator"></span>
|
||||
{% endif %}
|
||||
{% if not item.has_variants and settings.enable_wishlist %}
|
||||
<div class="like-action"
|
||||
data-item-code="{{ item.item_code }}"
|
||||
@ -363,7 +366,7 @@
|
||||
<div class="filter-options">
|
||||
{% for attr_value in attribute.item_attribute_values %}
|
||||
<div class="checkbox">
|
||||
<label data-value="{{ value }}">
|
||||
<label data-value="{{ attr_value }}">
|
||||
<input type="checkbox"
|
||||
class="product-filter attribute-filter"
|
||||
id="{{attr_value.name}}"
|
||||
@ -381,24 +384,3 @@
|
||||
</div>
|
||||
{% endfor %}
|
||||
{%- endmacro -%}
|
||||
|
||||
{%- macro discount_range_filters(filters)-%}
|
||||
<div class="mb-4 filter-block pb-5">
|
||||
<div class="filter-label mb-3">{{ _("Discounts") }}</div>
|
||||
<div class="filter-options">
|
||||
{% for entry in filters %}
|
||||
<div class="checkbox">
|
||||
<label data-value="{{ entry[0] }}">
|
||||
<input type="radio" class="product-filter discount-filter"
|
||||
name="discount" id="{{ entry[0] }}"
|
||||
data-filter-name="discount" data-filter-value="{{ entry[0] }}"
|
||||
>
|
||||
<span class="label-area" for="{{ entry[0] }}">
|
||||
{{ entry[1] }}
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{%- endmacro -%}
|
||||
|
@ -7,7 +7,8 @@
|
||||
{% endblock header %}
|
||||
|
||||
{% block page_content %}
|
||||
<div class="row" style="display: none;">
|
||||
<!-- Old Search -->
|
||||
<!-- <div class="row" style="display: none;">
|
||||
<div class="col-8">
|
||||
<div class="input-group input-group-sm mb-3">
|
||||
<input type="search" class="form-control" placeholder="{{_('Search')}}"
|
||||
@ -29,22 +30,16 @@
|
||||
{{ _('Toggle Filters') }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div> -->
|
||||
|
||||
<!-- Items section -->
|
||||
<div class="row">
|
||||
<div class="col-12 order-2 col-md-9 order-md-2 item-card-group-section">
|
||||
<div class="row products-list">
|
||||
{% if items %}
|
||||
{% for item in items %}
|
||||
{% include "erpnext/www/all-products/item_row.html" %}
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
{% include "erpnext/www/all-products/not_found.html" %}
|
||||
{% endif %}
|
||||
</div>
|
||||
<div id="product-listing" class="col-12 order-2 col-md-9 order-md-2 item-card-group-section">
|
||||
<!-- Rendered via JS -->
|
||||
</div>
|
||||
<div class="col-12 order-1 col-md-3 order-md-1">
|
||||
|
||||
<!-- Filters Section -->
|
||||
<div class="col-12 order-1 col-md-3 order-md-1">
|
||||
{% if frappe.form_dict.start or frappe.form_dict.field_filters or frappe.form_dict.attribute_filters or frappe.form_dict.search %}
|
||||
|
||||
|
||||
@ -64,11 +59,6 @@
|
||||
{% if attribute_filters %}
|
||||
{{ attribute_filter_section(attribute_filters) }}
|
||||
{% endif %}
|
||||
|
||||
<!-- discount filters -->
|
||||
{% if discount_filters %}
|
||||
{{ discount_range_filters(discount_filters) }}
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<script>
|
||||
@ -91,7 +81,10 @@
|
||||
</script>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row product-paging-area mt-5">
|
||||
|
||||
<!-- TODO -->
|
||||
<!-- Paging Section -->
|
||||
<!-- <div class="row product-paging-area mt-5">
|
||||
<div class="col-3">
|
||||
</div>
|
||||
<div class="col-9 text-right">
|
||||
@ -102,7 +95,7 @@
|
||||
<button class="btn btn-default btn-next" data-start="{{ frappe.form_dict.start|int + page_length }}">{{ _("Next") }}</button>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div> -->
|
||||
|
||||
<script>
|
||||
frappe.ready(() => {
|
||||
|
@ -1,6 +1,17 @@
|
||||
$(() => {
|
||||
class ProductListing {
|
||||
constructor() {
|
||||
let is_item_group_page = $(".item-group-content").data("item-group");
|
||||
let item_group = is_item_group_page || null;
|
||||
|
||||
// Render Products
|
||||
frappe.require('assets/js/e-commerce.min.js', function() {
|
||||
new erpnext.ProductView({
|
||||
products_section: $('#product-listing'),
|
||||
item_group: item_group
|
||||
});
|
||||
});
|
||||
|
||||
this.bind_filters();
|
||||
this.bind_card_actions();
|
||||
this.bind_search();
|
||||
@ -77,8 +88,8 @@ $(() => {
|
||||
}
|
||||
|
||||
bind_card_actions() {
|
||||
erpnext.shopping_cart.bind_add_to_cart_action();
|
||||
erpnext.wishlist.bind_wishlist_action();
|
||||
e_commerce.shopping_cart.bind_add_to_cart_action();
|
||||
e_commerce.wishlist.bind_wishlist_action();
|
||||
}
|
||||
|
||||
bind_search() {
|
||||
|
@ -6,33 +6,55 @@ from erpnext.e_commerce.filters import ProductFiltersBuilder
|
||||
sitemap = 1
|
||||
|
||||
def get_context(context):
|
||||
# Add homepage as parent
|
||||
context.parents = [{"name": frappe._("Home"), "route":"/"}]
|
||||
|
||||
filter_engine = ProductFiltersBuilder()
|
||||
context.field_filters = filter_engine.get_field_filters()
|
||||
context.attribute_filters = filter_engine.get_attribute_filters()
|
||||
|
||||
context.page_length = cint(frappe.db.get_single_value('E Commerce Settings', 'products_per_page'))or 20
|
||||
|
||||
context.no_cache = 1
|
||||
|
||||
@frappe.whitelist(allow_guest=True)
|
||||
def get_product_filter_data():
|
||||
"""Get pre-rendered filtered products and discount filters on load."""
|
||||
if frappe.form_dict:
|
||||
search = frappe.form_dict.search
|
||||
field_filters = frappe.parse_json(frappe.form_dict.field_filters)
|
||||
attribute_filters = frappe.parse_json(frappe.form_dict.attribute_filters)
|
||||
start = cint(frappe.parse_json(frappe.form_dict.start))
|
||||
item_group = frappe.form_dict.item_group
|
||||
else:
|
||||
search = field_filters = attribute_filters = None
|
||||
search, attribute_filters, item_group = None, None, None
|
||||
field_filters = {}
|
||||
start = 0
|
||||
|
||||
if item_group:
|
||||
field_filters['item_group'] = item_group
|
||||
|
||||
engine = ProductQuery()
|
||||
context.items, discounts = engine.query(attribute_filters, field_filters, search, start)
|
||||
items, discounts = engine.query(attribute_filters, field_filters, search_term=search, start=start)
|
||||
|
||||
# Add homepage as parent
|
||||
context.parents = [{"name": frappe._("Home"), "route":"/"}]
|
||||
item_html = []
|
||||
for item in items:
|
||||
item_html.append(frappe.render_template('erpnext/www/all-products/item_row.html', {
|
||||
'item': item,
|
||||
'e_commerce_settings': engine.settings
|
||||
}))
|
||||
html = ''.join(item_html)
|
||||
|
||||
filter_engine = ProductFiltersBuilder()
|
||||
if not items:
|
||||
html = frappe.render_template('erpnext/www/all-products/not_found.html', {})
|
||||
|
||||
context.field_filters = filter_engine.get_field_filters()
|
||||
context.attribute_filters = filter_engine.get_attribute_filters()
|
||||
# discount filter data
|
||||
filters = {}
|
||||
if discounts:
|
||||
context.discount_filters = filter_engine.get_discount_filters(discounts)
|
||||
filter_engine = ProductFiltersBuilder()
|
||||
filters["discount_filters"] = filter_engine.get_discount_filters(discounts)
|
||||
|
||||
context.e_commerce_settings = engine.settings
|
||||
context.page_length = engine.settings.products_per_page or 20
|
||||
|
||||
context.no_cache = 1
|
||||
return html, filters
|
||||
|
||||
@frappe.whitelist(allow_guest=True)
|
||||
def get_products_html_for_website(field_filters=None, attribute_filters=None):
|
||||
@ -47,7 +69,7 @@ def get_products_html_for_website(field_filters=None, attribute_filters=None):
|
||||
for item in items:
|
||||
item_html.append(frappe.render_template('erpnext/www/all-products/item_row.html', {
|
||||
'item': item,
|
||||
'e_commerce_settings': None
|
||||
'e_commerce_settings': engine.settings
|
||||
}))
|
||||
html = ''.join(item_html)
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user