Feature: [activity list] add pagination

This commit is contained in:
Julien Fastré 2023-06-23 12:44:54 +02:00
parent f7c11d3567
commit 0e5f1b4ab9
Signed by: julienfastre
GPG Key ID: BDE2190974723FCB
5 changed files with 74 additions and 8 deletions

View File

@ -0,0 +1,5 @@
kind: Feature
body: '[activity list] add pagination to the list of activities'
time: 2023-06-23T12:44:38.879098862+02:00
custom:
Issue: ""

View File

@ -22,6 +22,7 @@ use Chill\ActivityBundle\Repository\ActivityUserJobRepository;
use Chill\ActivityBundle\Security\Authorization\ActivityVoter; use Chill\ActivityBundle\Security\Authorization\ActivityVoter;
use Chill\MainBundle\Entity\Embeddable\CommentEmbeddable; use Chill\MainBundle\Entity\Embeddable\CommentEmbeddable;
use Chill\MainBundle\Entity\UserJob; use Chill\MainBundle\Entity\UserJob;
use Chill\MainBundle\Pagination\PaginatorFactory;
use Chill\MainBundle\Repository\LocationRepository; use Chill\MainBundle\Repository\LocationRepository;
use Chill\MainBundle\Repository\UserRepositoryInterface; use Chill\MainBundle\Repository\UserRepositoryInterface;
use Chill\MainBundle\Security\Resolver\CenterResolverManagerInterface; use Chill\MainBundle\Security\Resolver\CenterResolverManagerInterface;
@ -70,6 +71,7 @@ final class ActivityController extends AbstractController
private readonly TranslatorInterface $translator, private readonly TranslatorInterface $translator,
private readonly FilterOrderHelperFactoryInterface $filterOrderHelperFactory, private readonly FilterOrderHelperFactoryInterface $filterOrderHelperFactory,
private readonly TranslatableStringHelperInterface $translatableStringHelper, private readonly TranslatableStringHelperInterface $translatableStringHelper,
private readonly PaginatorFactory $paginatorFactory,
) { ) {
} }
@ -251,7 +253,6 @@ final class ActivityController extends AbstractController
{ {
$view = null; $view = null;
$activities = []; $activities = [];
// TODO: add pagination
[$person, $accompanyingPeriod] = $this->getEntity($request); [$person, $accompanyingPeriod] = $this->getEntity($request);
$filter = $this->buildFilterOrder($person ?? $accompanyingPeriod); $filter = $this->buildFilterOrder($person ?? $accompanyingPeriod);
@ -266,12 +267,14 @@ final class ActivityController extends AbstractController
if ($person instanceof Person) { if ($person instanceof Person) {
$this->denyAccessUnlessGranted(ActivityVoter::SEE, $person); $this->denyAccessUnlessGranted(ActivityVoter::SEE, $person);
$count = $this->activityACLAwareRepository->countByPerson($person, ActivityVoter::SEE, $filterArgs);
$paginator = $this->paginatorFactory->create($count);
$activities = $this->activityACLAwareRepository $activities = $this->activityACLAwareRepository
->findByPerson( ->findByPerson(
$person, $person,
ActivityVoter::SEE, ActivityVoter::SEE,
0, $paginator->getCurrentPageFirstItemNumber(),
null, $paginator->getItemsPerPage(),
['date' => 'DESC', 'id' => 'DESC'], ['date' => 'DESC', 'id' => 'DESC'],
$filterArgs $filterArgs
); );
@ -286,17 +289,21 @@ final class ActivityController extends AbstractController
} elseif ($accompanyingPeriod instanceof AccompanyingPeriod) { } elseif ($accompanyingPeriod instanceof AccompanyingPeriod) {
$this->denyAccessUnlessGranted(ActivityVoter::SEE, $accompanyingPeriod); $this->denyAccessUnlessGranted(ActivityVoter::SEE, $accompanyingPeriod);
$count = $this->activityACLAwareRepository->countByAccompanyingPeriod($accompanyingPeriod, ActivityVoter::SEE, $filterArgs);
$paginator = $this->paginatorFactory->create($count);
$activities = $this->activityACLAwareRepository $activities = $this->activityACLAwareRepository
->findByAccompanyingPeriod( ->findByAccompanyingPeriod(
$accompanyingPeriod, $accompanyingPeriod,
ActivityVoter::SEE, ActivityVoter::SEE,
0, $paginator->getCurrentPageFirstItemNumber(),
null, $paginator->getItemsPerPage(),
['date' => 'DESC', 'id' => 'DESC'], ['date' => 'DESC', 'id' => 'DESC'],
$filterArgs $filterArgs
); );
$view = 'ChillActivityBundle:Activity:listAccompanyingCourse.html.twig'; $view = 'ChillActivityBundle:Activity:listAccompanyingCourse.html.twig';
} else {
throw new \LogicException("Unsupported");
} }
return $this->render( return $this->render(
@ -306,6 +313,7 @@ final class ActivityController extends AbstractController
'person' => $person, 'person' => $person,
'accompanyingCourse' => $accompanyingPeriod, 'accompanyingCourse' => $accompanyingPeriod,
'filter' => $filter, 'filter' => $filter,
'paginator' => $paginator,
] ]
); );
} }

View File

@ -27,6 +27,8 @@ use Chill\PersonBundle\Entity\Person;
use Doctrine\DBAL\Types\Types; use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\AbstractQuery; use Doctrine\ORM\AbstractQuery;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\NonUniqueResultException;
use Doctrine\ORM\NoResultException;
use Doctrine\ORM\Query\Expr\Join; use Doctrine\ORM\Query\Expr\Join;
use Doctrine\ORM\Query\ResultSetMappingBuilder; use Doctrine\ORM\Query\ResultSetMappingBuilder;
use Doctrine\ORM\QueryBuilder; use Doctrine\ORM\QueryBuilder;
@ -48,6 +50,33 @@ final readonly class ActivityACLAwareRepository implements ActivityACLAwareRepos
) { ) {
} }
/**
* @throws NonUniqueResultException
* @throws NoResultException
*/
public function countByAccompanyingPeriod(AccompanyingPeriod $period, string $role, array $filters = []): int
{
$qb = $this->buildBaseQuery($filters);
$qb
->select('COUNT(a)')
->andWhere('a.accompanyingPeriod = :period')->setParameter('period', $period);
return $qb->getQuery()->getSingleScalarResult();
}
public function countByPerson(Person $person, string $role, array $filters = []): int
{
$qb = $this->buildBaseQuery($filters);
$qb = $this->filterBaseQueryByPerson($qb, $person, $role);
$qb->select('COUNT(a)');
return $qb->getQuery()->getSingleScalarResult();
}
public function findByAccompanyingPeriod(AccompanyingPeriod $period, string $role, ?int $start = 0, ?int $limit = 1000, array $orderBy = ['date' => 'DESC'], array $filters = []): array public function findByAccompanyingPeriod(AccompanyingPeriod $period, string $role, ?int $start = 0, ?int $limit = 1000, array $orderBy = ['date' => 'DESC'], array $filters = []): array
{ {
$qb = $this->buildBaseQuery($filters); $qb = $this->buildBaseQuery($filters);
@ -58,7 +87,12 @@ final readonly class ActivityACLAwareRepository implements ActivityACLAwareRepos
$qb->addOrderBy('a.' . $field, $order); $qb->addOrderBy('a.' . $field, $order);
} }
$qb->setFirstResult(0)->setMaxResults(1000); if (null !== $start) {
$qb->setFirstResult($start);
}
if (null !== $limit) {
$qb->setMaxResults($limit);
}
return $qb->getQuery()->getResult(); return $qb->getQuery()->getResult();
} }
@ -261,6 +295,13 @@ final readonly class ActivityACLAwareRepository implements ActivityACLAwareRepos
$qb->addOrderBy('a.' . $field, $direction); $qb->addOrderBy('a.' . $field, $direction);
} }
if (null !== $start) {
$qb->setFirstResult($start);
}
if (null !== $limit) {
$qb->setMaxResults($limit);
}
return $qb->getQuery()->getResult(); return $qb->getQuery()->getResult();
} }

View File

@ -28,6 +28,16 @@ interface ActivityACLAwareRepositoryInterface
*/ */
public function findByAccompanyingPeriod(AccompanyingPeriod $period, string $role, ?int $start = 0, ?int $limit = 1000, array $orderBy = ['date' => 'DESC'], array $filters = []): array; public function findByAccompanyingPeriod(AccompanyingPeriod $period, string $role, ?int $start = 0, ?int $limit = 1000, array $orderBy = ['date' => 'DESC'], array $filters = []): array;
/**
* @param array{my_activities?: bool, types?: array<ActivityType>, jobs?: array<UserJob>, after?: \DateTimeImmutable|null, before?: \DateTimeImmutable|null} $filters
*/
public function countByAccompanyingPeriod(AccompanyingPeriod $period, string $role, array $filters = []): int;
/**
* @param array{my_activities?: bool, types?: array<ActivityType>, jobs?: array<UserJob>, after?: \DateTimeImmutable|null, before?: \DateTimeImmutable|null} $filters
*/
public function countByPerson(Person $person, string $role, array $filters = []): int;
/** /**
* Return a list of activities, simplified as array (not object). * Return a list of activities, simplified as array (not object).
* *

View File

@ -80,6 +80,8 @@
<div class="context-{{ context }}"> <div class="context-{{ context }}">
{{ filter|chill_render_filter_order_helper }}
{% if activities|length == 0 %} {% if activities|length == 0 %}
<p class="chill-no-data-statement"> <p class="chill-no-data-statement">
{{ "There isn't any activities."|trans }} {{ "There isn't any activities."|trans }}
@ -87,8 +89,6 @@
{% else %} {% else %}
{{ filter|chill_render_filter_order_helper }}
<div class="flex-table activity-list"> <div class="flex-table activity-list">
{% for activity in activities %} {% for activity in activities %}
{% include 'ChillActivityBundle:Activity:_list_item.html.twig' with { {% include 'ChillActivityBundle:Activity:_list_item.html.twig' with {
@ -99,4 +99,6 @@
</div> </div>
{% endif %} {% endif %}
{{ chill_pagination(paginator) }}
</div> </div>