Skip to content

Commit

Permalink
Replace the admin shared training date list with a custom control/com…
Browse files Browse the repository at this point in the history
…ponent

From 94 level 4 errors to 66 with just this change.

This is probably how efabrica-team/phpstan-latte#391 should be solved, components suggested in #143 (comment)

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.
  • Loading branch information
spaze committed Jul 10, 2023
1 parent a6e43f9 commit 393c894
Show file tree
Hide file tree
Showing 13 changed files with 152 additions and 45 deletions.
41 changes: 23 additions & 18 deletions site/app/Admin/Presenters/HomepagePresenter.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -23,30 +25,14 @@ public function __construct(
private readonly TrainingDates $trainingDates,
private readonly UpcomingTrainingDates $upcomingTrainingDates,
private readonly Certificates $certificates,
private readonly TrainingApplicationsListFactory $trainingApplicationsListFactory,
) {
parent::__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();
Expand All @@ -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);
}

}
23 changes: 17 additions & 6 deletions site/app/Admin/Presenters/InvoicesPresenter.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -16,12 +18,15 @@ class InvoicesPresenter extends BasePresenter
/** @var array<int, string> */
private array $allUnpaidInvoiceIds = [];

/** @var list<TrainingDate> */
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();
}
Expand All @@ -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';
}

Expand All @@ -65,4 +70,10 @@ function (): never {
);
}


protected function createComponentTrainingApplicationsList(): TrainingApplicationsList
{
return $this->trainingApplicationsListFactory->create($this->datesWithUnpaid, DateListOrder::Asc);
}

}
37 changes: 25 additions & 12 deletions site/app/Admin/Presenters/TrainingsPresenter.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

namespace MichalSpacekCz\Admin\Presenters;

use DateTime;
use MichalSpacekCz\DateTime\DateTimeFormatter;
use MichalSpacekCz\Form\DeletePersonalDataFormFactory;
use MichalSpacekCz\Form\TrainingApplicationAdminFormFactory;
Expand All @@ -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;
Expand Down Expand Up @@ -50,6 +52,9 @@ class TrainingsPresenter extends BasePresenter

private int $redirectParam;

/** @var list<TrainingDate> */
private array $pastWithPersonalData = [];


public function __construct(
private readonly Applications $trainingApplications,
Expand All @@ -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();
}
Expand Down Expand Up @@ -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;
}


Expand Down Expand Up @@ -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);
}

}
2 changes: 1 addition & 1 deletion site/app/Admin/Presenters/templates/Homepage/default.latte
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
{define #content}
<div n:foreach="$flashes as $flash" class="flash {$flash->type}"><strong>{$flash->message}</strong></div>
<h2>Školení</h2>
{include "../Trainings/common/dateList.latte", trainings: $upcomingApplications, upcomingIds: $upcomingIds, now: $now, order: 'asc'}
{control trainingApplicationsList}
<h2>Certifikáty</h2>
<p id="certificates-toggle" class="small">
<span id="certificatesShow" n:class="$certificatesNeedAttention ? hidden">Zobrazit</span>
Expand Down
2 changes: 1 addition & 1 deletion site/app/Admin/Presenters/templates/Invoices/unpaid.latte
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
{if $unpaidApplications}
<p></p>
<div n:foreach="$flashes as $flash" class="flash {$flash->type}"><strong>{$flash->message}</strong></div>
{include "../Trainings/common/dateList.latte", trainings: $unpaidApplications, upcomingIds: $upcomingIds, now: $now, order: 'asc'}
{control trainingApplicationsList}
<p></p>
<hr>
<div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@
{include "common/dateForm.latte", form: addDate, id: pridat-termin-container}
</div>
<hr>
{include "common/dateList.latte", order: 'desc', upcomingIds: $upcomingIds, now: $now}
{control trainingApplicationsList}
{/define}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
{if !$trainings}
<p>Žádná minulá školení s osobními daty</p>
{else}
{include "common/dateList.latte", order: 'desc', upcomingIds: [], now: null}
{control pastWithPersonalDataTrainingApplicationsList}
<form n:name="deletePersonalDataForm">
<p>{input delete}</p>
</form>
Expand Down
14 changes: 14 additions & 0 deletions site/app/Application/UiControl.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php
declare(strict_types = 1);

namespace MichalSpacekCz\Application;

use Nette\Application\UI\Control;
use Nette\Bridges\ApplicationLatte\DefaultTemplate;

/**
* @property-read DefaultTemplate $template To suppress PhpStorm's "Member has private visibility but can be accessed via '__get' magic method" in child classes
*/
abstract class UiControl extends Control
{
}
12 changes: 12 additions & 0 deletions site/app/Training/DateList/DateListOrder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php
declare(strict_types = 1);

namespace MichalSpacekCz\Training\DateList;

enum DateListOrder
{

case Asc;
case Desc;

}
35 changes: 35 additions & 0 deletions site/app/Training/DateList/TrainingApplicationsList.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php
declare(strict_types = 1);

namespace MichalSpacekCz\Training\DateList;

use DateTimeImmutable;
use MichalSpacekCz\Application\UiControl;
use MichalSpacekCz\Training\Dates\TrainingDate;
use MichalSpacekCz\Training\Dates\UpcomingTrainingDates;

class TrainingApplicationsList extends UiControl
{

/**
* @param list<TrainingDate> $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');
}

}
16 changes: 16 additions & 0 deletions site/app/Training/DateList/TrainingApplicationsListFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php
declare(strict_types = 1);

namespace MichalSpacekCz\Training\DateList;

use MichalSpacekCz\Training\Dates\TrainingDate;

interface TrainingApplicationsListFactory
{

/**
* @param list<TrainingDate> $dates
*/
public function create(array $dates, DateListOrder $order, bool $pastOnly = false): TrainingApplicationsList;

}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
{define #listItems, Nette\Database\Row[] $applications}
<tr class="summary" n:foreach="$applications as $application">
<td><small>{$iterator->getCounter()}.</small></td>
<td><small n:tag-if="$application->name === null"><a n:href="Trainings:application $application->id">{$application->name ?? smazáno}</a></small></td>
<td><small n:tag-if="$application->name === null"><a href="{plink Trainings:application $application->id}">{$application->name ?? smazáno}</a></small></td>
<td><small>{$application->email ?? smazáno}</small></td>
<td><span n:tag-if="$application->company && ($application->company|length) > 40" title="{$application->company}">{$application->company|truncate:40}</span></td>
<td><small{if $application->note && ($application->note|length) > 20} title="{$application->note}"{/if}>{$application->note|truncate:20}</small></td>
Expand Down Expand Up @@ -37,7 +37,7 @@
{var $dateLineDisplayed = false}
<tbody n:inner-foreach="$trainings as $training">
{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}
Expand All @@ -47,12 +47,12 @@
{/if}
<tr n:class="summary, $dateLineCheck && !$dateLineDisplayed ? dateLine, $training->getStatus() !== \MichalSpacekCz\Training\Dates\TrainingDateStatus::Confirmed ? lighter">
{var $dateLineDisplayed = $dateLineCheck}
<td n:if="$order == 'desc'" class="positionCell"><small>{$iterator->count() - $iterator->getCounter() + 1}.</small></td>
<td n:if="$order == 'asc'" class="positionCell"><small>{$iterator->getCounter()}.</small></td>
<td n:if="$order === MichalSpacekCz\Training\DateList\DateListOrder::Desc" class="positionCell"><small>{$iterator->count() - $iterator->getCounter() + 1}.</small></td>
<td n:if="$order === MichalSpacekCz\Training\DateList\DateListOrder::Asc" class="positionCell"><small>{$iterator->getCounter()}.</small></td>
<td class="dateCell">
<strong n:tag-if="$upcoming">
<small n:tag-if="!$upcoming && $now && $training->getStart() > $now">
<a n:href="Trainings:date $training->getId()">{$training->getStart()|localeIntervalDay:$training->getEnd()}</a>
<a href="{plink Trainings:date $training->getId()}">{$training->getStart()|localeIntervalDay:$training->getEnd()}</a>
</small>
</strong>
<span n:if="$training->getNote()" title="Poznámka: {$training->getNote()}">{icon clipboard}</span>
Expand Down
1 change: 1 addition & 0 deletions site/config/services.neon
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 393c894

Please sign in to comment.