diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php index b9e0b3d4c..ba45daf42 100644 --- a/.php-cs-fixer.dist.php +++ b/.php-cs-fixer.dist.php @@ -1,4 +1,5 @@ true, - 'native_function_invocation' => ['include' => ['@internal', 'all']], - 'final_internal_class' => true, - 'header_comment' => ['header' => $comment, 'location' => 'after_open', 'separate' => 'bottom'], - 'blank_line_before_statement' => ['statements' => ['declare', 'try', 'return']], + 'strict_param' => true, + 'php_unit_strict' => true, + 'no_useless_else' => true, 'no_unused_imports' => true, + 'no_useless_return' => true, 'strict_comparison' => true, - 'strict_param' => true, - 'ordered_imports' => ['imports_order' => ['const', 'class', 'function']], - 'ordered_class_elements' => ['sort_algorithm' => 'alpha'], + 'ordered_interfaces' => true, + 'final_internal_class' => true, + 'method_chaining_indentation' => true, 'concat_space' => ['spacing' => 'one'], - 'array_syntax' => ['syntax' => 'short'], 'list_syntax' => ['syntax' => 'short'], + 'array_syntax' => ['syntax' => 'short'], + 'ordered_class_elements' => ['sort_algorithm' => 'alpha'], + 'attribute_empty_parentheses' => ['use_parentheses' => false], 'doctrine_annotation_array_assignment' => ['operator' => '='], - 'ordered_interfaces' => true, - 'no_useless_else' => true, - 'no_useless_return' => true, - 'php_unit_strict' => true, + 'native_function_invocation' => ['include' => ['@internal', 'all']], 'php_unit_test_case_static_method_calls' => ['call_type' => 'self'], + 'new_with_braces' => ['anonymous_class' => true, 'named_class' => true], + 'ordered_imports' => ['imports_order' => ['const', 'class', 'function']], + 'blank_line_before_statement' => ['statements' => ['declare', 'try', 'return']], + 'header_comment' => [ + 'header' => $comment, + 'location' => 'after_open', + 'separate' => 'bottom'], 'phpdoc_to_comment' => [ + 'allow_before_return_statement' => true, 'ignored_tags' => ['phpstan-var', 'psalm-suppress'], - 'allow_before_return_statement' => true ], - 'attribute_empty_parentheses' => ['use_parentheses' => false], - 'new_with_braces' => ['anonymous_class' => true, 'named_class' => true], - ]; $finder = Finder::create() ->in(__DIR__ . '/config') ->in(__DIR__ . '/src') - ->in(__DIR__ . '/tests'); + ->in(__DIR__ . '/tests') + ->append([ + __FILE__, + __DIR__ . '/public/index.php', + __DIR__ . '/.twig-cs-fixer.php', + __DIR__ . '/rector.php', + ]); $config = new Config(); return $config - ->setParallelConfig(ParallelConfigFactory::detect()) ->setCacheFile(__DIR__ . '/var/cache/php-cs-fixer/.php-cs-fixer.cache') + ->setParallelConfig(ParallelConfigFactory::detect()) ->setRiskyAllowed(true) ->setFinder($finder) ->setRules($rules); diff --git a/.twig-cs-fixer.php b/.twig-cs-fixer.php index bb25810fa..fb4836e5b 100644 --- a/.twig-cs-fixer.php +++ b/.twig-cs-fixer.php @@ -1,4 +1,5 @@ =8.0.2", + "php": ">=8.1.0", "symfony/deprecation-contracts": "^2.5|^3", "tijsverkoyen/css-to-inline-styles": "^2.0", "twig/twig": "^3.13|^4.0" @@ -7956,7 +7956,7 @@ "twig" ], "support": { - "source": "https://github.com/twigphp/cssinliner-extra/tree/v3.19.0" + "source": "https://github.com/twigphp/cssinliner-extra/tree/v3.20.0" }, "funding": [ { @@ -7968,24 +7968,24 @@ "type": "tidelift" } ], - "time": "2024-09-03T13:08:40+00:00" + "time": "2025-01-31T20:45:36+00:00" }, { "name": "twig/extra-bundle", - "version": "v3.19.0", + "version": "v3.20.0", "source": { "type": "git", "url": "https://github.com/twigphp/twig-extra-bundle.git", - "reference": "9746573ca4bc1cd03a767a183faadaf84e0c31fa" + "reference": "9df5e1dbb6a68c0665ae5603f6f2c20815647876" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/twig-extra-bundle/zipball/9746573ca4bc1cd03a767a183faadaf84e0c31fa", - "reference": "9746573ca4bc1cd03a767a183faadaf84e0c31fa", + "url": "https://api.github.com/repos/twigphp/twig-extra-bundle/zipball/9df5e1dbb6a68c0665ae5603f6f2c20815647876", + "reference": "9df5e1dbb6a68c0665ae5603f6f2c20815647876", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1.0", "symfony/framework-bundle": "^5.4|^6.4|^7.0", "symfony/twig-bundle": "^5.4|^6.4|^7.0", "twig/twig": "^3.2|^4.0" @@ -8030,7 +8030,7 @@ "twig" ], "support": { - "source": "https://github.com/twigphp/twig-extra-bundle/tree/v3.19.0" + "source": "https://github.com/twigphp/twig-extra-bundle/tree/v3.20.0" }, "funding": [ { @@ -8042,25 +8042,25 @@ "type": "tidelift" } ], - "time": "2024-09-26T19:22:23+00:00" + "time": "2025-02-08T09:47:15+00:00" }, { "name": "twig/inky-extra", - "version": "v3.19.0", + "version": "v3.20.0", "source": { "type": "git", "url": "https://github.com/twigphp/inky-extra.git", - "reference": "60c92c2a435ccd95d7a852229f01098aaf7fbced" + "reference": "aacd79d94534b4a7fd6533cb5c33c4ee97239a0d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/inky-extra/zipball/60c92c2a435ccd95d7a852229f01098aaf7fbced", - "reference": "60c92c2a435ccd95d7a852229f01098aaf7fbced", + "url": "https://api.github.com/repos/twigphp/inky-extra/zipball/aacd79d94534b4a7fd6533cb5c33c4ee97239a0d", + "reference": "aacd79d94534b4a7fd6533cb5c33c4ee97239a0d", "shasum": "" }, "require": { "lorenzo/pinky": "^1.0.5", - "php": ">=8.0.2", + "php": ">=8.1.0", "symfony/deprecation-contracts": "^2.5|^3", "twig/twig": "^3.13|^4.0" }, @@ -8100,7 +8100,7 @@ "twig" ], "support": { - "source": "https://github.com/twigphp/inky-extra/tree/v3.19.0" + "source": "https://github.com/twigphp/inky-extra/tree/v3.20.0" }, "funding": [ { @@ -8112,24 +8112,24 @@ "type": "tidelift" } ], - "time": "2024-09-03T13:08:40+00:00" + "time": "2025-01-31T20:45:36+00:00" }, { "name": "twig/markdown-extra", - "version": "v3.19.0", + "version": "v3.20.0", "source": { "type": "git", "url": "https://github.com/twigphp/markdown-extra.git", - "reference": "6c464fc3e016ada9f17be4511daf2576ba4085c5" + "reference": "f4616e1dd375209dacf6026f846e6b537d036ce4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/markdown-extra/zipball/6c464fc3e016ada9f17be4511daf2576ba4085c5", - "reference": "6c464fc3e016ada9f17be4511daf2576ba4085c5", + "url": "https://api.github.com/repos/twigphp/markdown-extra/zipball/f4616e1dd375209dacf6026f846e6b537d036ce4", + "reference": "f4616e1dd375209dacf6026f846e6b537d036ce4", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1.0", "symfony/deprecation-contracts": "^2.5|^3", "twig/twig": "^3.13|^4.0" }, @@ -8172,7 +8172,7 @@ "twig" ], "support": { - "source": "https://github.com/twigphp/markdown-extra/tree/v3.19.0" + "source": "https://github.com/twigphp/markdown-extra/tree/v3.20.0" }, "funding": [ { @@ -8184,24 +8184,24 @@ "type": "tidelift" } ], - "time": "2025-01-19T15:54:05+00:00" + "time": "2025-01-31T20:45:36+00:00" }, { "name": "twig/string-extra", - "version": "v3.19.0", + "version": "v3.20.0", "source": { "type": "git", "url": "https://github.com/twigphp/string-extra.git", - "reference": "cb4eec11de02f63ad8ea9d065a1f27752d0bf752" + "reference": "4b3337544ac8f76c280def94e32b53acfaec0589" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/string-extra/zipball/cb4eec11de02f63ad8ea9d065a1f27752d0bf752", - "reference": "cb4eec11de02f63ad8ea9d065a1f27752d0bf752", + "url": "https://api.github.com/repos/twigphp/string-extra/zipball/4b3337544ac8f76c280def94e32b53acfaec0589", + "reference": "4b3337544ac8f76c280def94e32b53acfaec0589", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1.0", "symfony/string": "^5.4|^6.4|^7.0", "symfony/translation-contracts": "^1.1|^2|^3", "twig/twig": "^3.13|^4.0" @@ -8239,7 +8239,7 @@ "unicode" ], "support": { - "source": "https://github.com/twigphp/string-extra/tree/v3.19.0" + "source": "https://github.com/twigphp/string-extra/tree/v3.20.0" }, "funding": [ { @@ -8251,28 +8251,27 @@ "type": "tidelift" } ], - "time": "2024-11-30T08:42:13+00:00" + "time": "2025-01-31T20:45:36+00:00" }, { "name": "twig/twig", - "version": "v3.19.0", + "version": "v3.20.0", "source": { "type": "git", "url": "https://github.com/twigphp/Twig.git", - "reference": "d4f8c2b86374f08efc859323dbcd95c590f7124e" + "reference": "3468920399451a384bef53cf7996965f7cd40183" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/Twig/zipball/d4f8c2b86374f08efc859323dbcd95c590f7124e", - "reference": "d4f8c2b86374f08efc859323dbcd95c590f7124e", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/3468920399451a384bef53cf7996965f7cd40183", + "reference": "3468920399451a384bef53cf7996965f7cd40183", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1.0", "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-ctype": "^1.8", - "symfony/polyfill-mbstring": "^1.3", - "symfony/polyfill-php81": "^1.29" + "symfony/polyfill-mbstring": "^1.3" }, "require-dev": { "phpstan/phpstan": "^2.0", @@ -8319,7 +8318,7 @@ ], "support": { "issues": "https://github.com/twigphp/Twig/issues", - "source": "https://github.com/twigphp/Twig/tree/v3.19.0" + "source": "https://github.com/twigphp/Twig/tree/v3.20.0" }, "funding": [ { @@ -8331,7 +8330,7 @@ "type": "tidelift" } ], - "time": "2025-01-29T07:06:14+00:00" + "time": "2025-02-13T08:34:43+00:00" }, { "name": "vich/uploader-bundle", @@ -8614,16 +8613,16 @@ }, { "name": "myclabs/deep-copy", - "version": "1.12.1", + "version": "1.13.0", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "123267b2c49fbf30d78a7b2d333f6be754b94845" + "reference": "024473a478be9df5fdaca2c793f2232fe788e414" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/123267b2c49fbf30d78a7b2d333f6be754b94845", - "reference": "123267b2c49fbf30d78a7b2d333f6be754b94845", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/024473a478be9df5fdaca2c793f2232fe788e414", + "reference": "024473a478be9df5fdaca2c793f2232fe788e414", "shasum": "" }, "require": { @@ -8662,7 +8661,7 @@ ], "support": { "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.12.1" + "source": "https://github.com/myclabs/DeepCopy/tree/1.13.0" }, "funding": [ { @@ -8670,7 +8669,7 @@ "type": "tidelift" } ], - "time": "2024-11-08T17:47:46+00:00" + "time": "2025-02-12T12:17:51+00:00" }, { "name": "nikic/php-parser", diff --git a/public/index.php b/public/index.php index a7763ab01..634f50d6d 100644 --- a/public/index.php +++ b/public/index.php @@ -1,4 +1,5 @@ new Kernel((string) $context['APP_ENV'], (bool) $context['APP_DEBUG']); +return fn (array $context): Kernel => new Kernel((string) $context['APP_ENV'], (bool) $context['APP_DEBUG']); diff --git a/public/js/application/bootstrap_table.js b/public/js/application/bootstrap_table.js index a2f12bd6f..6389fbe7b 100644 --- a/public/js/application/bootstrap_table.js +++ b/public/js/application/bootstrap_table.js @@ -29,7 +29,7 @@ function customViewFormatter(data) { while (match !== null) { let value = undefinedText; const callback = match[1]; - if (typeof window[callback] !== 'undefined') { + if (window[callback]) { value = window[callback](row) || undefinedText; } html = html.replaceAll(match[0], value); @@ -77,7 +77,7 @@ function formatProductClass(row) { */ function styleBorderColor(_value, row) { 'use strict'; - if ($.isUndefined(row.color)) { + if (!row.color) { return {}; } return { @@ -118,7 +118,7 @@ function styleTextMuted(row, index) { if ($.parseInt(row.textMuted) !== 0) { return {}; } - const $row = $('#table-edit tbody tr:eq(' + index + ')'); + const $row = $(`#table-edit tbody tr:eq(${index})`); const classes = ($row.attr('class') || '') + ' text-body-secondary'; return { classes: classes.trim() @@ -595,21 +595,24 @@ $(function () { onPageChange: function () { // hide $('.card').trigger('click'); - if ($table.isCustomView()) { - $('.bootstrap-table .fixed-table-custom-view .custom-item').animate({'opacity': '0'}, 200); - $table.hideCustomViewMessage(); + if (!$table.isCustomView()) { + return; } + const $view = $table.getCustomView(); + const $items = $view.find('.custom-item'); + $items.animate({'opacity': '0'}, 200); + $table.hideCustomViewMessage(); }, onRenderCustomView: function (_$table, row, $item) { // update border color - if (typeof row.color !== 'undefined') { + if (row.color) { const style = `border-left-color: ${row.color} !important`; $item.attr('style', style); } // text-muted - if (typeof row.textMuted !== 'undefined') { + if (row.textMuted) { const value = $.parseInt(row.textMuted); if (value === 0) { $item.addClass('text-body-secondary'); diff --git a/public/js/extensions/bootstrap-table-extensions.js b/public/js/extensions/bootstrap-table-extensions.js index 98ebd9579..5324317ec 100644 --- a/public/js/extensions/bootstrap-table-extensions.js +++ b/public/js/extensions/bootstrap-table-extensions.js @@ -24,25 +24,33 @@ * @property {string} view - the display mode ('table' or 'custom'). * @property {string} searchText - the search text. * - * @typedef {jQuery} jQueryTable - the bootstrap table. + * @typedef {jQuery} jQueryTable - the bootstrap table. * @property {Options} getOptions - the options. * @property {boolean} isCustomView - true if custom view is displayed. - * @property {jQuery} getCustomView - get the custom view. + * @property {jQuery} getCustomView - get the custom view. * @property {jQueryTable} enableKeys - enable the key handler. * @property {jQueryTable} disableKeys - disable the key handler. */ +/** + * The loading message. + * @type {string|null} + */ +let loadingMessage = null; + /** * Gets the loading template. * * @param {string} message - the loading message. * @returns {string} the loading template. */ + function loadingTemplate(message) { 'use strict'; - return `` + if (loadingMessage === null) { + loadingMessage = $('#loading-template').html(); + } + return loadingMessage.replace('%message%', message); } /** @@ -85,7 +93,7 @@ $(function () { */ updateCustomRow: function ($table) { const index = $(this).parents('.col-custom-view').index(); - const $row = $table.find('tbody tr[data-index]:eq(' + index + ')'); + const $row = $table.find(`tbody tr[data-index]:eq(${index})`); if ($row.length) { return $row.updateRow($table); } @@ -100,18 +108,14 @@ $(function () { */ updateRow: function ($table) { const $row = $(this); - const options = $table.getOptions(); - const rowClass = options.rowClass; - // no data? if ($row.hasClass('no-records-found')) { return true; } - // already selected? - if ($row.hasClass(rowClass)) { - return true; - } + // get selection class + const options = $table.getOptions(); + const rowClass = options.rowClass; // remove old selection $table.find(options.rowSelector).removeClass(rowClass); @@ -121,9 +125,14 @@ $(function () { // custom view? if ($table.isCustomView()) { + // remove selection const $view = $table.getCustomView(); - $view.find('.custom-item.' + rowClass).removeClass(rowClass); - $view.find('.custom-item:eq(' + $row.index() + ')').addClass(rowClass); + $view.find(options.customSelector).removeClass(rowClass); + + // add selection + const index = $row.index(); + const selector = `.custom-item:eq(${index})`; + $view.find(selector).addClass(rowClass); } $table.showSelection(); $table.trigger('update-row.bs.table', this); @@ -182,9 +191,7 @@ $(function () { const isModal = $item.is('.page-first-separator,.page-last-separator'); const title = isModal ? modalTitle : $link.attr('aria-label'); $link.attr({ - 'href': '#', - 'title': title, - 'aria-label': title + 'href': '#', 'title': title, 'aria-label': title }); if (isModal) { $item.removeClass('disabled'); @@ -202,12 +209,11 @@ $(function () { }, onCustomViewPostBody: function (data) { - const $view = $this.getCustomView(); - // data? if (data.length !== 0) { // hide the empty data message $this.hideCustomViewMessage(); + const $view = $this.getCustomView(); const params = $this.getParameters(); const selector = '.custom-view-actions:eq(%index%)'; const callback = typeof options.onRenderCustomView === 'function' ? options.onRenderCustomView : false; @@ -217,7 +223,6 @@ $(function () { const rowSelector = selector.replace('%index%', '' + index); const $customActions = $view.find(rowSelector); $rowActions.appendTo($customActions); - if (callback) { const row = data[index]; const $item = $customActions.parents('.custom-item'); @@ -226,9 +231,9 @@ $(function () { }); // display selection - const $selection = $view.find(options.customSelector); - if ($selection.length) { - $selection.scrollInViewport(); + const $row = $this.getSelection(); + if ($row) { + $row.updateRow($this); } $this.highlight(); } else { @@ -427,6 +432,16 @@ $(function () { return $row.length ? $row : null; }, + /** + * Gets the selected row index. + * + * @return {int} the selected row index, if any; -1 otherwise. + */ + getSelectionIndex: function () { + const $row = $(this).getSelection(); + return $row ? $row.index() : -1; + }, + /** * Scroll the selected row, if any, into the visible area of the browser window. * @@ -435,24 +450,24 @@ $(function () { showSelection: function () { const $this = $(this); let $row = $this.getSelection(); - if ($row) { - if ($this.isCustomView()) { - $row = $this.getCustomView().find('.custom-item:eq(' + $row.index() + ')'); - } - $row.scrollInViewport(); + if (!$row) { + return this; } + + if ($this.isCustomView()) { + const index = $row.index(); + const options = $this.getOptions(); + const rowClass = options.rowClass; + const $view = $this.getCustomView(); + const selector = `.custom-item:eq(${index})`; + $row = $view.find(selector); + $row.addClass(rowClass); + } + $row.scrollInViewport(); + return $this; }, - /** - * Gets the selected row index. - * - * @return {int} the selected row index, if any; -1 otherwise. - */ - getSelectionIndex: function () { - const $row = $(this).getSelection(); - return $row ? $row.index() : -1; - }, /** * Gets the custom view container. @@ -461,12 +476,13 @@ $(function () { */ getCustomView: function () { const $this = $(this); - if ($this.isCustomView()) { - /** @type {jQuery} */ - const $parent = $this.parents('.bootstrap-table'); - return $parent.find('.fixed-table-custom-view'); + if (!$this.isCustomView()) { + return null; } - return null; + + /** @type {jQuery} */ + const $parent = $this.parents('.bootstrap-table'); + return $parent.find('.fixed-table-custom-view'); }, /** @@ -594,18 +610,19 @@ $(function () { highlight: function () { const $this = $(this); const text = $this.getSearchText(); - if (text.length > 0) { - const options = { - element: 'span', - className: 'text-success', - separateWordSearch: false, - ignorePunctuation: ['\'', ','] - }; - if ($this.isCustomView()) { - $this.getCustomView().find('.custom-item').mark(text, options); - } else { - $this.find('tbody td:not(.rowlink-skip)').mark(text, options); - } + if (!text) { + return $this; + } + const options = { + element: 'span', + className: 'text-success', + separateWordSearch: false, + ignorePunctuation: ['\'', ','] + }; + if ($this.isCustomView()) { + $this.getCustomView().find('.custom-item').mark(text, options); + } else { + $this.find('tbody td:not(.rowlink-skip)').mark(text, options); } return $this; }, @@ -677,13 +694,11 @@ $(function () { const options = this.getOptions(); if (options.sortName !== sortName || options.sortOrder !== sortOrder) { $(this).bootstrapTable('sortBy', { - field: sortName, - sortOrder: sortOrder + field: sortName, sortOrder: sortOrder }); } return this; - }, - /** + }, /** * Select the first row. * * @return {boolean} true if the first row is selected. diff --git a/scss/bootstrap.scss b/scss/bootstrap.scss index ba2366b0f..3e48952cb 100644 --- a/scss/bootstrap.scss +++ b/scss/bootstrap.scss @@ -67,16 +67,32 @@ $tooltip-opacity: 1.0; @include border-radius($form-switch-border-radius, $form-switch-border-radius); } +/* keep form-range rounded */ +.form-range { + &::-webkit-slider-thumb { + @include border-radius($form-range-thumb-border-radius, $form-range-thumb-border-radius); + } + &::-webkit-slider-runnable-track { + @include border-radius($form-range-track-border-radius, $form-range-thumb-border-radius); + } + &::-moz-range-thumb { + @include border-radius($form-range-track-border-radius, $form-range-thumb-border-radius); + } + &::-moz-range-track { + @include border-radius($form-range-track-border-radius, $form-range-thumb-border-radius); + } +} + /* light theme exceptions */ html[data-bs-theme=light] { - .popover-light { + .popover.popover-light { #{prefix-property(popover-border-color)}: #{var-property(light-border-subtle)}; } } /* dark theme exceptions */ html[data-bs-theme=dark] { - .popover-dark { + .popover.popover-dark { #{prefix-property(popover-border-color)}: #{var-property(dark-border-subtle)}; } diff --git a/src/Controller/AjaxController.php b/src/Controller/AjaxController.php index 44be11f45..85a97976d 100644 --- a/src/Controller/AjaxController.php +++ b/src/Controller/AjaxController.php @@ -121,7 +121,7 @@ public function saveSession(#[MapRequestPayload] SessionQuery $query): JsonRespo } /** - * Save table parameters. + * Save table view parameter. * * @psalm-api */ @@ -131,10 +131,9 @@ public function saveTable( Request $request, UserService $service ): JsonResponse { - $value = $request->request->getString(TableInterface::PARAM_VIEW); - $view = TableView::tryFrom($value) ?? TableView::TABLE; $response = $this->json(true); $path = $this->getCookiePath(); + $view = $this->getRequestEnum($request, TableInterface::PARAM_VIEW, TableView::TABLE); $this->updateCookie($response, TableInterface::PARAM_VIEW, $view, path: $path); $service->setProperty(PropertyServiceInterface::P_DISPLAY_MODE, $view); diff --git a/src/Report/ReportFooter.php b/src/Report/ReportFooter.php index d3d8e6d64..2828bf797 100644 --- a/src/Report/ReportFooter.php +++ b/src/Report/ReportFooter.php @@ -29,7 +29,7 @@ class ReportFooter /** * The footer offset in millimeters. */ - final public const FOOTER_OFFSET = 15.0; + final public const FOOTER_OFFSET = 13.0; /** * The content text. @@ -55,7 +55,7 @@ public function __construct(private readonly AbstractReport $parent) */ public function output(): void { - $this->parent->useCellMargin(fn () => $this->outputTexts()); + $this->parent->useCellMargin(fn () => $this->outputFooter()); } /** @@ -71,37 +71,15 @@ public function setContent(string $content, ?string $url = null): self return $this; } - private function outputContent(float $width): self - { - return $this->outputText($this->content, $width, PdfTextAlignment::CENTER, $this->url); - } - - private function outputDate(float $width): void - { - $text = $this->date ??= FormatUtils::formatDateTime(new \DateTime()); - - $this->outputText($text, $width, PdfTextAlignment::RIGHT); - } - - private function outputPages(float $width): self - { - $parent = $this->parent; - $text = $parent->trans('report.page', [ - '{0}' => $parent->getPage(), - '{1}' => $parent->getAliasNumberPages(), - ]); - - return $this->outputText($text, $width, PdfTextAlignment::LEFT); - } - /** * Output the given text. */ - private function outputText(?string $text, float $width, PdfTextAlignment $align, ?string $link = null): self + private function outputCell(?string $text, float $width, PdfTextAlignment $align, ?string $link = null): self { $text ??= ''; $this->parent->cell( width: $width, + height: PdfDocument::LINE_HEIGHT - 2.0, text: $text, border: PdfBorder::top(), align: $align, @@ -111,15 +89,38 @@ private function outputText(?string $text, float $width, PdfTextAlignment $align return $this; } - private function outputTexts(): void + private function outputContent(float $width): self + { + return $this->outputCell($this->content, $width, PdfTextAlignment::CENTER, $this->url); + } + + private function outputDate(float $width): void + { + $text = $this->date ??= FormatUtils::formatDateTime(new \DateTime()); + + $this->outputCell($text, $width, PdfTextAlignment::RIGHT); + } + + private function outputFooter(): void { $parent = $this->parent; $parent->setY(-self::FOOTER_OFFSET); $width = $parent->getPrintableWidth() / 3.0; - PdfStyle::default()->setFontSize(PdfDocument::LINE_HEIGHT - 1.0)->apply($parent); + PdfStyle::default()->setFontSize(6.0)->apply($parent); $this->outputPages($width) ->outputContent($width) ->outputDate($width); $parent->resetStyle(); } + + private function outputPages(float $width): self + { + $parent = $this->parent; + $text = $parent->trans('report.page', [ + '{0}' => $parent->getPage(), + '{1}' => $parent->getAliasNumberPages(), + ]); + + return $this->outputCell($text, $width, PdfTextAlignment::LEFT); + } } diff --git a/src/Report/ReportHeader.php b/src/Report/ReportHeader.php index 89730a986..caf92d3f2 100644 --- a/src/Report/ReportHeader.php +++ b/src/Report/ReportHeader.php @@ -104,7 +104,7 @@ public function getHeight(): float */ public function output(): void { - $this->parent->useCellMargin(fn () => $this->outputLines()); + $this->parent->useCellMargin(fn () => $this->outputHeader()); } /** @@ -164,7 +164,7 @@ private function isPrintAddress(): bool private function outputAddress(float $cellWidth): void { $this->applySmallStyle(); - $this->outputText( + $this->outputCell( $cellWidth, self::SMALL_HEIGHT, $this->customer?->getAddress(), @@ -174,6 +174,27 @@ private function outputAddress(float $cellWidth): void ); } + private function outputCell( + float $width, + float $height, + ?string $text, + PdfBorder $border, + PdfTextAlignment $align, + PdfMove $move = PdfMove::RIGHT, + string|int|null $link = null + ): void { + $text ??= ''; + $this->parent->cell( + width: $width, + height: $height, + text: $text, + border: $border, + move: $move, + align: $align, + link: '' !== $text ? $link : null + ); + } + private function outputDescription(): void { $description = StringUtils::trim($this->description); @@ -192,7 +213,7 @@ private function outputDescription(): void private function outputEmail(float $cellWidth): void { $this->applySmallStyle(); - $this->outputText( + $this->outputCell( $cellWidth, self::SMALL_HEIGHT, $this->customer?->getEmail(), @@ -201,7 +222,7 @@ private function outputEmail(float $cellWidth): void ); } - private function outputLines(): void + private function outputHeader(): void { $parent = $this->parent; $isAddress = $this->isPrintAddress(); @@ -222,7 +243,7 @@ private function outputName(float $cellWidth, bool $isAddress): void { $this->applyNameStyle(); $border = $isAddress ? PdfBorder::none() : PdfBorder::bottom(); - $this->outputText( + $this->outputCell( $cellWidth, self::LINE_HEIGHT, $this->customer?->getName(), @@ -236,7 +257,7 @@ private function outputName(float $cellWidth, bool $isAddress): void private function outputPhone(float $cellWidth): void { $this->applySmallStyle(); - $this->outputText( + $this->outputCell( $cellWidth, self::SMALL_HEIGHT, $this->customer?->getPhone(), @@ -245,32 +266,11 @@ private function outputPhone(float $cellWidth): void ); } - private function outputText( - float $width, - float $height, - ?string $text, - PdfBorder $border, - PdfTextAlignment $align, - PdfMove $move = PdfMove::RIGHT, - string|int|null $link = null - ): void { - $text ??= ''; - $this->parent->cell( - width: $width, - height: $height, - text: $text, - border: $border, - move: $move, - align: $align, - link: '' !== $text ? $link : null - ); - } - private function outputTitle(float $cellWidth, bool $isAddress): void { $this->applyTitleStyle(); $border = $isAddress ? PdfBorder::none() : PdfBorder::bottom(); - $this->outputText( + $this->outputCell( $cellWidth, self::LINE_HEIGHT, $this->parent->getTitle(), @@ -282,7 +282,7 @@ private function outputTitle(float $cellWidth, bool $isAddress): void private function outputZipCity(float $cellWidth): void { $this->applySmallStyle(); - $this->outputText( + $this->outputCell( $cellWidth, self::SMALL_HEIGHT, $this->customer?->getZipCity(), diff --git a/templates/calculationstate/calculationstate_table.html.twig b/templates/calculationstate/calculationstate_table.html.twig index 72ec8195b..9cd0ae328 100644 --- a/templates/calculationstate/calculationstate_table.html.twig +++ b/templates/calculationstate/calculationstate_table.html.twig @@ -58,6 +58,6 @@ {% block custom_view_body -%} {{ _self.property_value('%description%') }} {{ _self.property_line() }} -{{ _self.property_row('calculationstate.fields.calculations', '%calculations%') }} {{ _self.property_row('calculationstate.fields.editable', '%editable%') }} +{{ _self.property_row('calculationstate.fields.calculations', '%calculations%') }} {%- endblock %} diff --git a/templates/cards/card_table.html.twig b/templates/cards/card_table.html.twig index e5908eaf9..d0ed84304 100644 --- a/templates/cards/card_table.html.twig +++ b/templates/cards/card_table.html.twig @@ -297,6 +297,12 @@ +{# loading message template #} + {%- endblock -%} {# stylesheets #} {% block stylesheets %} diff --git a/templates/dialog/dialog_table_page.html.twig b/templates/dialog/dialog_table_page.html.twig index 5e6363301..6a6542a54 100644 --- a/templates/dialog/dialog_table_page.html.twig +++ b/templates/dialog/dialog_table_page.html.twig @@ -8,7 +8,7 @@