spryker-demo/company-document-feature

Company Document Feature

1.0.0 2025-04-09 16:09 UTC

This package is auto-updated.

Last update: 2025-05-22 16:53:54 UTC


README

Minimum PHP Version

This feature handles company document functionality.

Install the required modules using Composer

composer require spryker-demo/company-document-feature

Add SprykerDemo namespace to configuration

$config[KernelConstants::CORE_NAMESPACES] = [
    ...
    'SprykerDemo',
];

Add translations

# data/import/common/common/glossary.csv

company.account.company_documents,Documents,en_US
company.account.company_documents,Dokumente,de_DE
company.account.company_documents,Documents,fr_FR
company.account.company_documents,Documentos,es_ES
company.account.company_document.name,Document name,en_US
company.account.company_document.name,Dokumentenname,de_DE
company.account.company_document.name,Nom du document,fr_FR
company.account.company_document.name,Nombre del documento,es_ES
company.account.company_document.upload_date,Upload Date,en_US
company.account.company_document.upload_date,Datum des Uploads,de_DE
company.account.company_document.upload_date,Date de téléchargement,fr_FR
company.account.company_document.upload_date,Fecha de subida,es_ES
company.account.company_document.download,Download,en_US
company.account.company_document.download,Download,de_DE
company.account.company_document.download,Télécharger,fr_FR
company.account.company_document.download,Descargar,es_ES
company.account.company_document.no_document.,No documents available at the moment,en_US
company.account.company_document.no_document.,Aktuell keine Dokumente verfügbar,de_DE
company.account.company_document.no_document.,Aucun document disponible pour le moment,fr_FR
company.account.company_document.no_document.,No hay documentos disponibles por el momento,es_ES

Import translations

console data:import:glossary

Set up behavior

Activate the following plugins:

src/Pyz/Yves/Router/RouterDependencyProvider.php

...
use SprykerDemo\Yves\CompanyDocumentPage\Plugin\Router\CompanyDocumentPageRouteProviderPlugin;
...

class RouterDependencyProvider extends SprykerRouterDependencyProvider
{
    ...
    /**
     * @return array<\Spryker\Yves\RouterExtension\Dependency\Plugin\RouteProviderPluginInterface>
     */
    protected function getRouteProvider(): array
    {
        return [
           new CompanyDocumentPageRouteProviderPlugin(),
        ];
    }
}

src/Pyz/Client/RabbitMq/RabbitMqConfig.php

...
use SprykerDemo\Yves\CompanyDocumentPage\Plugin\Router\CompanyDocumentPageRouteProviderPlugin;
...

class RouterDependencyProvider extends SprykerRouterDependencyProvider
{
    ...
    protected function getRouteProvider(): array
    {
        return [
           new CompanyDocumentPageRouteProviderPlugin(),
        ];
    }
}

src/Pyz/Client/RabbitMq/RabbitMqConfig.php

...
use SprykerDemo\Yves\CompanyDocumentPage\Plugin\Router\CompanyDocumentPageRouteProviderPlugin;
...

class RabbitMqConfig extends SprykerRabbitMqConfig
{
    ...
    protected function getPyzPublishQueueConfiguration(): array
    {
        return [
           ...
           CompanyDocumentStorageConfig::PUBLISH_COMPANY_DOCUMENT_QUEUE,
        ];
    }

    ...
    protected function getPyzSynchronizationQueueConfiguration(): array
    {
        return [
           ...
           CompanyDocumentStorageConfig::SYNC_STORAGE_COMPANY_DOCUMENT_QUEUE,
        ];
    }
}

src/Pyz/Zed/Publisher/PublisherDependencyProvider.php

...
use SprykerDemo\Shared\CompanyDocumentStorage\CompanyDocumentStorageConfig;
use SprykerDemo\Zed\CompanyDocumentStorage\Communication\Plugin\Publisher\CompanyDocument\CompanyDocumentDeletePublisherPlugin;
use SprykerDemo\Zed\CompanyDocumentStorage\Communication\Plugin\Publisher\CompanyDocument\CompanyDocumentWritePublisherPlugin;
...

class PublisherDependencyProvider extends SprykerPublisherDependencyProvider
{
    ...
    protected function getPublisherPlugins(): array
    {
        return array_merge(
            ...
            $this->getCompanyDocumentStoragePlugins(),
        );
    }

    ...
    protected function getCompanyDocumentStoragePlugins(): array
    {
        return [
            CompanyDocumentStorageConfig::PUBLISH_COMPANY_DOCUMENT_QUEUE => [
                new CompanyDocumentWritePublisherPlugin(),
                new CompanyDocumentDeletePublisherPlugin(),
            ],
        ];
    }
}

src/Pyz/Zed/Queue/QueueDependencyProvider.php

...
use SprykerDemo\Shared\CompanyDocumentStorage\CompanyDocumentStorageConfig;
...

class QueueDependencyProvider extends SprykerDependencyProvider
{
    ...
    protected function getProcessorMessagePlugins(Container $container): array
    {
        return [
            ...
            CompanyDocumentStorageConfig::PUBLISH_COMPANY_DOCUMENT_QUEUE => new EventQueueMessageProcessorPlugin(),
            CompanyDocumentStorageConfig::SYNC_STORAGE_COMPANY_DOCUMENT_QUEUE => new SynchronizationStorageQueueMessageProcessorPlugin(),
        ];
    }
}

src/Pyz/Zed/Publisher/PublisherDependencyProvider.php

...
use SprykerDemo\Zed\CompanyDocumentStorage\Communication\Plugin\Publisher\CompanyDocument\CompanyDocumentPublisherTriggerPlugin
...

class PublisherDependencyProvider extends SprykerPublisherDependencyProvider
{
    ...
    protected function getPublisherTriggerPlugins(): array
    {
        return [
            ...
            new CompanyDocumentPublisherTriggerPlugin(),
        ];
}

src/Pyz/Zed/Synchronization/SynchronizationDependencyProvider.php

...
use SprykerDemo\Zed\CompanyDocumentStorage\Communication\Plugin\Synchronization\CompanyDocument\CompanyDocumentSynchronizationDataBulkRepositoryPlugin;
...

class SynchronizationDependencyProvider extends SprykerSynchronizationDependencyProvider
{
    ...
    protected function getSynchronizationDataBulkPlugins(): array
    {
        return [
            ...
            new CompanyDocumentSynchronizationDataBulkRepositoryPlugin(),
        ];
    }
}

Extend CompanyDocumentStorageConfig:

src/Pyz/Zed/CompanyDocumentStorage/CompanyDocumentStorageConfig.php

namespace Pyz\Zed\CompanyDocumentStorage;

use Pyz\Zed\Synchronization\SynchronizationConfig;
use SprykerDemo\Zed\CompanyDocumentStorage\CompanyDocumentStorageConfig as SprykerDemoCompanyDocumentStorageConfig;

class CompanyDocumentStorageConfig extends SprykerDemoCompanyDocumentStorageConfig
{
    ...
    /**
     * @api
     *
     * @return string|null
     */
    public function getSynchronizationQueuePoolName(): ?string
    {
        return SynchronizationConfig::DEFAULT_SYNCHRONIZATION_POOL_NAME;
    }
}

Apply Twig customization

# src/Pyz/Yves/CustomerPage/Theme/default/components/molecules/customer-navigation/customer-navigation.twig

{% extends model('component') %}
{% import _self as component %}

{% define config = {
    name: 'customer-navigation',
    tag: 'nav'
} %}

{% define data = {
    activePage: required,
    activeEntityId: required
} %}


{% block body %}
    {% if can('SeeCompanyMenuPermissionPlugin') %}
        {% include molecule('customer-navigation-sidebar', 'CustomerPage') with {
            modifiers: ['company'],
            data: {
                title: 'customer.menu.company.title' | trans,
                activePage: data.activePage,
                items: [
                    {
                        name: 'overview',
                        url: path('company/overview'),
                        label: 'company.account.overview' | trans,
                        icon: 'shopping-list'
                    },
                    {
                        name: 'users',
                        url: path('company/user'),
                        label: 'company.account.company_user' | trans,
                        icon: 'users'
                    },
                    {
                        name: 'business-unit',
                        url: path('company/business-unit'),
                        label: 'company.account.business_unit' | trans,
                        icon: 'office'
                    },
                    {
                        name: 'role',
                        url: path('company/company-role'),
                        label: 'company.account.company_role' | trans,
                        icon: 'user'
                    },
                    {
                        name: 'company-documents',
                        url: path('company/documents'),
                        label: 'company.account.company_documents' | trans,
                        icon: 'file',
                    },
                ]
            }
        } only %}
    {% endif %}
    {% embed molecule('customer-navigation-sidebar', 'CustomerPage') with {
        modifiers: ['customer'],
        data: {
            title: 'customer.menu.customer.title' | trans,
            activePage: data.activePage,
            activeEntityId: data.activeEntityId,
            items: [
                {
                    name: 'customer-overview',
                    url: path('customer/overview'),
                    label: 'customer.account.overview' | trans,
                    icon: 'page',
                },
                {
                    name: 'profile',
                    url: path('customer/profile'),
                    label: 'customer.account.profile_data' | trans,
                    icon: 'user',
                },
                {
                    name: 'address',
                    url: path('customer/address'),
                    label: 'customer.account.address' | trans,
                    icon: 'marker',
                },
                {
                    name: 'order',
                    url: path('customer/order'),
                    label: 'customer.account.order_history' | trans,
                    icon: 'history',
                },
                {
                    name: 'subscription',
                    url: path('subscription-product'),
                    label: 'customer.account.subscriptions' | trans,
                    icon: 'subscription',
                },
                {
                    name: 'return',
                    url: path('return/list'),
                    label: 'return_page.list.title' | trans,
                    icon: 'return-arrow',
                    isActiveItem:  'return/list' == data.activePage | default,
                },
                {
                    name: 'newsletter',
                    url: path('customer/newsletter'),
                    label: 'customer.account.newsletter' | trans,
                    icon: 'envelopes',
                },
            ]
        }
    } only %}
        {% block postContent %}
            {% widget 'ShoppingListMenuItemWidget' args [
                data.activePage,
                data.activeEntityId,
            ] only %}
            {% endwidget %}

            {% widget 'MultiCartMenuItemWidget' args [data.activePage] only %}{% endwidget %}

            {% widget 'QuoteRequestMenuItemWidget' args [data.activePage] only %}{% endwidget %}

            {% widget 'BusinessOnBehalfStatusWidget' use view('change-company-user', 'BusinessOnBehalfWidget') with {
                isActivePage: 'change-company-user' == data.activePage
            } only %}
                {% block body %}
                    {% include molecule('navigation-sidebar-item') with {
                        data: {
                            url: path('company/user/select'),
                            icon: 'building',
                            label: 'business_on_behalf_widget.no_selected_company' | trans,
                            name: 'no-company',
                            active: isActivePage,
                        },
                        modifiers: isActivePage ? ['active'] : [],
                    } only %}
                {% endblock %}
            {% endwidget %}
        {% endblock %}
    {% endembed %}
{% endblock %}

# src/Pyz/Yves/ShopUi/Theme/default/components/molecules/user-navigation/user-navigation.twig

{% extends model('component') %}

{% define config = {
    name: 'user-navigation',
    tag: 'ul',
} %}

{% define data = {
    user: required,
} %}

{% set cartQuantityText = cartQuantity > 0 ? cartQuantity ~ ' ' %}
{% set shouldShowMiniCart = findWidget('MiniCartWidget', [cartQuantityText]).isMultiCartAllowed %}

{%- block class -%}
    {{ parent() }} {{ config.jsName }}
{%- endblock -%}

{% block body %}
    <li class="{{ config.name }}__item {{ config.name }}__item--user">
        <div class="{{ config.name }}__user-name">
            <span class="{{ config.name }}__icon">
                {% include atom('icon') with {
                    modifiers: ['user'],
                    data: {
                        name: 'user',
                    },
                } only %}
                {% include atom('icon') with {
                    class: config.name ~ '__arrow',
                    data: {
                        name: 'caret-down',
                    },
                } only %}
            </span>
            <span class="{{ config.name }}__text">{% widget 'CustomerFullNameWidget' only %}{% endwidget %}</span>
        </div>
        {% if can('SeeCompanyMenuPermissionPlugin') %}
            {% include molecule('navigation-list') with {
                modifiers: ['secondary'],
                class: config.name ~ '__sub-nav',
                data: {
                    nodes: [
                        {
                            url: path('company/overview'),
                            title: 'company.account.overview' | trans,
                        },
                        {
                            url: path('company/user'),
                            title: 'company.account.company_user' | trans,
                        },
                        {
                            url: path('company/business-unit'),
                            title: 'company.account.business_unit' | trans,
                        },
                        {
                            url: path('company/company-role'),
                            title: 'company.account.company_role' | trans,
                        },
                        {
                            url: path('company/documents'),
                            title: 'company.account.company_documents' | trans,
                            cssItemClass: 'has-separator',
                        },
                        {
                            url: url('customer/overview'),
                            title: 'customer.account.overview' | trans,
                        },
                        {
                            url: url('customer/profile'),
                            title: 'customer.account.profile_data' | trans,
                        },
                        {
                            url: url('customer/address'),
                            title: 'customer.account.address' | trans,
                        },
                        {
                            url: url('customer/order'),
                            title: 'customer.account.order_history' | trans,
                        },
                        {
                            url: url('subscription-product'),
                            title: 'customer.account.subscriptions' | trans,
                        },
                        {
                            url: url('return/list'),
                            title: 'return_page.default_title' | trans,
                        },
                        {
                            url: url('customer/newsletter'),
                            title: 'customer.account.newsletter' | trans,
                        },
                        {
                            url: url('quote-request'),
                            title: 'quote_request_widget.request_for_quote.list.title' | trans,
                        },
                        {
                            url: url('logout'),
                            title: 'customer.logout' | trans,
                            additionalClass: 'link--additional',
                        },
                    ]
                },
            } only %}
        {% else %}
            {% include molecule('navigation-list') with {
                modifiers: ['secondary'],
                class: config.name ~ '__sub-nav',
                data: {
                    nodes: [
                        {
                            url: url('customer/overview'),
                            title: 'customer.account.overview' | trans,
                        },
                        {
                            url: url('customer/profile'),
                            title: 'customer.account.profile_data' | trans,
                        },
                        {
                            url: url('customer/address'),
                            title: 'customer.account.address' | trans,
                        },
                        {
                            url: url('customer/order'),
                            title: 'customer.account.order_history' | trans,
                        },
                        {
                            url: url('subscription-product'),
                            title: 'customer.account.subscriptions' | trans,
                        },
                        {
                            url: url('return/list'),
                            title: 'return_page.default_title' | trans,
                        },
                        {
                            url: url('customer/newsletter'),
                            title: 'customer.account.newsletter' | trans,
                        },
                        {
                            url: url('quote-request'),
                            title: 'quote_request_widget.request_for_quote.list.title' | trans,
                        },
                        {
                            url: url('logout'),
                            title: 'customer.logout' | trans,
                            additionalClass: 'link--additional',
                        },
                    ]
                },
            } only %}
        {% endif %}
    </li>
    <li class="{{ config.name }}__item">
        <a class="{{ config.name }}__link" href="{{ url('quick-order') }}">
            <span class="{{ config.name }}__icon">
                {% include atom('icon') with {
                    modifiers: ['quick-order'],
                    data: {
                        name: 'quick-order',
                    },
                } only %}
            </span>
            <span class="{{ config.name }}__text">{{ 'quick-order.page-title'|trans }}</span>
        </a>
    </li>

    {% widget 'ShoppingListNavigationMenuWidget' with {config: config} only %}
        {% block body %}
            <li class="{{ config.name }}__item">
                <a class="{{ config.name }}__link {{ config.jsName }}__trigger" href="{{ url('shopping-list') }}" data-toggle-target='.{{ config.jsName }}__sub-nav-shopping-list'>
                    <span class="{{ config.name }}__icon">
                    {% include atom('icon') with {
                        modifiers: ['header-shopping-list'],
                        data: {
                            name: 'shopping-list',
                        },
                    } only %}
                    </span>
                    <span class="{{ config.name }}__text">{{ 'customer.account.shopping_list'|trans }}</span>
                </a>
                <div class="{{ config.name }}__sub-nav {{ config.name }}__sub-nav--pull-left spacing spacing--inner spacing--reset {{ config.jsName }}__sub-nav-shopping-list">
                    <button class="{{config.name}}__sub-nav-close {{ config.jsName }}__trigger" data-toggle-target='.{{ config.jsName }}__sub-nav-shopping-list'>
                        {% include atom('icon') with {
                            data: {
                                name: 'cross',
                            },
                        } only %}
                    </button>
                    <h4 class="{{ config.name }}__sub-nav-title">
                        {{ 'shopping_list.shopping_list'|trans }}
                    </h4>
                    {% block listItems %}
                        <div class="{{ config.name }}__sub-nav-inner">
                            {{ parent() }}
                        </div>
                    {% endblock %}
                    {% block listActions %}
                        <div class="{{ config.name }}__sub-nav-actions">
                            {{ parent() }}
                        </div>
                    {% endblock %}
                </div>
            </li>
        {% endblock %}
    {% endwidget %}

    <li class="{{ config.name }}__item">
        {% if not shouldShowMiniCart %}
            <a class="{{ config.name }}__link" href="{{ url('cart') }}">
                <span class="{{ config.name }}__empty-cart">
                    {% include atom('icon') with {
                        modifiers: ['cart'],
                        data: {
                            name: 'cart',
                        },
                    } only %}
                </span>

                <span>{{ 'global.my-cart' | trans }}</span>
            </a>
        {% else %}
            {% embed molecule('cart-counter') with {
                class: config.jsName ~ '__trigger',
                data: {
                    quantity: cartQuantity,
                },
                attributes: {
                    'data-toggle-target': '.' ~ config.jsName ~ '__sub-nav-cart',
                },
                embed: {
                    parentConfigName: config.name,
                },
            } only %}
                {% block content %}
                    {% set linkClass = embed.parentConfigName ~ '__link' %}
                    {{ parent() }}
                {% endblock %}
            {% endembed %}
            <div class="{{ config.name }}__sub-nav {{ config.name }}__sub-nav--pull-left spacing spacing--inner spacing--reset {{ config.jsName }}__sub-nav-cart">
                {% widget 'MiniCartWidget' args [cartQuantityText] with {config: config} only %}
                    {% block body %}
                        <button class="{{config.name}}__sub-nav-close {{ config.jsName }}__trigger" data-toggle-target='.{{ config.jsName }}__sub-nav-cart'>
                            {% include atom('icon') with {
                                data: {
                                    name: 'cross',
                                },
                            } only %}
                        </button>
                        <h4 class="{{ config.name }}__sub-nav-title">
                            {{ 'multi_cart_widget.cart.carts'|trans }}
                        </h4>
                        {% block cartItems %}
                            <div class="{{ config.name }}__sub-nav-inner">
                                {{ parent() }}
                            </div>
                        {% endblock %}

                        {% block cartActions %}
                            <div class="{{ config.name }}__sub-nav-actions">
                                {{ parent() }}
                            </div>
                        {% endblock %}
                    {% endblock %}
                {% endwidget %}
            </div>
        {% endif %}
    </li>

    {% include molecule('toggler-accordion') with {
        attributes: {
            'wrap-class-name': config.jsName,
            'trigger-class-name': config.jsName ~ '__trigger',
            'class-to-toggle': config.name ~ '__sub-nav--touch-active',
            'active-on-touch': 'true',
        },
    } only %}

{% endblock %}

# src/Pyz/Yves/ShopUi/Theme/default/templates/page-layout-main/page-layout-main.twig

{% extends template('page-blank') %}

{% block meta %}
    {{ parent() }}
    <meta name="format-detection" content="telephone=no">
{% endblock %}

{% block headStyles %}
    {{ parent() }}

    {% if findWidget('FrontendConfiguratorWidget') %}
        {% widget 'FrontendConfiguratorWidget' only %}{% endwidget %}
    {% endif %}
{% endblock %}

{%- block class -%}js-page-layout-main__side-drawer-container{%- endblock -%}

{% block body %}

    {% if findWidget('FrontendConfiguratorWidget') %}
        {% set frontendConfiguratorWidget = findWidget('FrontendConfiguratorWidget') %}
    {% endif %}

    {% block notifications %}
        {% include organism('notification-area') only %}
    {% endblock %}
    <div class="page-layout page-layout--preload">
        {% widget 'AgentControlBarWidget' only %}{% endwidget %}

        {% block sidebar %}
            {% embed organism('side-drawer') with {
                attributes: {
                    'container-class-name': 'js-page-layout-main__side-drawer-container',
                    'trigger-class-name': 'js-page-layout-main__side-drawer-trigger',
                    'locked-body-class-name': 'is-locked-tablet',
                },
            } only %}
                {% block navigation %}
                    {% cms_slot 'slt-mobile-header' %}
                {% endblock %}
            {% endembed %}

            {% if is_granted('ROLE_USER') %}
                {% set customerFullNameWidget = findWidget('CustomerFullNameWidget') %}
                {% set customerFullName = customerFullNameWidget.customerFullName %}

                {% include organism('account-navigation') with {
                    attributes: {
                        'container-class-name': 'js-page-layout-main__side-drawer-container',
                        'trigger-class-name': 'js-page-layout-main__user-account-navigation-trigger',
                        'locked-body-class-name': 'is-locked-mobile',
                    },
                    data: {
                        title: customerFullName,
                        items: [
                            {
                                name: 'overview',
                                url: path('customer/overview'),
                                label: 'customer.account.overview' | trans,
                                icon: 'page'
                            },
                            {
                                name: 'profile',
                                url: path('customer/profile'),
                                label: 'customer.account.profile_data' | trans,
                                icon: 'user'
                            },
                            {
                                name: 'address',
                                url: path('customer/address'),
                                label: 'customer.account.address' | trans,
                                icon: 'marker'
                            },
                            {
                                name: 'order',
                                url: path('customer/order'),
                                label: 'customer.account.order_history' | trans,
                                icon: 'history'
                            },
                            {
                                name: 'returns',
                                url: path('return/list'),
                                label: 'return_page.default_title' | trans,
                                icon: 'return-arrow'
                            },
                            {
                                name: 'newsletter',
                                url: path('customer/newsletter'),
                                label: 'customer.account.newsletter' | trans,
                                icon: 'envelopes'
                            },
                            {
                                name: 'shopping-list',
                                url: path('shopping-list'),
                                label: 'customer.account.shopping_list' | trans,
                                icon: 'shopping-list'
                            },
                            {
                                name: 'shopping-cart',
                                url: path('multi-cart'),
                                label: 'page.multi_cart.shopping_cart.list.title' | trans,
                                icon: 'cart'
                            },
                            {
                                name: 'quote-request',
                                url: path('quote-request'),
                                label: 'quote_request_widget.request_for_quote.list.title' | trans,
                                icon: 'message',
                            },
                        ],
                    }
                } only %}

                {% if can('SeeCompanyMenuPermissionPlugin') %}
                    {% set menuItemCompanyWidget = findWidget('MenuItemCompanyWidget') %}
                    {% set companyName = menuItemCompanyWidget.companyName %}

                    {% include organism('account-navigation') with {
                        modifiers: ['company'],
                        attributes: {
                            'container-class-name': 'js-page-layout-main__side-drawer-container',
                            'trigger-class-name': 'js-page-layout-main__company-account-navigation-trigger',
                            'locked-body-class-name': 'is-locked-mobile',
                        },
                        data: {
                            introIcon: 'office',
                            title: companyName,
                            items: [
                                {
                                    name: 'overview',
                                    url: path('company/overview'),
                                    label: 'company.account.overview' | trans,
                                    icon: 'shopping-list'
                                },
                                {
                                    name: 'users',
                                    url: path('company/user'),
                                    label: 'company.account.company_user' | trans,
                                    icon: 'users'
                                },
                                {
                                    name: 'business-unit',
                                    url: path('company/business-unit'),
                                    label: 'company.account.business_unit' | trans,
                                    icon: 'office'
                                },
                                {
                                    name: 'role',
                                    url: path('company/company-role'),
                                    label: 'company.account.company_role' | trans,
                                    icon: 'user'
                                },
                                {
                                    name: 'company-documents',
                                    url: path('company/documents'),
                                    label: 'company.account.company_documents' | trans,
                                    icon: 'file',
                                }
                            ]
                        }
                    } only %}
                {% endif %}
            {% endif %}
        {% endblock %}

        {% block outside %}{% endblock %}

        {% block header %}

            {% embed organism('header') with {
                embed: {
                    logoSrc: frontendConfiguratorWidget.data.logoUrl ?? null,
                },
            } only %}
                {% block navigation %}
                    {% cms_slot 'slt-desktop-header' %}
                {% endblock %}

                {% block logo %}
                    {% include molecule('logo') with {
                        class: 'col ' ~  config.name ~ '__logo',
                        modifiers: ['main'],
                        attributes: {
                            src: embed.logoSrc,
                        }
                    } only %}
                {% endblock %}

                {% block mobile %}
                    <a href="#" class="link link--alt js-page-layout-main__side-drawer-trigger">
                        {% include atom('icon') with {
                            modifiers: ['big'],
                            data: {
                                name: 'bars',
                            },
                        } only %}
                    </a>
                {% endblock %}
            {% endembed %}
        {% endblock %}

        <div itemscope itemtype="https://schema.org/Product" class="content-wrap">
            {% block pageInfo %}
                <div class="page-info">
                    <div class="container">
                        {% block breadcrumbs %}
                            {% include molecule('breadcrumb') only %}
                        {% endblock %}

                        {% block title %}
                            <h1 class="page-info__title title title--h3 ">{{ data.title }}</h1>
                        {% endblock %}
                    </div>
                </div>
            {% endblock %}

            <main class="{% block contentClass %}{% endblock %}">
                {% block contentTop %}{% endblock %}

                {% block contentWrap %}
                    <div class="container">
                        {% block content %}{% endblock %}
                    </div>
                {% endblock %}

                {% block contentBottom %}{% endblock %}
            </main>
        </div>

        {% block footer %}
            {% cms_slot 'slt-1' %}

            {% embed organism('footer') only %}
                {% block logosInner %}
                    {% cms_slot 'slt-footer-partners' %}
                {% endblock %}

                {% block navigationInner %}
                    <div class="grid grid--gap">
                        {% cms_slot 'slt-footer-navigation' %}
                    </div>
                {% endblock %}

                {% block socialLinks %}
                    {% cms_slot 'slt-footer-social-links' %}
                {% endblock %}
            {% endembed %}
        {% endblock %}
    </div>

    {% include atom('overlay-block') only %}
    {% include atom('touch-checker') only %}

    {% block globalComponents %}
        {% include molecule('action-single-click-enforcer') with {
            attributes: {
                'target-selector': '[data-init-single-click]',
            },
        } only %}

        {% include molecule('form-submitter') with {
            attributes: {
                'trigger-selector': '[data-form-submitter]',
            },
        } only %}

        {% include molecule('viewport-intersection-observer') only %}

        {% include molecule('node-animator') only %}

        {% include molecule('window-load-class-remover') with {
            attributes: {
                'target-class-name': 'page-layout',
                'trigger-class-name': 'page-layout--preload',
            },
        } only %}
    {% endblock %}

    {% block icons %}
        {% include atom('icon-sprite') only %}
    {% endblock %}
{% endblock %}