From 393c894cfb5d88c1199c6da6101d48dd8856d43a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20=C5=A0pa=C4=8Dek?= Date: Sat, 8 Jul 2023 17:24:00 +0200 Subject: [PATCH] Replace the admin shared training date list with a custom control/component From 94 level 4 errors to 66 with just this change. This is probably how https://github.com/efabrica-team/phpstan-latte/issues/391 should be solved, components suggested in https://github.com/spaze/michalspacek.cz/pull/143#issuecomment-1627296213 Docs https://doc.nette.org/cs/application/components https://doc.nette.org/en/application/creating-links#toc-links-in-component for {plink} The UiControl class is there mostly, I mean only to suppress PhpStorm's "Member has private visibility but can be accessed via '__get' magic method" which is thrown in child classes of Nette\Application\UI\Control even though it has the same `@property-read` tag. --- .../Admin/Presenters/HomepagePresenter.php | 41 +++++++++++-------- .../Admin/Presenters/InvoicesPresenter.php | 23 ++++++++--- .../Admin/Presenters/TrainingsPresenter.php | 37 +++++++++++------ .../templates/Homepage/default.latte | 2 +- .../templates/Invoices/unpaid.latte | 2 +- .../templates/Trainings/default.latte | 2 +- .../Trainings/pastWithPersonalData.latte | 2 +- site/app/Application/UiControl.php | 14 +++++++ site/app/Training/DateList/DateListOrder.php | 12 ++++++ .../DateList/TrainingApplicationsList.php | 35 ++++++++++++++++ .../TrainingApplicationsListFactory.php | 16 ++++++++ .../DateList/trainingApplicationsList.latte} | 10 ++--- site/config/services.neon | 1 + 13 files changed, 152 insertions(+), 45 deletions(-) create mode 100644 site/app/Application/UiControl.php create mode 100644 site/app/Training/DateList/DateListOrder.php create mode 100644 site/app/Training/DateList/TrainingApplicationsList.php create mode 100644 site/app/Training/DateList/TrainingApplicationsListFactory.php rename site/app/{Admin/Presenters/templates/Trainings/common/dateList.latte => Training/DateList/trainingApplicationsList.latte} (87%) diff --git a/site/app/Admin/Presenters/HomepagePresenter.php b/site/app/Admin/Presenters/HomepagePresenter.php index 733a1da2e..59b437756 100644 --- a/site/app/Admin/Presenters/HomepagePresenter.php +++ b/site/app/Admin/Presenters/HomepagePresenter.php @@ -3,10 +3,12 @@ namespace MichalSpacekCz\Admin\Presenters; -use DateTime; use MichalSpacekCz\Tls\Certificate; use MichalSpacekCz\Tls\Certificates; use MichalSpacekCz\Training\Applications; +use MichalSpacekCz\Training\DateList\DateListOrder; +use MichalSpacekCz\Training\DateList\TrainingApplicationsList; +use MichalSpacekCz\Training\DateList\TrainingApplicationsListFactory; use MichalSpacekCz\Training\Dates\TrainingDates; use MichalSpacekCz\Training\Dates\UpcomingTrainingDates; use MichalSpacekCz\Training\Mails; @@ -23,6 +25,7 @@ public function __construct( private readonly TrainingDates $trainingDates, private readonly UpcomingTrainingDates $upcomingTrainingDates, private readonly Certificates $certificates, + private readonly TrainingApplicationsListFactory $trainingApplicationsListFactory, ) { parent::__construct(); } @@ -30,23 +33,6 @@ public function __construct( public function actionDefault(): void { - $trainings = $this->trainingDates->getAllTrainingsInterval('-1 week'); - foreach ($this->upcomingTrainingDates->getAllUpcoming() as $training) { - foreach ($training->getDates() as $date) { - $trainings[] = $date; - } - } - $dates = []; - foreach ($trainings as $date) { - $date->setApplications($this->trainingApplications->getValidByDate($date->getId())); - $date->setCanceledApplications($this->trainingApplications->getCanceledPaidByDate($date->getId())); - $dates[$date->getStart()->getTimestamp()] = $date; - } - ksort($dates); - $this->template->upcomingApplications = $dates; - $this->template->now = new DateTime(); - $this->template->upcomingIds = $this->upcomingTrainingDates->getPublicUpcomingIds(); - $this->template->pageTitle = 'Administrace'; $this->template->emailsToSend = count($this->trainingMails->getApplications()); $this->template->unpaidInvoices = $this->trainingApplications->getValidUnpaidCount(); @@ -73,4 +59,23 @@ private function certsNeedAttention(array $certificates): bool return false; } + + protected function createComponentTrainingApplicationsList(): TrainingApplicationsList + { + $trainings = $this->trainingDates->getAllTrainingsInterval('-1 week'); + foreach ($this->upcomingTrainingDates->getAllUpcoming() as $training) { + foreach ($training->getDates() as $date) { + $trainings[] = $date; + } + } + $dates = []; + foreach ($trainings as $date) { + $date->setApplications($this->trainingApplications->getValidByDate($date->getId())); + $date->setCanceledApplications($this->trainingApplications->getCanceledPaidByDate($date->getId())); + $dates[$date->getStart()->getTimestamp()] = $date; + } + ksort($dates); + return $this->trainingApplicationsListFactory->create(array_values($dates), DateListOrder::Asc); + } + } diff --git a/site/app/Admin/Presenters/InvoicesPresenter.php b/site/app/Admin/Presenters/InvoicesPresenter.php index 3c3a401b1..1f8dcb1e7 100644 --- a/site/app/Admin/Presenters/InvoicesPresenter.php +++ b/site/app/Admin/Presenters/InvoicesPresenter.php @@ -3,11 +3,13 @@ namespace MichalSpacekCz\Admin\Presenters; -use DateTime; use MichalSpacekCz\Form\TrainingInvoiceFormFactory; use MichalSpacekCz\Training\Applications; +use MichalSpacekCz\Training\DateList\DateListOrder; +use MichalSpacekCz\Training\DateList\TrainingApplicationsList; +use MichalSpacekCz\Training\DateList\TrainingApplicationsListFactory; +use MichalSpacekCz\Training\Dates\TrainingDate; use MichalSpacekCz\Training\Dates\TrainingDates; -use MichalSpacekCz\Training\Dates\UpcomingTrainingDates; use Nette\Forms\Form; class InvoicesPresenter extends BasePresenter @@ -16,12 +18,15 @@ class InvoicesPresenter extends BasePresenter /** @var array */ private array $allUnpaidInvoiceIds = []; + /** @var list */ + private array $datesWithUnpaid = []; + public function __construct( private readonly Applications $trainingApplications, private readonly TrainingDates $trainingDates, - private readonly UpcomingTrainingDates $upcomingTrainingDates, private readonly TrainingInvoiceFormFactory $trainingInvoiceFormFactory, + private readonly TrainingApplicationsListFactory $trainingApplicationsListFactory, ) { parent::__construct(); } @@ -39,9 +44,9 @@ public function actionUnpaid(): void $dates[$date->getStart()->getTimestamp()] = $date; } ksort($dates); - $this->template->unpaidApplications = $dates; - $this->template->now = new DateTime(); - $this->template->upcomingIds = $this->upcomingTrainingDates->getPublicUpcomingIds(); + $this->template->unpaidApplications = (bool)$dates; + $this->datesWithUnpaid = array_values($dates); + $this->template->pageTitle = 'Nezaplacené faktury'; } @@ -65,4 +70,10 @@ function (): never { ); } + + protected function createComponentTrainingApplicationsList(): TrainingApplicationsList + { + return $this->trainingApplicationsListFactory->create($this->datesWithUnpaid, DateListOrder::Asc); + } + } diff --git a/site/app/Admin/Presenters/TrainingsPresenter.php b/site/app/Admin/Presenters/TrainingsPresenter.php index d07e2322a..4704d7987 100644 --- a/site/app/Admin/Presenters/TrainingsPresenter.php +++ b/site/app/Admin/Presenters/TrainingsPresenter.php @@ -3,7 +3,6 @@ namespace MichalSpacekCz\Admin\Presenters; -use DateTime; use MichalSpacekCz\DateTime\DateTimeFormatter; use MichalSpacekCz\Form\DeletePersonalDataFormFactory; use MichalSpacekCz\Form\TrainingApplicationAdminFormFactory; @@ -13,6 +12,9 @@ use MichalSpacekCz\Form\TrainingReviewFormFactory; use MichalSpacekCz\Form\TrainingStatusesFormFactory; use MichalSpacekCz\Training\Applications; +use MichalSpacekCz\Training\DateList\DateListOrder; +use MichalSpacekCz\Training\DateList\TrainingApplicationsList; +use MichalSpacekCz\Training\DateList\TrainingApplicationsListFactory; use MichalSpacekCz\Training\Dates\TrainingDate; use MichalSpacekCz\Training\Dates\TrainingDates; use MichalSpacekCz\Training\Dates\UpcomingTrainingDates; @@ -50,6 +52,9 @@ class TrainingsPresenter extends BasePresenter private int $redirectParam; + /** @var list */ + private array $pastWithPersonalData = []; + public function __construct( private readonly Applications $trainingApplications, @@ -67,6 +72,7 @@ public function __construct( private readonly TrainingDateFormFactory $trainingDateFormFactory, private readonly TrainingReviewFormFactory $trainingReviewFormFactory, private readonly TrainingStatusesFormFactory $trainingStatusesFormFactory, + private readonly TrainingApplicationsListFactory $trainingApplicationsListFactory, ) { parent::__construct(); } @@ -205,23 +211,15 @@ public function actionPreliminary(): void public function renderDefault(): void { - $trainings = $this->trainingDates->getAllTrainings(); - $this->addApplications($trainings); - $this->template->pageTitle = 'Školení'; - $this->template->trainings = $trainings; - $this->template->now = new DateTime(); - $this->template->upcomingIds = $this->upcomingTrainingDates->getPublicUpcomingIds(); } - public function renderPastWithPersonalData(): void + public function actionPastWithPersonalData(): void { - $trainings = $this->trainingDates->getPastWithPersonalData(); - $this->addApplications($trainings); - + $this->pastWithPersonalData = $this->trainingDates->getPastWithPersonalData(); $this->template->pageTitle = 'Minulá školení s osobními daty starší než ' . $this->dateTimeFormatter->localeDay($this->trainingDates->getDataRetentionDate()); - $this->template->trainings = $trainings; + $this->template->trainings = (bool)$this->pastWithPersonalData; } @@ -349,4 +347,19 @@ protected function createComponentDeletePersonalDataForm(): Form }); } + + protected function createComponentTrainingApplicationsList(): TrainingApplicationsList + { + $dates = $this->trainingDates->getAllTrainings(); + $this->addApplications($dates); + return $this->trainingApplicationsListFactory->create($dates, DateListOrder::Desc); + } + + + protected function createComponentPastWithPersonalDataTrainingApplicationsList(): TrainingApplicationsList + { + $this->addApplications($this->pastWithPersonalData); + return $this->trainingApplicationsListFactory->create($this->pastWithPersonalData, DateListOrder::Desc, true); + } + } diff --git a/site/app/Admin/Presenters/templates/Homepage/default.latte b/site/app/Admin/Presenters/templates/Homepage/default.latte index b12cd8299..658aea433 100644 --- a/site/app/Admin/Presenters/templates/Homepage/default.latte +++ b/site/app/Admin/Presenters/templates/Homepage/default.latte @@ -2,7 +2,7 @@ {define #content}
{$flash->message}

Školení

-{include "../Trainings/common/dateList.latte", trainings: $upcomingApplications, upcomingIds: $upcomingIds, now: $now, order: 'asc'} +{control trainingApplicationsList}

Certifikáty

Zobrazit diff --git a/site/app/Admin/Presenters/templates/Invoices/unpaid.latte b/site/app/Admin/Presenters/templates/Invoices/unpaid.latte index 521aa8a00..d3db015f2 100644 --- a/site/app/Admin/Presenters/templates/Invoices/unpaid.latte +++ b/site/app/Admin/Presenters/templates/Invoices/unpaid.latte @@ -8,7 +8,7 @@ {if $unpaidApplications}

{$flash->message}
-{include "../Trainings/common/dateList.latte", trainings: $unpaidApplications, upcomingIds: $upcomingIds, now: $now, order: 'asc'} +{control trainingApplicationsList}


diff --git a/site/app/Admin/Presenters/templates/Trainings/default.latte b/site/app/Admin/Presenters/templates/Trainings/default.latte index b10a2537d..12ae6825b 100644 --- a/site/app/Admin/Presenters/templates/Trainings/default.latte +++ b/site/app/Admin/Presenters/templates/Trainings/default.latte @@ -6,5 +6,5 @@ {include "common/dateForm.latte", form: addDate, id: pridat-termin-container}

-{include "common/dateList.latte", order: 'desc', upcomingIds: $upcomingIds, now: $now} +{control trainingApplicationsList} {/define} diff --git a/site/app/Admin/Presenters/templates/Trainings/pastWithPersonalData.latte b/site/app/Admin/Presenters/templates/Trainings/pastWithPersonalData.latte index de3d81ac5..b1c834491 100644 --- a/site/app/Admin/Presenters/templates/Trainings/pastWithPersonalData.latte +++ b/site/app/Admin/Presenters/templates/Trainings/pastWithPersonalData.latte @@ -3,7 +3,7 @@ {if !$trainings}

Žádná minulá školení s osobními daty

{else} - {include "common/dateList.latte", order: 'desc', upcomingIds: [], now: null} + {control pastWithPersonalDataTrainingApplicationsList}

{input delete}

diff --git a/site/app/Application/UiControl.php b/site/app/Application/UiControl.php new file mode 100644 index 000000000..b9f9f26e5 --- /dev/null +++ b/site/app/Application/UiControl.php @@ -0,0 +1,14 @@ + $dates + */ + public function __construct( + private readonly UpcomingTrainingDates $upcomingTrainingDates, + private readonly array $dates, + private readonly DateListOrder $order, + private readonly bool $pastOnly, + ) { + } + + + public function render(): void + { + $this->template->trainings = $this->dates; + $this->template->now = $this->pastOnly ? null : new DateTimeImmutable(); + $this->template->upcomingIds = $this->pastOnly ? [] : $this->upcomingTrainingDates->getPublicUpcomingIds(); + $this->template->order = $this->order; + $this->template->render(__DIR__ . '/trainingApplicationsList.latte'); + } + +} diff --git a/site/app/Training/DateList/TrainingApplicationsListFactory.php b/site/app/Training/DateList/TrainingApplicationsListFactory.php new file mode 100644 index 000000000..500e41d34 --- /dev/null +++ b/site/app/Training/DateList/TrainingApplicationsListFactory.php @@ -0,0 +1,16 @@ + $dates + */ + public function create(array $dates, DateListOrder $order, bool $pastOnly = false): TrainingApplicationsList; + +} diff --git a/site/app/Admin/Presenters/templates/Trainings/common/dateList.latte b/site/app/Training/DateList/trainingApplicationsList.latte similarity index 87% rename from site/app/Admin/Presenters/templates/Trainings/common/dateList.latte rename to site/app/Training/DateList/trainingApplicationsList.latte index 89cfadcda..3a6082466 100644 --- a/site/app/Admin/Presenters/templates/Trainings/common/dateList.latte +++ b/site/app/Training/DateList/trainingApplicationsList.latte @@ -4,7 +4,7 @@ {define #listItems, Nette\Database\Row[] $applications} {$iterator->getCounter()}. - {$application->name ?? smazáno} + {$application->name ?? smazáno} {$application->email ?? smazáno} {$application->company|truncate:40} note && ($application->note|length) > 20} title="{$application->note}"{/if}>{$application->note|truncate:20} @@ -37,7 +37,7 @@ {var $dateLineDisplayed = false} {var $upcoming = in_array($training->getId(), $upcomingIds)} - {if $order == 'desc'} + {if $order === MichalSpacekCz\Training\DateList\DateListOrder::Desc} {var $dateLineCheck = $now && $training->getStart() < $now} {else} {var $dateLineCheck = $now && $training->getStart() > $now} @@ -47,12 +47,12 @@ {/if} {var $dateLineDisplayed = $dateLineCheck} - {$iterator->count() - $iterator->getCounter() + 1}. - {$iterator->getCounter()}. + {$iterator->count() - $iterator->getCounter() + 1}. + {$iterator->getCounter()}. - {$training->getStart()|localeIntervalDay:$training->getEnd()} + {$training->getStart()|localeIntervalDay:$training->getEnd()} {icon clipboard} diff --git a/site/config/services.neon b/site/config/services.neon index 04781e1d4..d13487078 100644 --- a/site/config/services.neon +++ b/site/config/services.neon @@ -90,6 +90,7 @@ services: - MichalSpacekCz\Tls\CertificatesApiClient - MichalSpacekCz\Training\Applications(emailEncryption: @emailEncryption) - MichalSpacekCz\Training\CompanyTrainings + - MichalSpacekCz\Training\DateList\TrainingApplicationsListFactory - MichalSpacekCz\Training\Dates\TrainingDateStatuses - MichalSpacekCz\Training\Dates\TrainingDateFactory(texyFormatter: @texyFormatterNoPlaceholders) - MichalSpacekCz\Training\Dates\TrainingDates