From 935c54a61fe0b0bfbc779e13c5818a35f823d6cd Mon Sep 17 00:00:00 2001 From: Kevin Papst <kpapst@gmx.net> Date: Fri, 21 Jan 2022 00:35:09 +0100 Subject: [PATCH] new export template --- src/Export/Base/RendererTrait.php | 8 +-- src/Invoice/Renderer/AbstractTwigRenderer.php | 41 +++--------- src/Twig/LocaleFormatExtensions.php | 2 +- src/Twig/TwigRendererTrait.php | 66 +++++++++++++++++++ templates/export/pdf-layout.html.twig | 37 ++++++----- templates/export/renderer/timesheet.pdf.twig | 18 +++++ translations/export.de.xlf | 4 ++ translations/export.en.xlf | 18 +++-- 8 files changed, 134 insertions(+), 60 deletions(-) create mode 100644 src/Twig/TwigRendererTrait.php create mode 100644 templates/export/renderer/timesheet.pdf.twig diff --git a/src/Export/Base/RendererTrait.php b/src/Export/Base/RendererTrait.php index bf091e2ee..32b6354c8 100644 --- a/src/Export/Base/RendererTrait.php +++ b/src/Export/Base/RendererTrait.php @@ -10,14 +10,14 @@ namespace App\Export\Base; use App\Activity\ActivityStatisticService; -use App\Export\ExportItemInterface; +use App\Invoice\InvoiceItemInterface; use App\Project\ProjectStatisticService; use App\Repository\Query\TimesheetQuery; trait RendererTrait { /** - * @param ExportItemInterface[] $exportItems + * @param InvoiceItemInterface[] $exportItems * @return array */ protected function calculateSummary(array $exportItems) @@ -130,7 +130,7 @@ trait RendererTrait } /** - * @param ExportItemInterface[] $exportItems + * @param InvoiceItemInterface[] $exportItems * @param TimesheetQuery $query * @param ProjectStatisticService $projectStatisticService * @return array @@ -209,7 +209,7 @@ trait RendererTrait } /** - * @param ExportItemInterface[] $exportItems + * @param InvoiceItemInterface[] $exportItems * @param TimesheetQuery $query * @param ActivityStatisticService $activityStatisticService * @return array diff --git a/src/Invoice/Renderer/AbstractTwigRenderer.php b/src/Invoice/Renderer/AbstractTwigRenderer.php index 4ceaf9092..7606b9667 100644 --- a/src/Invoice/Renderer/AbstractTwigRenderer.php +++ b/src/Invoice/Renderer/AbstractTwigRenderer.php @@ -12,9 +12,7 @@ namespace App\Invoice\Renderer; use App\Entity\InvoiceDocument; use App\Invoice\InvoiceModel; use App\Invoice\RendererInterface; -use App\Twig\LocaleFormatExtensions; -use Symfony\Bridge\Twig\Extension\TranslationExtension; -use Symfony\Contracts\Translation\LocaleAwareInterface; +use App\Twig\TwigRendererTrait; use Twig\Environment; /** @@ -22,6 +20,8 @@ use Twig\Environment; */ abstract class AbstractTwigRenderer implements RendererInterface { + use TwigRendererTrait; + /** * @var Environment */ @@ -34,39 +34,16 @@ abstract class AbstractTwigRenderer implements RendererInterface protected function renderTwigTemplate(InvoiceDocument $document, InvoiceModel $model): string { - $previousLocale = $this->changeTwigLocale($this->twig, $model->getTemplate()->getLanguage()); - - $content = $this->twig->render('@invoice/' . basename($document->getFilename()), [ + $language = $model->getTemplate()->getLanguage(); + $formatLocale = $model->getFormatter()->getLocale(); + $template = '@invoice/' . basename($document->getFilename()); + $options = [ // model should not be used in the future, but we can likely not remove it 'model' => $model, // new since 1.16.7 - templates should only use the pre-generated values 'invoice' => $model->toArray(), - ]); + ]; - $this->changeTwigLocale($this->twig, $previousLocale); - - return $content; - } - - private function changeTwigLocale(Environment $twig, ?string $locale = null): ?string - { - // for invoices that don't have a language configured (using request locale) - if (null === $locale) { - return null; - } - - /** @var TranslationExtension $extension */ - $extension = $twig->getExtension(TranslationExtension::class); - /** @var LocaleAwareInterface $translator */ - $translator = $extension->getTranslator(); - $previousLocale = $translator->getLocale(); - - $translator->setLocale($locale); - - /** @var LocaleFormatExtensions $extension */ - $extension = $twig->getExtension(LocaleFormatExtensions::class); - $extension->setLocale($locale); - - return $previousLocale; + return $this->renderTwigTemplateWithLanguage($this->twig, $template, $options, $language, $formatLocale); } } diff --git a/src/Twig/LocaleFormatExtensions.php b/src/Twig/LocaleFormatExtensions.php index c0c8d6dcf..ed709b5b3 100644 --- a/src/Twig/LocaleFormatExtensions.php +++ b/src/Twig/LocaleFormatExtensions.php @@ -137,7 +137,7 @@ final class LocaleFormatExtensions extends AbstractExtension return $this->formatter; } - private function getLocale() + public function getLocale(): string { if (null === $this->locale) { $this->locale = \Locale::getDefault(); diff --git a/src/Twig/TwigRendererTrait.php b/src/Twig/TwigRendererTrait.php new file mode 100644 index 000000000..66a175dcc --- /dev/null +++ b/src/Twig/TwigRendererTrait.php @@ -0,0 +1,66 @@ +<?php + +/* + * This file is part of the Kimai time-tracking app. + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace App\Twig; + +use Symfony\Bridge\Twig\Extension\TranslationExtension; +use Symfony\Contracts\Translation\LocaleAwareInterface; +use Twig\Environment; + +/** + * @internal + */ +trait TwigRendererTrait +{ + protected function renderTwigTemplateWithLanguage(Environment $twig, string $template, array $options = [], ?string $language = null, ?string $formatLocale = null): string + { + $previousTranslation = null; + $previousFormatLocale = null; + + if ($language === null) { + $previousTranslation = $this->switchTranslationLocale($twig, $language); + } + if ($formatLocale === null) { + $previousFormatLocale = $this->switchFormatLocale($twig, $formatLocale); + } + + $content = $twig->render($template, $options); + + if ($previousTranslation !== null) { + $this->switchTranslationLocale($twig, $previousTranslation); + } + if ($previousFormatLocale !== null) { + $this->switchFormatLocale($twig, $previousFormatLocale); + } + + return $content; + } + + protected function switchTranslationLocale(Environment $twig, string $language): string + { + /** @var TranslationExtension $extension */ + $extension = $twig->getExtension(TranslationExtension::class); + /** @var LocaleAwareInterface $translator */ + $translator = $extension->getTranslator(); + $previous = $translator->getLocale(); + $translator->setLocale($language); + + return $previous; + } + + protected function switchFormatLocale(Environment $twig, string $language): string + { + /** @var LocaleFormatExtensions $extension */ + $extension = $twig->getExtension(LocaleFormatExtensions::class); + $previous = $extension->getLocale(); + $extension->setLocale($language); + + return $previous; + } +} diff --git a/templates/export/pdf-layout.html.twig b/templates/export/pdf-layout.html.twig index dabe4010d..1aa1cb5d5 100644 --- a/templates/export/pdf-layout.html.twig +++ b/templates/export/pdf-layout.html.twig @@ -3,16 +3,18 @@ {% set showRateColumn = showRateColumn ?? is_granted('view_rate_other_timesheet') %} {% set showRateBudget = showRateBudget ?? false %} {% set showTimeBudget = showTimeBudget ?? false %} +{% set showCustomerSummary = showCustomerSummary ?? true %} {% set showTotalSummary = showTotalSummary ?? true %} +{% set showDateTimeShort = showDateTimeShort ?? false %} {% set now = create_date('now', app.user) %} {% set decimal = decimal ?? false %} {# this is only triggered, if a user exports from his personal timesheet screen #} -{% if query.user is not null %} +{% if query is defined and query.user is not null %} {% set showUserColumn = false %} {# if exporting via the admin screen, users without view_rate_own_timesheet might still see their own rates #} {% set showRateColumn = is_granted('view_rate_own_timesheet') %} {% endif %} -<html lang="{{ app.request.locale }}"> +<html{% if app.request is defined and app.request is not null %} lang="{{ app.request.locale }}"{% endif %}> <head> {% block styles %} <style> @@ -82,7 +84,7 @@ <tr> <td align="left"> {{ 'export.page_of'|trans({'%page%': '{PAGENO}', '%pages%': '{nb}'}) }} - {% if not showUserColumn and query.user %} + {% if not showUserColumn and query is defined and query.user %} – {{ 'label.user'|trans }}: {{ query.user.displayName }} {% endif %} @@ -102,11 +104,13 @@ mpdf--> {% endblock %} {% block summary %} - <h2 style="margin-bottom: 0; padding-bottom: 0">{{ 'export.document_title'|trans }}</h2> + <h2 style="margin-bottom: 4px; padding-bottom: 0">{% block title %}{{ 'export.document_title'|trans }}{% endblock %}</h2> + {% if query is defined %} <p> {{ 'export.period'|trans }}: {{ query.begin|date_short }} - {{ query.end|date_short }} </p> + {% endif %} <h3>{{ 'export.summary'|trans }}</h3> <table class="items"> <thead> @@ -206,7 +210,7 @@ mpdf--> {% set customerInternalRate = customerInternalRate + summary.rate_internal %} {% set customerCount = customerCount + 1 %} {% endfor %} - {% if customer is not same as(null) %} + {% if showCustomerSummary and customer is not same as(null) %} <tr class="summary"> <td colspan="2"></td> {% if showTimeBudget %} @@ -225,7 +229,7 @@ mpdf--> </tr> {% endif %} {% if showTotalSummary and not multiCurrency %} - <tr class="summary-total"> + <tr class="{% if not showCustomerSummary %}summary{% else %}summary-total{% endif %}"> <td class="totals" colspan="2"> {{ 'sum.total'|trans }} </td> @@ -285,21 +289,22 @@ mpdf--> {% endif %} <tr class="{{ cycle(['odd', 'even'], loop.index0) }}"> <td class="text-nowrap"> - {{ entry.begin|date_time }} + {% block date_begin %}{% if not showDateTimeShort %}{{ entry.begin|date_time }}{% else %}{{ entry.begin|date_short }}{% endif %}{% endblock %} {% if entry.end %} - <br> - {{ entry.end|date_time }} + {% block date_end %}{% if not showDateTimeShort %}<br>{{ entry.end|date_time }}{% endif %}{% endblock %} {% endif %} </td> {% if showUserColumn %} <td>{{ entry.user.displayName }}</td> {% endif %} <td> - {{ entry.project.customer.name }} - {{ entry.project.name }}{% if entry.activity is not null %} - {{ entry.activity.name }}{% endif %} - {% if entry.description is not empty %} - <br> - <i>{{ entry.description|desc2html }}</i> - {% endif %} + {% block description %} + {{ entry.project.customer.name }} - {{ entry.project.name }}{% if entry.activity is not null %} - {{ entry.activity.name }}{% endif %} + {% if entry.description is not empty %} + <br> + <i>{{ entry.description|desc2html }}</i> + {% endif %} + {% endblock %} </td> <td class="duration">{{ entry.duration|duration(decimal) }}</td> {% if showRateColumn %} @@ -318,9 +323,9 @@ mpdf--> {% endfor %} <tr class="summary"> {% if showUserColumn %} - <td colspan="3"></td> + <td colspan="3">{{ 'sum.total'|trans }}</td> {% else %} - <td colspan="2"></td> + <td colspan="2">{{ 'sum.total'|trans }}</td> {% endif %} <td class="totals duration">{{ duration|duration(decimal) }}</td> {% if showRateColumn %} diff --git a/templates/export/renderer/timesheet.pdf.twig b/templates/export/renderer/timesheet.pdf.twig new file mode 100644 index 000000000..5727b4ddc --- /dev/null +++ b/templates/export/renderer/timesheet.pdf.twig @@ -0,0 +1,18 @@ +{% extends 'export/pdf-layout.html.twig' %} +{% set showRateColumn = false %} +{% set showRateBudget = false %} +{% set showTimeBudget = false %} +{% set showUserColumn = true %} +{% set showCustomerSummary = false %} +{% set decimal = true %} +{% set showDateTimeShort = true %} +{% block title %}{{ 'timesheet.pdf.twig'|trans({}, 'export') }}{% endblock %} +{% block description %} + {% if entry.description is not empty %} + {{ entry.description|desc2html }} + {% elseif entry.activity is not null %} + {{ entry.activity.name }} + {% endif %} + <br> + <small>{{ entry.project.customer.name }}, {{ entry.project.name }}</small> +{% endblock %} \ No newline at end of file diff --git a/translations/export.de.xlf b/translations/export.de.xlf index 22a85f092..b43e2c251 100644 --- a/translations/export.de.xlf +++ b/translations/export.de.xlf @@ -14,6 +14,10 @@ <source>default-internal.pdf.twig</source> <target>Inkl. interner Kosten</target> </trans-unit> + <trans-unit id="bTIKMV." resname="timesheet.pdf.twig"> + <source>Timesheet</source> + <target>Stundennachweis</target> + </trans-unit> </body> </file> </xliff> diff --git a/translations/export.en.xlf b/translations/export.en.xlf index 09699b086..41f998ac6 100644 --- a/translations/export.en.xlf +++ b/translations/export.en.xlf @@ -2,18 +2,22 @@ <xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2"> <file source-language="en" target-language="en" datatype="plaintext" original="export.en.xlf"> <body> - <trans-unit id="oRRnhwf" resname="default.pdf.twig"> - <source>default.pdf.twig</source> - <target>Standard</target> + <trans-unit id="IbERy.5" resname="default.pdf.twig"> + <source>Default</source> + <target>Default</target> </trans-unit> - <trans-unit id="YjWg9hr" resname="default-budget.pdf.twig"> - <source>default-budget.pdf.twig</source> + <trans-unit id="Xvh5B5U" resname="default-budget.pdf.twig"> + <source>With remaining budget</source> <target>With remaining budget</target> </trans-unit> - <trans-unit id="AuhL8Sb" resname="default-internal.pdf.twig"> - <source>default-internal.pdf.twig</source> + <trans-unit id="rok3rBO" resname="default-internal.pdf.twig"> + <source>With internal rates</source> <target>With internal rates</target> </trans-unit> + <trans-unit id="bTIKMV." resname="timesheet.pdf.twig"> + <source>Timesheet</source> + <target>Timesheet</target> + </trans-unit> </body> </file> </xliff>