feat: replace some partials with twig components

This commit is contained in:
Björn Fromme
2024-03-01 11:13:47 +01:00
parent a668dcb326
commit f722afe7ff
23 changed files with 205 additions and 96 deletions
+1
View File
@@ -55,6 +55,7 @@
"symfony/translation": "6.4.*", "symfony/translation": "6.4.*",
"symfony/twig-bundle": "6.4.*", "symfony/twig-bundle": "6.4.*",
"symfony/uid": "6.4.*", "symfony/uid": "6.4.*",
"symfony/ux-twig-component": "^2.16",
"symfony/validator": "6.4.*", "symfony/validator": "6.4.*",
"symfony/web-link": "6.4.*", "symfony/web-link": "6.4.*",
"symfony/webpack-encore-bundle": "^2.0", "symfony/webpack-encore-bundle": "^2.0",
Generated
+85 -1
View File
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "818236d2338d823f03df901faa47b1c5", "content-hash": "18ff369a6df51ed294b3946625466f92",
"packages": [ "packages": [
{ {
"name": "beberlei/doctrineextensions", "name": "beberlei/doctrineextensions",
@@ -8130,6 +8130,90 @@
], ],
"time": "2024-01-23T14:51:35+00:00" "time": "2024-01-23T14:51:35+00:00"
}, },
{
"name": "symfony/ux-twig-component",
"version": "v2.16.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/ux-twig-component.git",
"reference": "c789f33dd8800949293dd94bf8e7bf01c39559a2"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/ux-twig-component/zipball/c789f33dd8800949293dd94bf8e7bf01c39559a2",
"reference": "c789f33dd8800949293dd94bf8e7bf01c39559a2",
"shasum": ""
},
"require": {
"php": ">=8.1",
"symfony/dependency-injection": "^5.4|^6.0|^7.0",
"symfony/deprecation-contracts": "^2.2|^3.0",
"symfony/event-dispatcher": "^5.4|^6.0|^7.0",
"symfony/property-access": "^5.4|^6.0|^7.0",
"twig/twig": "~3.8.0"
},
"conflict": {
"symfony/config": "<5.4.0"
},
"require-dev": {
"symfony/console": "^5.4|^6.0|^7.0",
"symfony/css-selector": "^5.4|^6.0|^7.0",
"symfony/dom-crawler": "^5.4|^6.0|^7.0",
"symfony/framework-bundle": "^5.4|^6.0|^7.0",
"symfony/phpunit-bridge": "^6.0|^7.0",
"symfony/stimulus-bundle": "^2.9.1",
"symfony/stopwatch": "^5.4|^6.0|^7.0",
"symfony/twig-bundle": "^5.4|^6.0|^7.0",
"symfony/webpack-encore-bundle": "^1.15"
},
"type": "symfony-bundle",
"extra": {
"thanks": {
"name": "symfony/ux",
"url": "https://github.com/symfony/ux"
}
},
"autoload": {
"psr-4": {
"Symfony\\UX\\TwigComponent\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Twig components for Symfony",
"homepage": "https://symfony.com",
"keywords": [
"components",
"symfony-ux",
"twig"
],
"support": {
"source": "https://github.com/symfony/ux-twig-component/tree/v2.16.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2024-02-29T16:20:59+00:00"
},
{ {
"name": "symfony/validator", "name": "symfony/validator",
"version": "v6.4.3", "version": "v6.4.3",
+1
View File
@@ -18,4 +18,5 @@ return [
Liip\ImagineBundle\LiipImagineBundle::class => ['all' => true], Liip\ImagineBundle\LiipImagineBundle::class => ['all' => true],
Knp\Bundle\PaginatorBundle\KnpPaginatorBundle::class => ['all' => true], Knp\Bundle\PaginatorBundle\KnpPaginatorBundle::class => ['all' => true],
Nelmio\SecurityBundle\NelmioSecurityBundle::class => ['all' => true], Nelmio\SecurityBundle\NelmioSecurityBundle::class => ['all' => true],
Symfony\UX\TwigComponent\TwigComponentBundle::class => ['all' => true],
]; ];
+5
View File
@@ -0,0 +1,5 @@
twig_component:
anonymous_template_directory: 'components/'
defaults:
# Namespace & directory for components
App\Twig\Components\: 'components/'
+10
View File
@@ -0,0 +1,10 @@
<?php
namespace App\Twig\Components;
use Symfony\UX\TwigComponent\Attribute\AsTwigComponent;
#[AsTwigComponent(template: 'components/dropdown.html.twig')]
class DropDown
{
}
+12
View File
@@ -0,0 +1,12 @@
<?php
namespace App\Twig\Components;
use Symfony\UX\TwigComponent\Attribute\AsTwigComponent;
#[AsTwigComponent(template: 'components/messagebox.html.twig')]
class MessageBox
{
public string $message;
public string $type = 'info';
}
+11
View File
@@ -0,0 +1,11 @@
<?php
namespace App\Twig\Components;
use Symfony\UX\TwigComponent\Attribute\AsTwigComponent;
#[AsTwigComponent(template: 'components/rating_stars.html.twig')]
class RatingStars
{
public ?int $averageRating;
}
+12
View File
@@ -300,6 +300,18 @@
"config/packages/uid.yaml" "config/packages/uid.yaml"
] ]
}, },
"symfony/ux-twig-component": {
"version": "2.16",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "2.13",
"ref": "67814b5f9794798b885cec9d3f48631424449a01"
},
"files": [
"config/packages/twig_component.yaml"
]
},
"symfony/validator": { "symfony/validator": {
"version": "6.3", "version": "6.3",
"recipe": { "recipe": {
+18 -16
View File
@@ -30,22 +30,24 @@
</div> </div>
{% if assignment.pickup %} {% if assignment.pickup %}
{% set pickup = assignment.destination.pickup(assignment.pickup) %} {% set pickup = assignment.destination.pickup(assignment.pickup) %}
<div class="py-6 first:pt-0 last:pb-0 sm:grid sm:grid-cols-3 sm:gap-4"> {% if pickup is not null %}
<dt class="text-sm font-bold leading-6 text-gray-900"> <div class="py-6 first:pt-0 last:pb-0 sm:grid sm:grid-cols-3 sm:gap-4">
Busbegleitung <dt class="text-sm font-bold leading-6 text-gray-900">
</dt> Busbegleitung
<dd class="mt-1 text-sm leading-6 text-gray-700 sm:col-span-2 sm:mt-0"> </dt>
ab {{ pickup.city }}, {{ pickup.street }} <dd class="mt-1 text-sm leading-6 text-gray-700 sm:col-span-2 sm:mt-0">
</dd> ab {{ pickup.city }}, {{ pickup.street }}
</div> </dd>
<div class="py-6 first:pt-0 last:pb-0 sm:grid sm:grid-cols-3 sm:gap-4"> </div>
<dt class="text-sm font-bold leading-6 text-gray-900"> <div class="py-6 first:pt-0 last:pb-0 sm:grid sm:grid-cols-3 sm:gap-4">
Busabfahrt <dt class="text-sm font-bold leading-6 text-gray-900">
</dt> Busabfahrt
<dd class="mt-1 text-sm leading-6 text-gray-700 sm:col-span-2 sm:mt-0"> </dt>
{{ pickup.time }} Uhr <dd class="mt-1 text-sm leading-6 text-gray-700 sm:col-span-2 sm:mt-0">
</dd> {{ pickup.time }} Uhr
</div> </dd>
</div>
{% endif %}
{% endif %} {% endif %}
{% if application is defined and application is not null and application.pickup is not null %} {% if application is defined and application is not null and application.pickup is not null %}
<div class="py-6 first:pt-0 last:pb-0 sm:grid sm:grid-cols-3 sm:gap-4"> <div class="py-6 first:pt-0 last:pb-0 sm:grid sm:grid-cols-3 sm:gap-4">
@@ -1,12 +0,0 @@
<dl class="divide-y divide-gray-100">
{% for item in items %}
<div class="py-6 first:pt-0 last:pb-0 sm:grid sm:grid-cols-3 sm:gap-4">
<dt class="text-sm font-bold leading-6 text-gray-900">
{{ item.type }}
</dt>
<dd class="mt-1 text-sm leading-6 text-gray-700 sm:col-span-2 sm:mt-0">
{{ item.description }}
</dd>
</div>
{% endfor %}
</dl>
-4
View File
@@ -1,4 +0,0 @@
<div class="flex items-start space-x-4 bg-red-600 text-white p-4 rounded-md w-full">
{{ icon('alert', 'w-6 h-6 shrink-0') }}
<span>{{ message }}</span>
</div>
-4
View File
@@ -1,4 +0,0 @@
<div class="flex items-start space-x-4 bg-primary text-white p-4 rounded-md w-full">
{{ icon('info', 'w-6 h-6 shrink-0') }}
<span>{{ message }}</span>
</div>
@@ -1,6 +0,0 @@
{% set averageRating = teamer.averageRating %}
<div class="inline-flex items-center"{% if teamer.averageRating %}{{ stimulus_controller('tooltip', { content: averageRating|format_rating|raw, placement: 'top' }) }}{% endif %}>
{% for grade in range(1, 5) %}
{{ icon('star', html_classes('w-4 h-4', { 'text-gray-200': averageRating < grade * 100, 'text-primary': averageRating >= grade * 100 })) }}
{% endfor %}
</div>
@@ -47,7 +47,7 @@
<span>{{ application.teamer }}</span> <span>{{ application.teamer }}</span>
{{ icon('info', 'w-4 h-4') }} {{ icon('info', 'w-4 h-4') }}
</button> </button>
{% include '_partials/_rating_stars.html.twig' with { 'teamer': application.teamer } %} <twig:RatingStars averageRating="{{ application.teamer.averageRating }}" />
</td> </td>
<td> <td>
{{ application.pickup|bpn_pickup_label|default('-') }} {{ application.pickup|bpn_pickup_label|default('-') }}
@@ -138,7 +138,7 @@
<span>{{ disposition.teamer }}</span> <span>{{ disposition.teamer }}</span>
{{ icon('info', 'w-4 h-4') }} {{ icon('info', 'w-4 h-4') }}
</button> </button>
{% include '_partials/_rating_stars.html.twig' with { 'teamer': disposition.teamer } %} <twig:RatingStars averageRating="{{ disposition.teamer.averageRating }}" />
</td> </td>
<td> <td>
{{ disposition.remarks|nl2br|default('-') }} {{ disposition.remarks|nl2br|default('-') }}
@@ -149,40 +149,38 @@
hx-target="body" hx-target="body"
hx-swap="beforeend"> hx-swap="beforeend">
<span class="whitespace-nowrap">{{ disposition.teamer }}</span> <span class="whitespace-nowrap">{{ disposition.teamer }}</span>
{% include '_partials/_rating_stars.html.twig' with { 'teamer': disposition.teamer } %} <twig:RatingStars averageRating="{{ disposition.teamer.averageRating }}" />
</div> </div>
</li> </li>
{% endfor %} {% endfor %}
</ul> </ul>
</td> </td>
<td> <td>
{% embed '_partials/_dropdown.html.twig' %} <twig:DropDown>
{% block items %} <button type="button"
<button type="button" class="text-red-500 hover:text-primary block px-4 py-2 text-sm w-full text-left"
class="text-red-500 hover:text-primary block px-4 py-2 text-sm w-full text-left" role="menuitem"
role="menuitem" tabindex="-1"
tabindex="-1" hx-get="{{ path('app_administrative_assignment_delete', { 'uuid': assignment.uuid }) }}"
hx-get="{{ path('app_administrative_assignment_delete', { 'uuid': assignment.uuid }) }}" hx-target="body"
hx-target="body" hx-swap="beforeend">
hx-swap="beforeend"> löschen
löschen </button>
</button> <a href="{{ path('app_administrative_assignment_duplicate', { 'uuid': assignment.uuid, 'r': return_url() }) }}"
<a href="{{ path('app_administrative_assignment_duplicate', { 'uuid': assignment.uuid, 'r': return_url() }) }}" class="text-gray-700 hover:text-primary block px-4 py-2 text-sm"
role="menuitem"
tabindex="-1">
duplizieren
</a>
{% if is_granted('EDIT', assignment) %}
<a href="{{ path('app_administrative_assignment_edit', { 'uuid': assignment.uuid, 'r': return_url() }) }}"
class="text-gray-700 hover:text-primary block px-4 py-2 text-sm" class="text-gray-700 hover:text-primary block px-4 py-2 text-sm"
role="menuitem" role="menuitem"
tabindex="-1"> tabindex="-1">
duplizieren bearbeiten
</a> </a>
{% if is_granted('EDIT', assignment) %} {% endif %}
<a href="{{ path('app_administrative_assignment_edit', { 'uuid': assignment.uuid, 'r': return_url() }) }}" </twig:DropDown>
class="text-gray-700 hover:text-primary block px-4 py-2 text-sm"
role="menuitem"
tabindex="-1">
bearbeiten
</a>
{% endif %}
{% endblock %}
{% endembed %}
</td> </td>
</tr> </tr>
{% else %} {% else %}
@@ -66,7 +66,7 @@
{{ icon('user', 'w-10 h-10 text-gray-200') }} {{ icon('user', 'w-10 h-10 text-gray-200') }}
</div> </div>
{% endif %} {% endif %}
{% include '_partials/_rating_stars.html.twig' with { 'teamer': teamer } %} <twig:RatingStars averageRating="{{ teamer.averageRating }}" />
</div> </div>
</td> </td>
<td> <td>
@@ -45,7 +45,7 @@
{{ icon('user', 'w-32 h-32 text-gray-200') }} {{ icon('user', 'w-32 h-32 text-gray-200') }}
</div> </div>
{% endif %} {% endif %}
{% include '_partials/_rating_stars.html.twig' with { 'teamer': teamer } %} <twig:RatingStars averageRating="{{ teamer.averageRating }}"/>
<ul class="pb-8 divide-y divide-gray-200"> <ul class="pb-8 divide-y divide-gray-200">
{% if teamer.communication.phone %} {% if teamer.communication.phone %}
<li class="py-2"> <li class="py-2">
@@ -6,7 +6,7 @@
<div class="hidden group-hover:block absolute right-0 top-0 z-10 w-56 origin-top-right pt-4" role="menu" aria-orientation="vertical" aria-labelledby="menu-button" tabindex="-1"> <div class="hidden group-hover:block absolute right-0 top-0 z-10 w-56 origin-top-right pt-4" role="menu" aria-orientation="vertical" aria-labelledby="menu-button" tabindex="-1">
<div class="rounded-md bg-white shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none"> <div class="rounded-md bg-white shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none">
<div class="py-1 menu menu--pulldown" role="none"> <div class="py-1 menu menu--pulldown" role="none">
{% block items %}{% endblock %} {% block content %}{% endblock %}
</div> </div>
</div> </div>
</div> </div>
@@ -0,0 +1,4 @@
<div class="{{ html_classes('flex items-start space-x-4 text-white p-4 rounded-md w-full', { 'bg-primary': type != 'error', 'bg-red-500': type == 'error' }) }}">
{{ icon(type == 'error' ? 'alert' : 'info', 'w-6 h-6 shrink-0') }}
<span>{{ message }}</span>
</div>
@@ -0,0 +1,5 @@
<div class="inline-flex items-center"{% if averageRating %}{{ stimulus_controller('tooltip', { content: averageRating|format_rating|raw, placement: 'top' }) }}{% endif %}>
{% for grade in range(1, 5) %}
{{ icon('star', html_classes('w-4 h-4', { 'text-gray-200': averageRating < grade * 100, 'text-primary': averageRating >= grade * 100 })) }}
{% endfor %}
</div>
+4 -12
View File
@@ -15,28 +15,20 @@
{% include '_partials/_assignment_requirements_info.html.twig' %} {% include '_partials/_assignment_requirements_info.html.twig' %}
<div class="flex flex-col items-start space-y-4"> <div class="flex flex-col items-start space-y-4">
{% if disposition is not null %} {% if disposition is not null %}
{% include '_partials/_infobox.html.twig' with { <twig:MessageBox message="Du wurdest am {{ disposition.createdAt|date('d.m.Y') }} für diesen Einsatz eingeteilt."/>
'message': 'Du wurdest am ' ~ disposition.createdAt|date('d.m.Y') ~ ' für diesen Einsatz eingeteilt.'
} %}
{% elseif application is not null %} {% elseif application is not null %}
{% if application.status == constant('App\\Entity\\Application::STATUS_REJECTED') %} {% if application.status == constant('App\\Entity\\Application::STATUS_REJECTED') %}
{% include '_partials/_errorbox.html.twig' with { <twig:MessageBox message="Deine Bewerbung wurde leider abgelehnt." type="error"/>
'message': 'Deine Bewerbung wurde leider abgelehnt.'
} %}
{% if application.comment and application.commentVisible %} {% if application.comment and application.commentVisible %}
<strong>Begründung:</strong> {{ application.comment|nl2br}} <strong>Begründung:</strong> {{ application.comment|nl2br}}
{% endif %} {% endif %}
{% elseif application.status == constant('App\\Entity\\Application::STATUS_PENDING') %} {% elseif application.status == constant('App\\Entity\\Application::STATUS_PENDING') %}
{% include '_partials/_infobox.html.twig' with { <twig:MessageBox message="Deine Bewerbung befindet sich in Bearbeitung."/>
'message': 'Deine Bewerbung befindet sich in Bearbeitung.'
} %}
{% if application.comment and application.commentVisible %} {% if application.comment and application.commentVisible %}
<strong>Begründung:</strong> {{ application.comment|nl2br}} <strong>Begründung:</strong> {{ application.comment|nl2br}}
{% endif %} {% endif %}
{% else %} {% else %}
{% include '_partials/_infobox.html.twig' with { <twig:MessageBox message="Du hast dich am {{ application.createdAt|date('d.m.Y') }} auf diesen Einsatz beworben."/>
'message': 'Du hast dich am ' ~ application.createdAt|date('d.m.Y') ~ ' auf diesen Einsatz beworben.'
} %}
<button type="button" <button type="button"
class="btn btn--secondary" class="btn btn--secondary"
title="Bewerbung zurückziehen" title="Bewerbung zurückziehen"
+6 -4
View File
@@ -21,10 +21,12 @@
</div> </div>
{% if assignment.pickup %} {% if assignment.pickup %}
{% set pickup = assignment.destination.pickup(assignment.pickup) %} {% set pickup = assignment.destination.pickup(assignment.pickup) %}
<div class="flex items-start space-x-2"> {% if pickup is not null %}
{{ icon('bus', 'w-5 h-5 shrink-0') }} <div class="flex items-start space-x-2">
<span>{{ pickup.city }}, {{ pickup.time }} Uhr</span> {{ icon('bus', 'w-5 h-5 shrink-0') }}
</div> <span>{{ pickup.city }}, {{ pickup.time }} Uhr</span>
</div>
{% endif %}
{% endif %} {% endif %}
</div> </div>
<a href="{{ path('app_teamer_disposition_detail', { 'uuid': disposition.uuid, 'r': return_url() }) }}" <a href="{{ path('app_teamer_disposition_detail', { 'uuid': disposition.uuid, 'r': return_url() }) }}"
@@ -33,9 +33,7 @@
{# Existing upload has been rejected #} {# Existing upload has been rejected #}
{% set contract = disposition.documentByType('contract') %} {% set contract = disposition.documentByType('contract') %}
{% if contract and contract.status == constant('App\\Entity\\Upload::STATUS_REJECTED') %} {% if contract and contract.status == constant('App\\Entity\\Upload::STATUS_REJECTED') %}
{% include '_partials/_errorbox.html.twig' with { <twig:MessageBox message="Dein Honorarvertrag muss überarbeitet werden" type="error"/>
'message': 'Dein Honorarvertrag muss überarbeitet werden'
} %}
{% if contract.comment %} {% if contract.comment %}
<div class="py-2"> <div class="py-2">
<strong>Begründung:</strong> {{ contract.comment|nl2br }} <strong>Begründung:</strong> {{ contract.comment|nl2br }}
@@ -68,7 +66,7 @@
{{ form_end(form) }} {{ form_end(form) }}
{% else %} {% else %}
{% for blocker in workflow_transition_blockers(disposition, 'upload_contract') %} {% for blocker in workflow_transition_blockers(disposition, 'upload_contract') %}
{% include '_partials/_infobox.html.twig' with { 'message': blocker.message } %} <twig:MessageBox message="{{ blocker.message }}"/>
{% endfor %} {% endfor %}
{% endif %} {% endif %}
{% endif %} {% endif %}
@@ -99,7 +97,7 @@
{{ form_end(form) }} {{ form_end(form) }}
{% else %} {% else %}
{% for blocker in workflow_transition_blockers(disposition, 'upload_invoice') %} {% for blocker in workflow_transition_blockers(disposition, 'upload_invoice') %}
{% include '_partials/_infobox.html.twig' with { 'message': blocker.message } %} <twig:MessageBox message="{{ blocker.message }}"/>
{% endfor %} {% endfor %}
{% endif %} {% endif %}
{% endif %} {% endif %}
@@ -116,9 +114,7 @@
{# Existing upload is being checked #} {# Existing upload is being checked #}
{% set contract = disposition.documentByType('contract') %} {% set contract = disposition.documentByType('contract') %}
{% if contract and contract.status == constant('App\\Entity\\Upload::STATUS_PENDING') %} {% if contract and contract.status == constant('App\\Entity\\Upload::STATUS_PENDING') %}
{% include '_partials/_infobox.html.twig' with { <twig:MessageBox message="Dein Honorarvertrag befindet sich in Bearbeitung"/>
'message': 'Dein Honorarvertrag befindet sich in Bearbeitung'
} %}
{% if contract.comment %} {% if contract.comment %}
<div class="py-2"> <div class="py-2">
<strong>Begründung:</strong> {{ contract.comment|nl2br }} <strong>Begründung:</strong> {{ contract.comment|nl2br }}