Grav template -- Twig not listing child pages - twig

I have made a few pages in grav with a taxonomy like this.
- Home (category type)
- programming (category type)
- stuff (category type)
- stuff1 (page type)
- stuff2 (page type)
- stuff3 (page type)
I've also made a template type called "category" which should hopefully grab all the links to stuff1/2/3 and place them on the "stuff" page as links. My code looks a bit like this:
{% block body %}
{% block content %}
<ul>
{% for p in self.children %}
<li>{{ p.title }}</li>
{% endfor %}
</ul>
{% endblock %}
{% endblock %}
The end goal is to just get a simple listing of links for children to the category something like:
<ul>
<li>stuff1</li>
<li>stuff2</li>
<li>stuff3</li>
</ul>
I've tried using page.children, self.children, and a few other things but nothing seems to be getting this to work the way that I want it to.
Any help would be appreciated.

I'm afraid I do not quite understand what you mean by 'category type' and 'page type...
The docs on Page Collections might be quite helpful.
Example:
If you want a page with template 'category.html.twig' which shows a list of urls to all pages containing a certain category (or tag), you can do the following:
create a page 'category.md' defining a collection of categories in frontmatter:
content:
items:
'#taxonomy.category': mycategory
Create a template 'category.html.twig' containing:
<ul>
{% for p in page.collection() %}
<li>{{p.title}}</li>
{% endfor %}
</ul>
The resulting page will look like:
<ul>
<li>Home</li>
<li>Body & Hero Classes</li>
</ul>

Related

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

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

How to check routes on template?

Does anyone know how to check if a template is being accessed through a url route with the django template language?
Here is my situation: There's this template article.html, that shows all posts of a blog when accessed through blog-home url route, and that also shows only posts of a given user through user-posts url route.
This template works like that because what defines which posts will be shown are the classes in views.py.
That being said, here is what I tried to do: (I know its wrong)
{% if url == 'user-posts' %}
"Some HTML h1 tag I want do be shown only when this template is accessed via 'user-posts' url"
{% endif %}
How would be the correct way, if there's any, to write this if statement?
When Django matches a url pattern a ResolverMatch object is created and made available on the request object at request.resolver_match. This ResolverMatch object can be queried in your template to acheive what you want, the url_name attribute is the name of the url pattern that was matched
{% if request.resolver_match.url_name == 'user-posts' %}
You should create a custom templatetag,
my_app/templatetags/utils.py
from django import template
register = template.Library()
#register.simple_tag(takes_context=True)
def is_active_view(context, *view_names):
request = context.get('request')
for view_name in view_names:
if getattr(request.resolver_match, 'view_name', False) and request.resolver_match.view_name == view_name:
return True
return ''
And use it in your template this way, assuming blog-home is the url name you gave to your url :
blog-home.html
{% load utils %}
{% is_active_view 'blog-home' as display_blog_home_section %}
{% if display_blog_home_section %}
<!-- Your code -->
{% endif %}
NB : this template tag can check after multiple view names at once and support namespaced url :
{% is_active_view 'front:blog-home' 'front:blog-categories' as display %}
Here is a more optimized version of this if you are using boostrap and trying to make the menu options "active" when you are on that URL
from django import template
register = template.Library()
#register.simple_tag(takes_context=True)
def is_active_tab(context, *view_names):
request = context.get('request')
for view_name in view_names:
if getattr(request.resolver_match, 'view_name', '') == view_name:
return 'active'
return ''
And you use it like
<li class="nav-item {% is_active_tab 'games:list' %}">
<a class="nav-link" href="{% url 'games:list' %}">
{% translate "My Quizzes" %}
</a>
</li>
<li class="nav-item {% is_active_tab 'games:create' %}">
<a class="nav-link" href="{% url 'games:create' %}">
{% translate "New Game" %}
</a>
</li>
It adds an extra active classname to the class of the element if any of the view_names match the current view name. Makes the template writing much cleaner

How can I iterate over the terms in a taxonomy outside the list.html using Zola?

I've found out you can use
{% set posts = get_taxonomy(kind="posts") %}
to retrieve a taxonomy but I'm clueless how to iterate over the terms of the taxonomy in for example single.html of this taxonomy.
I tried things like the following, but I get:
"Tried to iterate using key value on variable 'posts', but it is
missing a key"
{% set posts = get_taxonomy(kind="posts") %}
{% for term in posts %}
<li class="list__item">
<a href="{{ term.permalink }}">
{{ term.name }}
</a>
</li>
{% endfor %}
get_taxonomy returns a struct with keys items & kind. You can debug using:
{% set posts = get_taxonomy(kind="posts") %}
<code>{{ posts.kind | json_encode(pretty=true) }}
{{ posts.items | json_encode(pretty=true) }}</code>
kind seems to have TaxonomyConfig structure and each element in items seems to have TaxonomyTerm structure.

Dynamic nav-bar elements - passed from Flask to Jinja - inherited layout template

Environment: Python 3.6, Flask 1.02, Jinja2
Objective:
Create a dynamic menu in layout.html (which is extended by content.html)
yet the url_for of the dynamic element is frequently requires a parameter to be passed
Issue statement:
How can I pass the parameters for url_for in Jinja template when rendering the template?
I feel like I would need the syntax of str().format in Jinja..
I tried to:
1. pass each part as a separate value:
menus = [{'url': 'func_name', 'menu_title': 'title', 'param': 'param_name', 'param_val': 'param_value'}]
return render_template('content1.html', menus=menus]
in jinja I tried to call it like: (I also tried it without the plus and double-quotes)
{{ url_for(func_name), param_name+ "=" + param_val }}
During rendering it gives error of
url_for() takes 1 positional argument but 2 were given
2. tried to use the {% set var_name: passed_variable %}
Built on 1st version of menus defined on server side, I tried to set the variables within Jinja, but also failed.
menus = [{'url': 'func_name', 'menu_title': 'title', 'param': 'param_name', 'param_val': 'param_value'}]
return render_template('content1.html', menus=menus]
Jinja
{% for menu in menus %}
{% set url = menu.get('url') %}
{% set param = menu.get('param') %}
{% set value = menu.get('param_val') %}
{% url_for(url, param + "=" + value %}
Yet it also didn't work.
It feels like if I give a param for the url_for syntax (not a hard-wired string) I cannot add the parameters.
3. tried to pass whole content of url_for as a string:
menus={'url_string': " 'func_name', param_name=param_value"}
yet it fails again as url_for syntacs put the whole between apostrophes, which I wouldn't need at the end.
Some references I scanned through.
Flask context-processor
It could work if I would create another template of each nav-bar for each content page - yet with that move i could simply move the navbar into the content page. However that seems dull. Stack Overflow topic
Thus question:
How can I pass the
param_id=paramval['id']
for the url_for syntax during rendering
{{ url_for('edit_question', param_id=paramval['id']) }}
The code/structure stg like below:
layout.html
<html>
<body>
{% for menu in menus %}
{% for key, value in menu.items() %}
<a href="{{ url_for(value) }}" >
{{ key }}
</a>
{% endfor %}
{% endfor %}
{% block content %}
{% endblock %}
</body>
</html>
content1.html
{% extends 'layout.html' %}
{% block content %}
content
{% endblock %}
content2.html
{% extends 'layout.html' %}
{% block content %}
content
{% endblock %}
app.py
#app.route('/')
def index():
menus = [{'menu_title1': 'menu_func_name1'}]
return render_template('content1.html', menus=menus)
#app.route('/menu_details/<int:menu_nr>')
def show_details_of_menu(menu_nr):
menus = [{'menu_title3': 'menu_func_name3', 'menu_param_name': 'menu_param_value'}
return render_template('content2.html', menus=menus)
sorry for the Wall of text..
sigh.. after hours I just found how to construct the syntax. I hope it will help others!
During rendering:
menus = [{'url': 'func_name', 'menu_title': 'title', 'parameters': {'param1': param1_value}}]
return render_template('context.html', menus=menus]
In Jinja, I adjusted the syntax to manage cases where no parameters are needed:
{% for menu in menus %}
{% if menu.get('parameters').items()|length > 0 %}
<a href="{{ url_for(menu.get('url'), **menu.get('parameters')) }}">
{{ menu.get('menu_title') }}
</a>
{% else %}
<a href="{{ url_for(menu.get('url')) }}">
{{ menu.get('menu_title') }}
</a>
{% endif %}
{% endfor %}

Resources