wip: pagination
This commit is contained in:
@@ -4,10 +4,9 @@ namespace App\Download\Framework\Repository;
|
|||||||
|
|
||||||
use App\Download\Framework\Entity\Download;
|
use App\Download\Framework\Entity\Download;
|
||||||
use App\User\Framework\Entity\User;
|
use App\User\Framework\Entity\User;
|
||||||
|
use App\Util\Paginator;
|
||||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||||
use Doctrine\Persistence\ManagerRegistry;
|
use Doctrine\Persistence\ManagerRegistry;
|
||||||
use Knp\Component\Pager\Paginator;
|
|
||||||
use Knp\Component\Pager\PaginatorInterface;
|
|
||||||
use Symfony\Component\Security\Core\User\UserInterface;
|
use Symfony\Component\Security\Core\User\UserInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -17,38 +16,35 @@ class DownloadRepository extends ServiceEntityRepository
|
|||||||
{
|
{
|
||||||
private ManagerRegistry $managerRegistry;
|
private ManagerRegistry $managerRegistry;
|
||||||
|
|
||||||
public function __construct(ManagerRegistry $registry, ManagerRegistry $managerRegistry)
|
private Paginator $paginator;
|
||||||
|
|
||||||
|
public function __construct(ManagerRegistry $registry, ManagerRegistry $managerRegistry, Paginator $paginator)
|
||||||
{
|
{
|
||||||
parent::__construct($registry, Download::class);
|
parent::__construct($registry, Download::class);
|
||||||
$this->managerRegistry = $managerRegistry;
|
$this->managerRegistry = $managerRegistry;
|
||||||
|
$this->paginator = $paginator;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getCompletePaginated(int $pageNumber = 1, int $perPage = 10)
|
public function getCompletePaginated(int $pageNumber = 1, int $perPage = 10)
|
||||||
{
|
{
|
||||||
$firstResult = ($pageNumber - 1) * $perPage;
|
|
||||||
$query = $this->createQueryBuilder('d')
|
$query = $this->createQueryBuilder('d')
|
||||||
->andWhere('d.status IN (:statuses)')
|
->andWhere('d.status IN (:statuses)')
|
||||||
->orderBy('d.id', 'DESC')
|
->orderBy('d.id', 'DESC')
|
||||||
->setParameter('statuses', ['Complete'])
|
->setParameter('statuses', ['Complete'])
|
||||||
->setFirstResult($firstResult)
|
|
||||||
->setMaxResults($perPage)
|
|
||||||
->getQuery();
|
->getQuery();
|
||||||
|
|
||||||
return new \Doctrine\ORM\Tools\Pagination\Paginator($query);
|
return $this->paginator->paginate($query, $pageNumber, $perPage);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getActivePaginated(int $pageNumber = 1, int $perPage = 5)
|
public function getActivePaginated(int $pageNumber = 1, int $perPage = 5)
|
||||||
{
|
{
|
||||||
$firstResult = ($pageNumber - 1) * $perPage;
|
|
||||||
$query = $this->createQueryBuilder('d')
|
$query = $this->createQueryBuilder('d')
|
||||||
->andWhere('d.status IN (:statuses)')
|
->andWhere('d.status IN (:statuses)')
|
||||||
->orderBy('d.id', 'ASC')
|
->orderBy('d.id', 'ASC')
|
||||||
->setParameter('statuses', ['New', 'In Progress'])
|
->setParameter('statuses', ['New', 'In Progress'])
|
||||||
->setFirstResult($firstResult)
|
|
||||||
->setMaxResults($perPage)
|
|
||||||
->getQuery();
|
->getQuery();
|
||||||
|
|
||||||
return new \Doctrine\ORM\Tools\Pagination\Paginator($query);
|
return $this->paginator->paginate($query, $pageNumber, $perPage);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function insert(
|
public function insert(
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
namespace App\Twig\Components;
|
namespace App\Twig\Components;
|
||||||
|
|
||||||
|
use App\Download\Framework\Repository\DownloadRepository;
|
||||||
|
use App\Util\Paginator;
|
||||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||||
use Symfony\UX\LiveComponent\Attribute\AsLiveComponent;
|
use Symfony\UX\LiveComponent\Attribute\AsLiveComponent;
|
||||||
use Symfony\UX\LiveComponent\DefaultActionTrait;
|
use Symfony\UX\LiveComponent\DefaultActionTrait;
|
||||||
@@ -13,12 +15,16 @@ final class DownloadList extends AbstractController
|
|||||||
|
|
||||||
public string $type;
|
public string $type;
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
private readonly DownloadRepository $downloadRepository,
|
||||||
|
) {}
|
||||||
|
|
||||||
public function getDownloads()
|
public function getDownloads()
|
||||||
{
|
{
|
||||||
if ($this->type === "active") {
|
if ($this->type === "active") {
|
||||||
return $this->getUser()->queryDownloads('in-progress', 5);
|
return $this->downloadRepository->getActivePaginated();
|
||||||
} elseif ($this->type === "complete") {
|
} elseif ($this->type === "complete") {
|
||||||
return $this->getUser()->queryDownloads('complete', 5);
|
return $this->downloadRepository->getCompletePaginated();
|
||||||
}
|
}
|
||||||
|
|
||||||
return [];
|
return [];
|
||||||
|
|||||||
59
src/Util/Paginator.php
Normal file
59
src/Util/Paginator.php
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Util;
|
||||||
|
|
||||||
|
use Doctrine\ORM\Query;
|
||||||
|
use Doctrine\ORM\QueryBuilder;
|
||||||
|
use Doctrine\ORM\Tools\Pagination\Paginator as OrmPaginator;
|
||||||
|
|
||||||
|
class Paginator
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var integer
|
||||||
|
*/
|
||||||
|
private $total;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var integer
|
||||||
|
*/
|
||||||
|
private $lastPage;
|
||||||
|
|
||||||
|
private $items;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param QueryBuilder|Query $query
|
||||||
|
* @param int $page
|
||||||
|
* @param int $limit
|
||||||
|
* @return Paginator
|
||||||
|
*/
|
||||||
|
public function paginate($query, int $page = 1, int $limit = 10): Paginator
|
||||||
|
{
|
||||||
|
$paginator = new OrmPaginator($query);
|
||||||
|
|
||||||
|
$paginator
|
||||||
|
->getQuery()
|
||||||
|
->setFirstResult($limit * ($page - 1))
|
||||||
|
->setMaxResults($limit);
|
||||||
|
|
||||||
|
$this->total = $paginator->count();
|
||||||
|
$this->lastPage = (int) ceil($paginator->count() / $paginator->getQuery()->getMaxResults());
|
||||||
|
$this->items = $paginator;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getTotal(): int
|
||||||
|
{
|
||||||
|
return $this->total;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getLastPage(): int
|
||||||
|
{
|
||||||
|
return $this->lastPage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getItems()
|
||||||
|
{
|
||||||
|
return $this->items;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
</thead>
|
</thead>
|
||||||
<tbody id="{{ table_body_id }}" class="divide-y divide-gray-200 dark:divide-gray-50">
|
<tbody id="{{ table_body_id }}" class="divide-y divide-gray-200 dark:divide-gray-50">
|
||||||
{% if this.downloads|length > 0 %}
|
{% if this.downloads|length > 0 %}
|
||||||
{% for download in this.downloads %}
|
{% for download in this.downloads.items %}
|
||||||
<tr id="ad_download_{{ download.id }}">
|
<tr id="ad_download_{{ download.id }}">
|
||||||
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-800 dark:text-stone-800 min-w-[45ch] max-w-[45ch] truncate">
|
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-800 dark:text-stone-800 min-w-[45ch] max-w-[45ch] truncate">
|
||||||
{{ download.title }}
|
{{ download.title }}
|
||||||
@@ -40,5 +40,10 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
{% if this.downloads.items|length > 0 %}
|
||||||
|
{% set paginator = this.downloads %}
|
||||||
|
{% include 'partial/paginator.html.twig' %}
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -25,11 +25,11 @@
|
|||||||
</th>
|
</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody class="divide-y divide-gray-200 dark:divide-gray-50">
|
<tbody class="divide-y divide-gray-50">
|
||||||
{% if this.userMonitors()|length > 0 %}
|
{% if this.userMonitors()|length > 0 %}
|
||||||
{% for monitor in this.userMonitors() %}
|
{% for monitor in this.userMonitors() %}
|
||||||
<tr id="monitor_{{ monitor.id }}">
|
<tr id="monitor_{{ monitor.id }}">
|
||||||
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-800 dark:text-stone-800 min-w-[45ch] max-w-[45ch] truncate">
|
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-stone-800 min-w-[50ch] max-w-[50ch] truncate">
|
||||||
{{ monitor.title }}
|
{{ monitor.title }}
|
||||||
</td>
|
</td>
|
||||||
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-800">
|
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-800">
|
||||||
@@ -54,7 +54,7 @@
|
|||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% else %}
|
{% else %}
|
||||||
<tr>
|
<tr>
|
||||||
<td class="px-6 py-4 whitespace-nowrap text-xs uppercase text-center col-span-2 font-medium text-gray-800 dark:text-stone-800" colspan="2">
|
<td class="px-6 py-4 whitespace-nowrap text-xs uppercase text-center col-span-2 font-medium text-stone-800" colspan="2">
|
||||||
No monitors
|
No monitors
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
<span {{ attributes }} class="py-[3px] px-[7px] bg-{{ color|default('green') }}-600 rounded-lg inline-block text-center text-xs text-gray-50">
|
<span {{ attributes }} class="py-[3px] px-[7px] bg-{{ color|default('green') }}-600 rounded-lg inline-block text-center text-xs text-white">
|
||||||
{{ status }}
|
{{ status }}
|
||||||
</span>
|
</span>
|
||||||
48
templates/partial/paginator.html.twig
Normal file
48
templates/partial/paginator.html.twig
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
{% set _currentPage = app.request.query.get('page') ?: 1 %}
|
||||||
|
{% set _currentRoute = app.request.attributes.get('_route') %}
|
||||||
|
{% set _lastPage = paginator.lastPage %}
|
||||||
|
{% set _currentParams = app.request.query.all|merge(app.request.attributes.get('_route_params')) %}
|
||||||
|
|
||||||
|
{% if paginator.lastPage > 1 %}
|
||||||
|
<nav>
|
||||||
|
<ul class="pagination justify-content-center">
|
||||||
|
<li class="page-item{{ _currentPage <= 1 ? ' disabled' : '' }}">
|
||||||
|
<a class="page-link" href="{{ path(_currentRoute, _currentParams|merge({page: _currentPage - 1})) }}" aria-label="Previous">
|
||||||
|
« {{ "Previous"|trans }}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
{% set startPage = max(1, _currentPage - 2) %}
|
||||||
|
{% set endPage = min(_lastPage, startPage + 4) %}
|
||||||
|
{% if startPage > 1 %}
|
||||||
|
<li class="page-item">
|
||||||
|
<a class="page-link" href="{{ path(_currentRoute, _currentParams|merge({page: 1})) }}">1</a>
|
||||||
|
</li>
|
||||||
|
{% if startPage > 2 %}
|
||||||
|
<li class="page-item disabled">
|
||||||
|
<span class="page-link">...</span>
|
||||||
|
</li>
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
{% for i in startPage..endPage %}
|
||||||
|
<li class="page-item {% if i == _currentPage %}active{% endif %}">
|
||||||
|
<a class="page-link" href="{{ path(_currentRoute, _currentParams|merge({page: i})) }}">{{ i }}</a>
|
||||||
|
</li>
|
||||||
|
{% endfor %}
|
||||||
|
{% if endPage < _lastPage %}
|
||||||
|
{% if endPage < _lastPage - 1 %}
|
||||||
|
<li class="page-item disabled">
|
||||||
|
<span class="page-link">...</span>
|
||||||
|
</li>
|
||||||
|
{% endif %}
|
||||||
|
<li class="page-item">
|
||||||
|
<a class="page-link" href="{{ path(_currentRoute, _currentParams|merge({page: _lastPage})) }}">{{ _lastPage }}</a>
|
||||||
|
</li>
|
||||||
|
{% endif %}
|
||||||
|
<li class="page-item {{ _currentPage >= paginator.lastPage ? ' disabled' : '' }}">
|
||||||
|
<a class="page-link" href="{{ path(_currentRoute, _currentParams|merge({page: _currentPage + 1})) }}" aria-label="Next">
|
||||||
|
{{ "Next"|trans }} »
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
{% endif %}
|
||||||
Reference in New Issue
Block a user