Hide b2b product for b2c customers in search - search

I am using sparklayer app for b2c/b2b hybrid shop. The feature of hiding b2b tagged products in the search bar from b2c customers is missing.
I just put a condition before the rendering of the product in search results grid. But now there are of course empty spaces in the grid. Any idea how not to have those spaces in the grid and hide a product with a tag?
{% if result.object_type == 'product' and result.tags contains 'b2b' %}
{% if customer.tags contains 'b2b' %}
{%- render 'product-item', product: result, show_labels: true, show_product_info: true, show_vendor: false -%}
{%endif%}
{% else %}
{%- render 'product-item', product: result, show_labels: true, show_product_info: true, show_vendor: false -%}
{%endif%}

Related

How to add entity extension in Shopware 6 App?

I want to query the categories of the product in the product listing of a Shopware app, so that I can query the customFields of all categories. Is this even possible with an app?
I have already tried via a navigation-page-loaded. And when I override the box-standard.html.twig and access the product, I can't access the categories there.
For each product i want the categories extensions
As the categories association is not loaded for products in the listing you have to fetch the categories using an app script.
As already noted, add the script to the navigation-page-loaded hook, i.e. in Resources/scripts/navigation-page-loaded/category-loader.twig:
{% set products = [] %}
{% if hook.page.cmsPage.type === 'product_list' %}
{% foreach hook.page.cmsPage.sections as section %}
{% foreach section.blocks as sectionBlock %}
{% if sectionBlock.type !== 'product-listing' %}
{% continue %}
{% endif %}
{% foreach sectionBlock.slots as slot %}
{% if slot.type !== 'product-listing' %}
{% continue %}
{% endif %}
{% foreach slot.data.listing.entities as product %}
{% set products = products|merge([product]) %}
{% endforeach %}
{% endforeach %}
{% endforeach %}
{% endforeach %}
{% endif %}
{% set categoryIds = products|reduce((carry, v) => carry|merge(v.categoryIds), []) %}
{% if categoryIds %}
{% set categories = services.repository.search('category', {'ids': categoryIds}) %}
{% foreach products as product %}
{% do product.addArrayExtension('myCategories', {
'categories': categories.entities.getList(product.categoryIds),
}) %}
{% endforeach %}
{% endif %}
Where we first extract all the products, than load the categories of all products at once, and than assign the categories back to the products.
Note that for reading the category entity you need the correct permission, i.e. in the manifest.xml add:
<permissions>
<read>category</read>
<read>category_translation</read>
</permissions>
Now you should be able to access in the box-standard.html.twig template the categories using product.extensions.myCategories.categories.
If I understand your issue correctly, you are trying to access a product's category's custom fields in some piece of storefront logic (like a Twig template).
The way I see it, you would have to add a script that would enable you to query the repository for the categories and their custom fields. The issue is, a SalesChannelProductEntity will not contain the information about all its categories (only the SeoCategory), so you might need to first query the product_category repository.
Generally, it is going to be complicated but it should be doable.

How can I create a multi-page blog post in Jekyll?

I am trying to re-create this Wordpress blog post on Jekyll. The post is made up of images with descriptions, with 5 or 6 such images per page.
I created the page with a Wordpress pagination plugin. Jekyll uses a paginate plugin to paginate blog menus, but it seems I cannot re-use that for a single blog post because:
the number of items per page must be hard-coded in _config.yml
I don't have the same number of elements on every page of my blog post anyway
I use a script to create this post, so I can use HTML, markdown, whatever. I could also make a separate file for each page--and hopefully, figure out how to direct Jekyll to find them without the date prefix.
I don't know Javascript or Ruby, but I can mostly find my way around. What I really need to know is which strategy to take so I can work toward that instead of spending all morning on something that won't work well.
So, how would you do it?
Here's my idea of what it could look like in Jekyll. This is a hack with some potential issues.
TL;DR
The blog post you have shared is using two different layouts for the start page and the subpages. The index has a different position for the menu and the intro. Also, the page content differs.
Good news: Jekyll has layouts, powerful collections (beside posts), as well as includes to reuse content. See the details with some notes below. I have also added short post about the solution to my own blog.
You need two layouts
_layouts\paginated-post.md
---
---
<p>tags here</p>
<h2>{{ page.title }}</h2>
<!-- page menu -->
<ul>
<li>{{ page.title }}</li>
{% for item in page.page_urls %}
<li>{{ item.title }} Palettes</li>
{% endfor %}
</ul>
{{ content }}
<h2>Pages</h2>
<ul>
<li>1</li>
{% for item in page.page_urls %}
{% assign page_number = forloop.index | plus: 1 %}
<li>{{ page_number }}</li>
{% endfor %}
</ul>
_layouts\paginated-post-index.md
---
---
<p>tags here</p>
<h2>{{ page.title }}</h2>
I created Artificial Intelligence to produce these palettes ...
<h2>Menu</h2>
<!-- page menu here -->
<ul>
<li>{{ page.title }}</li>
{% for item in page.page_urls %}
<li>{{ item.title }} Palettes</li>
{% endfor %}
</ul>
{{ content }}
<h2>Pages</h2>
<ul>
<li>1</li>
{% for item in page.page_urls %}
{% assign page_number = forloop.index | plus: 1 %}
<li>{{ page_number }}</li>
{% endfor %}
</ul>
Add a new collection
_config.yml
Note: I have chosen permalink path here, the defaults are optional if you set a layout in each collection item). Learn more about Jekyll collections in the docs.
collections:
palettes:
output: true
permalink: /:path/
defaults:
- scope:
path: ""
values:
layout: paginated-post
New collection folder (_palettes) with two files:
The index on each page defines the palettes index.
_palettes\index.md
---
layout: paginated-post-index
title: AI-Generated Palettes
index: palettes-index
page_urls:
- title: Wes Anderson
palette: Kind of Bird
url: /wes-anderson-kind-of-bird/
---
{% include palettes/wes.html %}
_palettes\wes-anderson-kind-of-bird.md
---
title: AI-Generated Palettes
subtitle: Wes Anderson – Kind of Bird
index: palettes-index
page_urls:
- title: Wes Anderson
palette: Kind of Bird
url: /wes-anderson-kind-of-bird/
---
{% include palettes/wes.html %}
Include file used above in _includes\palettes\wes.html
Note: the first line is the only line which will cause issues in other palette include files - maybe you will find your own solution or can just adjust the index here.
<h2>{{ page.page_urls[0].title }} </h2>
image here
Merin’s Fire: ff9506
Trojan Horse Brown: 7b571e
Minestrone: c4280d
Punch of Yellow: efd185
Root Brew: 2b0f0b
Green Ink: 12887f

How to get Data from Many-2-Many-Relation an ObjectBricks

When creating templates for document output, I would like to access the fields of ObjectBricks or many2many relations. With the relations, I can only access the path of the relation via Twig, but not the content of the object.
With ObjectBricks I can't get any further via Twig. I understood that all objects that are addressed in a class are loaded.
Or do I have to create extra snippets or views for each object, which are then included in the template? This then again in PHP and not in Twig?
Example :
a product has a m2m relation to a class "Material" , which contains the field "Description".
{% set matdate = product.Material %}
{% if matdate %}
{% for element in matdat %}
{{ element }}
so far it works, but
{% if(item) %}
{% for dat in element %}
{{dat}}
{% endfor %}
{% endif %}
When I then address the array, I get no content and no error.
Unfortunately, the descriptions from the Pimcore documentation don't help me with the ObjectBricks either. I can't figure out how to query them.
Maybe it's just a problem of understanding that is clear to everyone, but I can't find an answer.
Here is the dump:
Pimcore\Model\DataObject\Data\ElementMetadata {#4103 ▼
#elementType: "object"
#elementId: "88"
#fieldname: "Material"
#columns: array:1 [▶]
#data: []
#dao: Pimcore\Model\DataObject\Data\ElementMetadata\Dao {#4078 ▶}
#_owner: Pimcore\Model\DataObject\Implantat {#4079 ▶}
#_fieldname: "Material"
#_language: null
elementType: "object"
elementId: "88"
fieldname: "Material"
columns: array:1 [▶]
data: []
_owner: Pimcore\Model\DataObject\Implantat {#4079 ▶}
_fieldname: "Material"
_language: null

Shopware: Remove Add To Cart for Some products

Within Shopware 6, has anyone figured out how to remove the “add to cart” button for some products? My goal is to allow the add to cart on most items, but I’d like the option/ability to remove it for select products.
Thanks in advance!
Scott
You can use a custom field for this.
In admin go to Settings / Custom fields and add a new custom field set. Name it for example custom_product and assign Products, save. Then add a new custom field. Name it for example custom_product_remove_buy_button and choose Active switch as type.
Alternatively, you can create the custom field programmatically as described in the documentation.
You will see the new custom field in admin in product detail under Specifications / Custom fields.
Then you can use the custom field in a template to disable the "add to cart" button in the storefront. In order to remove the button on the product detail page, create a new file src/Resources/views/storefront/page/product-detail/buy-widget.html.twig in your theme or plugin and paste the following code:
{% sw_extends '#Storefront/storefront/page/product-detail/buy-widget.html.twig' %}
{% block page_product_detail_buy_form %}
{% if page.product.active and page.product.customFields.custom_product_remove_buy_button != true %}
<div class="product-detail-form-container">
{% sw_include '#Storefront/storefront/page/product-detail/buy-widget-form.html.twig' %}
</div>
{% endif %}
{% endblock %}
To remove the button in the product listing, create a file src/Resources/views/storefront/component/product/card/action.html.twig:
{% sw_extends '#Storefront/storefront/component/product/card/action.html.twig' %}
{% block component_product_box_action_buy %}
{% if product.customFields.custom_product_remove_buy_button != true %}
{{ parent() }}
{% endif %}
{% endblock %}
Setting the Max. order quantity to 0 will result in not showing a buy button on the product detail page. However it is still possible to add the product via the listing. To fix this you can extend this file as mentioned before:
src/Resources/views/storefront/component/product/card/action.html.twig
{% block component_product_box_action_buy %}
{% if product.calculatedMaxPurchase > 0 %}
{{ parent() }}
{% endif %}
{% endblock %}
If the user somehow manages to add the product in the cart Shopware will throw a default error message:
The product "Test" is not available any more

Navigation for pages (not for posts) in Jekyll

I'm building a website with Jekyll, just with pages.
I want to find a way to generate previous and next links for the pages, with an attribute for the pages like order.
Is there something that can do the job (without plugin)? I could only find something about posts.
{% assign sortedPages = site.pages | sort:'order' | where: 'published', true %}
{% for p in sortedPages %}
{% if p.url == page.url %}
{% if forloop.first == false %}
{% assign prevIndex = forloop.index0 | minus: 1 %}
<a href="{{site.baseurl}}{{sortedPages[prevIndex].url}}">
previous : {{sortedPages[prevIndex].title}}
</a>
{% endif %}
{% if forloop.last == false %}
{% assign nextIndex = forloop.index0 | plus: 1 %}
<a href="{{site.baseurl}}{{sortedPages[nextIndex].url}}">
next : {{sortedPages[nextIndex].title}}
</a>
{% endif %}
{% endif %}
{% endfor %}
This will do the job.
In order to filter which page you publish, you can add a published variable in pages front matter.
setting the variable
published: true -> this is a boolean
published: 'true' -> this is a string
using where filter
| where: 'published', true will test for boolean
| where: 'published', 'true' will test for string

Resources