Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions content/docs/apps/guides/dispute-service.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ It's desirable to cancel fulfillment for orders that have not shipped yet when t
<Callout type="info">
To retrieve a list of all fulfillment orders and their status, use the [ordersFulfillmentOrdersRetrieve](/docs/admin-api/reference/orders/ordersFulfillmentOrdersRetrieve) endpoint.
</Callout>
<Tabs items={['Fulfillment Status - Unfulfilled', 'Fulifllment Status - Processing']}>
<Tabs items={['Fulfillment Status - Unfulfilled', 'Fulfillment Status - Processing']}>
<Tab value="Fulfillment Status - Unfulfilled">

If order `fulfilmlent_status` is `unfulfilled`, your dispute service can stop fulfillment using the [fulfillmentOrdersHold](/docs/admin-api/reference/fulfillment/fulfillmentOrdersHold) endpoint.
Expand All @@ -151,7 +151,7 @@ If order `fulfilmlent_status` is `unfulfilled`, your dispute service can stop fu
```

</Tab>
<Tab value="Fulifllment Status - Processing">
<Tab value="Fulfillment Status - Processing">

If order `fulfilmlent_status` is `processing` your dispute service can request processing fulfillment orders be canceled with the fulfillment locations with the [cancellationRequestSend](/docs/admin-api/reference/fulfillment/cancellationRequestSend) endpoint.

Expand Down
2 changes: 1 addition & 1 deletion content/docs/storefront/themes/cdn-and-caching.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -39,5 +39,5 @@ Updating a template through the dashboard or [Theme Kit](/docs/storefront/themes
<Callout type="warn">
There are a few cases wherein a form on the frontend needs to use a `{% csrf_token %}` field to secure submission to the backend. The platform core JS will automatically replace `{% csrf_token %}` that are in cached versions of pages to ensure the forms still work.

**It is advisable to not implement custom templates that require `{% csrf_token %}`, we recommend to [Storefront API](/docs/storefront/api) instead.**
**It is advisable to not implement custom templates that require `{% csrf_token %}`, we recommend the [Storefront GraphQL API](/docs/storefront/graphql) instead.**
</Callout>
32 changes: 31 additions & 1 deletion content/docs/storefront/themes/templates/filters.md
Original file line number Diff line number Diff line change
Expand Up @@ -297,9 +297,16 @@ For example, if value is the string "Sandy", the output would be the list ['S',
Returns a plural suffix if the value is not 1, '1', or an object of length 1. By default, this suffix is 's'.

```jinja title="pluralize"
You have { num_messages }} message {{ num_messages|pluralize }}
You have {{ num_messages }} message{{ num_messages|pluralize }}
```

### split
Splits a string by the given delimiter and returns a list.
```django title="split"
{{ value|split:"," }}
```
For example, if value is `"red,green,blue"`, the output will be the list `['red', 'green', 'blue']`.

### slugify

Converts to ASCII. Converts spaces to hyphens. Removes characters that aren’t alphanumerics, underscores, or hyphens. Converts to lowercase. Also strips
Expand Down Expand Up @@ -355,6 +362,29 @@ Returns the number of words.

For example, if value is "Joel is a slug", the output will be 4.

## Currency

### currency
Formats a decimal value as a currency string using the provided currency code. This is the primary filter for displaying prices throughout a theme.
```django title="currency"
{{ session.price.price|currency:session.price.currency }}
```
For example, if the price is `29.99` and the currency is `USD`, the output will be `$29.99`. The filter handles currency symbol placement and formatting based on the currency code.

```django title="Example Product Price Display"
{% purchase_info_for_product request product as session %}
{% if session.price.exists %}
{% if session.price.price_retail %}
<span class="text-muted text-decoration-line-through">
{{ session.price.price_retail|currency:session.price.currency }}
</span>
{% endif %}
<span class="fw-bold">
{{ session.price.price|currency:session.price.currency }}
</span>
{% endif %}
```

## Files

### asset_url
Expand Down
2 changes: 1 addition & 1 deletion content/docs/storefront/themes/templates/meta.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
"title": "Templates",
"pages": ["index", "tags", "objects", "urls-and-template-paths"]
"pages": ["index", "tags", "objects", "filters", "urls-and-template-paths"]
}
206 changes: 202 additions & 4 deletions content/docs/storefront/themes/templates/objects.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,7 @@ Returns a list of active storefront languages you can iterate over, see [languag

### menus


Allows you to access a menu's items by it's code to iterate over to generate a menu from the backend, see [menu items](#items-menu).
Allows you to access a menu's items by its code to iterate over to generate a menu from the backend, see [menu items](#items-menu). Menus are configured in the dashboard at **Storefront > Navigation**.


```django title="Example Dynamic Menu"
Expand Down Expand Up @@ -204,6 +203,9 @@ Returns a list of post categories you can iterate over, see [post_category](#pos

Content from store Privacy Policy settings, typically used in a "Privacy Policy" page to automatically pull content in from settings.

<Callout type="idea">
Store policies are configured in the dashboard at **Settings > Policies**. The content entered there is automatically available as global template variables.
</Callout>

```django title="privacy_policy"
{{ privacy_policy }}
Expand Down Expand Up @@ -340,7 +342,7 @@ Object have many properties that can be accessed in templates.

### branding

Store branding properties accessed through the [store](#store) object to leverage within templates.
Store branding properties accessed through the [store](#store) object to leverage within templates. Branding values are configured in the dashboard at **Settings > Branding**.

| Property | Type | Description |
| ----- | ------ | ------ |
Expand Down Expand Up @@ -596,7 +598,7 @@ Product review object.
| `id` | String | Review ID. |
| `title` | String | Review title. |
| `score` | Integer | Review score. |
| `user` | Object | The customer that created the review, see [user](#user). |
| `user` | Object | The customer that created the review. |


### voucher
Expand All @@ -607,3 +609,199 @@ Voucher object.
| ----- | ------ | ------ |
| `title` | String | Voucher title. |
| `code` | String | Voucher code. |


## View-Specific Objects

View-specific objects are available in the templates rendered by their corresponding views. See [Template Contexts](#template-contexts) below for which objects are available in each template.


### session

The session object is returned by the [`purchase_info_for_product`](/docs/storefront/themes/templates/tags#purchase_info_for_product) and [`purchase_info_for_line`](/docs/storefront/themes/templates/tags#purchase_info_for_line) template tags. It contains pricing and availability information for a product in the current user's currency.

```django title="Example Product Price with Session"
{% purchase_info_for_product request product as session %}
{% if session.price.exists %}
{% if session.price.price_retail %}
<span class="text-muted text-decoration-line-through">
{{ session.price.price_retail|currency:session.price.currency }}
</span>
{% endif %}
<span class="price">{{ session.price.price|currency:session.price.currency }}</span>
{% endif %}

{% if not session.availability.is_available_to_buy %}
<span class="text-danger">Out of Stock</span>
{% endif %}
```

**session.price**

| Property | Type | Description |
| ----- | ------ | ------ |
| `exists` | Boolean | Whether a price exists for this product. |
| `price` | Decimal | The current selling price. |
| `price_retail` | Decimal | The retail/compare-at price, if set. |
| `currency` | String | The currency code for this price. |
| `excl_tax` | Decimal | The price excluding tax. |

**session.availability**

| Property | Type | Description |
| ----- | ------ | ------ |
| `is_available_to_buy` | Boolean | Whether the product can be purchased. |


### variant_form

The variant selection form object available on product detail pages (`catalogue/product.html`). Used to render variant attribute selectors (size, color, etc.) for products with variants.

```django title="Example Variant Selection"
{% if variant_form %}
<div class="variant-options">
{% for field in variant_form %}
<div class="mb-3">
<label>{{ field.label }}</label>
{% render_field field class+="form-select" %}
</div>
{% endfor %}
</div>
{% endif %}
```

### filters

The `filters` object is a list of product filter/facet objects available on category pages (`catalogue/category.html`). Filters allow customers to narrow product listings by attributes like price, color, size, etc. The `has_active_filter` boolean indicates whether any filter is currently applied.

There are three filter types: `price_range`, `boolean`, and `list`. Each type has different properties for rendering the appropriate UI.

```django title="Example Category Filters"
{% if filters %}
<div class="filters">
{% for filter in filters %}
<div class="filter-group">
<h6>{{ filter.label }}</h6>

{% if filter.type == 'price_range' %}
<input type="number" name="{{ filter.min_value.param_name }}" value="{{ filter.min_value.value }}" placeholder="{{ filter.min_value.label }}">
<input type="number" name="{{ filter.max_value.param_name }}" value="{{ filter.max_value.value }}" placeholder="{{ filter.max_value.label }}">

{% elif filter.type == 'boolean' %}
<label>
<input type="checkbox" name="{{ filter.true_value.param_name }}" {% if filter.true_value.active %}checked{% endif %}>
Yes ({{ filter.true_value.count }})
</label>

{% else %}
{% for value in filter.values %}
<label>
<input type="checkbox" name="{{ value.param_name }}" {% if value.active %}checked{% endif %}>
{{ value.label }} ({{ value.count }})
</label>
{% endfor %}
{% endif %}
</div>
{% endfor %}

{% if has_active_filter %}
{% for filter in filters %}
{% for active in filter.active_values %}
<a href="{{ active.url_to_remove }}">Remove {{ active }}</a>
{% endfor %}
{% endfor %}
{% endif %}
</div>
{% endif %}
```

**Common filter properties:**

| Property | Type | Description |
| ----- | ------ | ------ |
| `type` | String | Filter type: `'price_range'`, `'boolean'`, or `'list'`. |
| `label` | String | Display label for the filter. |
| `active_values` | List | List of currently selected filter values. |
| `url_to_remove` | String | URL to remove this active filter. |

**Price range filter properties:**

| Property | Type | Description |
| ----- | ------ | ------ |
| `min_value.value` | Decimal | Current minimum price value. |
| `min_value.param_name` | String | Query parameter name for the minimum. |
| `min_value.label` | String | Display label for the minimum input. |
| `max_value.value` | Decimal | Current maximum price value. |
| `max_value.param_name` | String | Query parameter name for the maximum. |
| `max_value.label` | String | Display label for the maximum input. |
| `range_max` | Decimal | Maximum possible range value. |

**Boolean filter properties:**

| Property | Type | Description |
| ----- | ------ | ------ |
| `true_value.param_name` | String | Query parameter name for true selection. |
| `true_value.active` | Boolean | Whether true is currently selected. |
| `true_value.count` | Integer | Number of results matching true. |
| `false_value.param_name` | String | Query parameter name for false selection. |
| `false_value.active` | Boolean | Whether false is currently selected. |
| `false_value.count` | Integer | Number of results matching false. |

**List filter value properties:**

| Property | Type | Description |
| ----- | ------ | ------ |
| `param_name` | String | Query parameter name for this value. |
| `active` | Boolean | Whether this value is currently selected. |
| `count` | Integer | Number of results matching this value. |
| `value` | String | The filter value. |
| `label` | String | Display label for this value. |


## Template Contexts

All templates receive the [Global Objects](#global-objects) (`store`, `settings`, `currencies`, `languages_active_storefront`, `menus`, `products`, `product_categories`, `posts`, `post_categories`, `privacy_policy`, `terms_and_conditions`, `subscription_terms_and_conditions`, `request`, `storefront_geos`). The table below lists additional view-specific context variables passed to each template.

| Template | View-Specific Context |
| ----- | ------ |
| `templates/index.html` | Global objects only. Use the [`where`](/docs/storefront/themes/templates/tags#where) tag to query products and categories. |
| `templates/catalogue/product.html` | `product`, `variant_form`, `interval_count_choices` |
| `templates/catalogue/index.html` | `products` (paginated), `paginator`, `page_obj` |
| `templates/catalogue/category.html` | `category`, `products` (paginated), `filters`, `has_active_filter`, `paginator`, `page_obj` |
| `templates/search.html` | `query`, `products` (paginated), `paginator`, `page_obj` |
| `templates/blog/index.html` | `posts` (paginated), `paginator`, `page_obj` |
| `templates/blog/post.html` | `post` |
| `templates/pages/page.html` | `page` |
| `templates/support/index.html` | `categories` |
| `templates/support/category.html` | `category`, `articles` |
| `templates/support/article.html` | `article` |
| `templates/reviews/index.html` | `product`, `reviews` (paginated), `paginator`, `page_obj` |
| `templates/reviews/form.html` | `product`, `form` |
| `templates/reviews/review.html` | `product`, `review` |

<Callout type="idea">
Use the [`purchase_info_for_product`](/docs/storefront/themes/templates/tags#purchase_info_for_product) tag in any template to get pricing and availability for a product. Use [`cart_form`](/docs/storefront/themes/templates/tags#cart_form) on product pages to generate add-to-cart forms.
</Callout>

<Callout type="warn">
**Cart and user data must use the [Storefront GraphQL API](/docs/storefront/graphql).** All storefront pages are fully cached per language and currency combination. Per-user data (cart contents, authentication state, wishlists) rendered in server-side templates would be cached and served to other visitors. Use client-side JavaScript with the GraphQL API for all cart and user interactions.
</Callout>


## Dashboard Cross-Reference

Some template variables are populated from dashboard settings. Use this reference to understand where data originates when building or debugging templates.

| Template Variable | Dashboard Path | Description |
| ----- | ------ | ------ |
| `store.branding.logo` | Settings > Branding | Store logo image. |
| `store.branding.icon` | Settings > Branding | Store icon/favicon image. |
| `store.branding.primary_color` | Settings > Branding | Primary brand color (HEX). |
| `store.branding.accent_color` | Settings > Branding | Accent brand color (HEX). |
| `store.name`, `store.tagline` | Settings > General | Store name and tagline. |
| `store.legal_name`, `store.address` | Settings > General | Legal details and address. |
| `menus.{menu_key}.items` | Storefront > Navigation | Navigation menu items (up to 3 levels). |
| `privacy_policy` | Settings > Policies | Privacy policy content. |
| `terms_and_conditions` | Settings > Policies | Terms and conditions content. |
| `subscription_terms_and_conditions` | Settings > Policies | Subscription T&C content. |
| `settings.*` | Storefront > Themes > Customize | Theme settings from `settings_schema.json`. |
Loading