feat: admin list filtering and search
This commit is contained in:
1 parent
aa8fa5c1b2
commit
dd658bf9d6
41 files changed
+1977
-44
No files matched your search
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Controller\Admin\AccommodationBooking;
|
||||
|
||||
use App\Controller\Traits\ListFilterTrait;
|
||||
use App\Entity\User;
|
||||
use App\Form\Admin\Filter\AccommodationBookingFilterOptionsProvider;
|
||||
use App\Form\Admin\Filter\AccommodationBookingFilterType;
|
||||
use App\Form\Model\Filter\AccommodationBookingFilterDto;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
|
||||
/**
|
||||
* Renders the filter modal, pre-filled with whatever the list is currently showing.
|
||||
*
|
||||
* There is no submit action to go with it: the form is a GET form pointing at the list itself,
|
||||
* so applying a filter is a plain navigation.
|
||||
*/
|
||||
#[IsGranted('ROLE_GROUPS_MANAGER')]
|
||||
class FilterController extends AbstractController
|
||||
{
|
||||
use ListFilterTrait;
|
||||
|
||||
public function __construct(
|
||||
private readonly AccommodationBookingFilterOptionsProvider $filterOptions,
|
||||
) {
|
||||
}
|
||||
|
||||
#[Route('/admin/accommodation-booking/filter', name: 'app_admin_accommodationbooking_filter', methods: ['GET'])]
|
||||
public function filter(Request $request): Response
|
||||
{
|
||||
// ROLE_ADMIN inherits ROLE_GROUPS_ADMIN, so this single check covers both.
|
||||
$seesAllBookings = $this->isGranted('ROLE_GROUPS_ADMIN');
|
||||
$user = $this->getUser();
|
||||
|
||||
$filterView = $this->createListFilterView(
|
||||
$request,
|
||||
AccommodationBookingFilterType::class,
|
||||
AccommodationBookingFilterDto::defaults($seesAllBookings, $user instanceof User ? $user : null),
|
||||
'app_admin_accommodationbooking',
|
||||
$this->filterOptions->formOptions($seesAllBookings),
|
||||
);
|
||||
|
||||
return $this->render('admin/accommodation_booking/modal_filter.html.twig', [
|
||||
'form' => $filterView,
|
||||
'route' => 'app_admin_accommodationbooking',
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,11 @@ declare(strict_types=1);
|
||||
|
||||
namespace App\Controller\Admin\AccommodationBooking;
|
||||
|
||||
use App\Controller\Traits\ListFilterTrait;
|
||||
use App\Entity\User;
|
||||
use App\Form\Admin\Filter\AccommodationBookingFilterOptionsProvider;
|
||||
use App\Form\Admin\Filter\AccommodationBookingFilterType;
|
||||
use App\Form\Model\Filter\AccommodationBookingFilterDto;
|
||||
use App\Repository\Groups\AccommodationBookingRepository;
|
||||
use Knp\Component\Pager\PaginatorInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
@@ -15,8 +20,11 @@ use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
#[IsGranted('ROLE_GROUPS_MANAGER')]
|
||||
class IndexController extends AbstractController
|
||||
{
|
||||
use ListFilterTrait;
|
||||
|
||||
public function __construct(
|
||||
private readonly AccommodationBookingRepository $bookingRepository,
|
||||
private readonly AccommodationBookingFilterOptionsProvider $filterOptions,
|
||||
private readonly PaginatorInterface $paginator,
|
||||
) {
|
||||
}
|
||||
@@ -24,21 +32,33 @@ class IndexController extends AbstractController
|
||||
#[Route('/admin/accommodation-booking', name: 'app_admin_accommodationbooking')]
|
||||
public function index(Request $request): Response
|
||||
{
|
||||
$today = new \DateTimeImmutable('today');
|
||||
// ROLE_ADMIN inherits ROLE_GROUPS_ADMIN, so this single check covers both.
|
||||
$seesAllBookings = $this->isGranted('ROLE_GROUPS_ADMIN');
|
||||
$user = $this->getUser();
|
||||
$user = $user instanceof User ? $user : null;
|
||||
|
||||
$qb = $this
|
||||
->bookingRepository
|
||||
->createQueryBuilder('booking')
|
||||
->select('booking', 'managed_by')
|
||||
->leftJoin('booking.accommodation', 'accommodation')
|
||||
->leftJoin('booking.managedBy', 'managed_by')
|
||||
->addSelect('accommodation')
|
||||
->where('booking.dateTo >= :today')
|
||||
->setParameter('today', $today)
|
||||
;
|
||||
// The form writes into $filter, so after this call it holds either the defaults or
|
||||
// whatever the query string asked for.
|
||||
$filter = AccommodationBookingFilterDto::defaults($seesAllBookings, $user);
|
||||
|
||||
$filterView = $this->createListFilterView(
|
||||
$request,
|
||||
AccommodationBookingFilterType::class,
|
||||
$filter,
|
||||
'app_admin_accommodationbooking',
|
||||
$this->filterOptions->formOptions($seesAllBookings),
|
||||
);
|
||||
|
||||
// The manager fields are not part of the form for this role, but the scope is pinned
|
||||
// here as well so that a hand-written query parameter cannot widen it either.
|
||||
if (!$seesAllBookings) {
|
||||
$filter->managedBy = $user;
|
||||
$filter->unassigned = false;
|
||||
$filter->managedByLocked = true;
|
||||
}
|
||||
|
||||
$pagination = $this->paginator->paginate(
|
||||
$qb,
|
||||
$this->bookingRepository->createFilteredQueryBuilder($filter),
|
||||
$request->query->getInt('page', 1),
|
||||
$request->query->getInt('limit', 20),
|
||||
[
|
||||
@@ -49,6 +69,8 @@ class IndexController extends AbstractController
|
||||
|
||||
return $this->render('admin/accommodation_booking/index.html.twig', [
|
||||
'pagination' => $pagination,
|
||||
'filter' => $filter,
|
||||
'filter_form' => $filterView,
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Controller\Admin\BookingEditDraft;
|
||||
|
||||
use App\Controller\Traits\ListFilterTrait;
|
||||
use App\Form\Admin\Filter\BookingEditDraftFilterType;
|
||||
use App\Form\Model\Filter\BookingEditDraftFilterDto;
|
||||
use App\Repository\BookingEditDraftRepository;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
|
||||
#[IsGranted('ROLE_GROUPS_ADMIN')]
|
||||
class FilterController extends AbstractController
|
||||
{
|
||||
use ListFilterTrait;
|
||||
|
||||
public function __construct(
|
||||
private readonly BookingEditDraftRepository $bookingEditDraftRepository,
|
||||
) {
|
||||
}
|
||||
|
||||
#[Route('/admin/booking-edit-draft/filter', name: 'app_admin_bookingeditdraft_filter', methods: ['GET'])]
|
||||
public function filter(Request $request): Response
|
||||
{
|
||||
$filterView = $this->createListFilterView(
|
||||
$request,
|
||||
BookingEditDraftFilterType::class,
|
||||
new BookingEditDraftFilterDto(),
|
||||
'app_admin_bookingeditdraft',
|
||||
['users' => $this->bookingEditDraftRepository->findDraftOwners()],
|
||||
);
|
||||
|
||||
return $this->render('admin/_modal_filter.html.twig', [
|
||||
'form' => $filterView,
|
||||
'route' => 'app_admin_bookingeditdraft',
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,10 @@ declare(strict_types=1);
|
||||
|
||||
namespace App\Controller\Admin\BookingEditDraft;
|
||||
|
||||
use App\Controller\Traits\ListFilterTrait;
|
||||
use App\Controller\Traits\ReturnUrlTrait;
|
||||
use App\Form\Admin\Filter\BookingEditDraftFilterType;
|
||||
use App\Form\Model\Filter\BookingEditDraftFilterDto;
|
||||
use App\Repository\BookingEditDraftRepository;
|
||||
use Knp\Component\Pager\PaginatorInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
@@ -16,6 +19,7 @@ use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
#[IsGranted('ROLE_GROUPS_ADMIN')]
|
||||
class IndexController extends AbstractController
|
||||
{
|
||||
use ListFilterTrait;
|
||||
use ReturnUrlTrait;
|
||||
|
||||
public function __construct(
|
||||
@@ -27,14 +31,18 @@ class IndexController extends AbstractController
|
||||
#[Route('/admin/booking-edit-draft', name: 'app_admin_bookingeditdraft')]
|
||||
public function index(Request $request): Response
|
||||
{
|
||||
$qb = $this
|
||||
->bookingEditDraftRepository
|
||||
->createQueryBuilder('booking_edit_draft')
|
||||
->leftJoin('booking_edit_draft.user', 'user')
|
||||
;
|
||||
$filter = new BookingEditDraftFilterDto();
|
||||
|
||||
$filterView = $this->createListFilterView(
|
||||
$request,
|
||||
BookingEditDraftFilterType::class,
|
||||
$filter,
|
||||
'app_admin_bookingeditdraft',
|
||||
['users' => $this->bookingEditDraftRepository->findDraftOwners()],
|
||||
);
|
||||
|
||||
$pagination = $this->paginator->paginate(
|
||||
$qb,
|
||||
$this->bookingEditDraftRepository->createFilteredQueryBuilder($filter),
|
||||
$request->query->getInt('page', 1),
|
||||
$request->query->getInt('limit', 20),
|
||||
[
|
||||
@@ -45,6 +53,8 @@ class IndexController extends AbstractController
|
||||
|
||||
return $this->render('admin/booking_edit_draft/index.html.twig', [
|
||||
'pagination' => $pagination,
|
||||
'filter' => $filter,
|
||||
'filter_form' => $filterView,
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Controller\Admin\Log;
|
||||
|
||||
use App\Controller\Traits\ListFilterTrait;
|
||||
use App\Form\Admin\Filter\LogEntryFilterType;
|
||||
use App\Form\Model\Filter\LogEntryFilterDto;
|
||||
use App\Repository\LogEntryRepository;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
|
||||
#[IsGranted('ROLE_ADMIN')]
|
||||
class FilterController extends AbstractController
|
||||
{
|
||||
use ListFilterTrait;
|
||||
|
||||
public function __construct(
|
||||
private readonly LogEntryRepository $logEntryRepository,
|
||||
) {
|
||||
}
|
||||
|
||||
#[Route('/admin/log/filter', name: 'app_admin_log_filter', methods: ['GET'])]
|
||||
public function filter(Request $request): Response
|
||||
{
|
||||
$filterView = $this->createListFilterView(
|
||||
$request,
|
||||
LogEntryFilterType::class,
|
||||
new LogEntryFilterDto(),
|
||||
'app_admin_log',
|
||||
['channels' => $this->logEntryRepository->findChannels()],
|
||||
);
|
||||
|
||||
return $this->render('admin/_modal_filter.html.twig', [
|
||||
'form' => $filterView,
|
||||
'route' => 'app_admin_log',
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,9 @@ declare(strict_types=1);
|
||||
|
||||
namespace App\Controller\Admin\Log;
|
||||
|
||||
use App\Controller\Traits\ListFilterTrait;
|
||||
use App\Form\Admin\Filter\LogEntryFilterType;
|
||||
use App\Form\Model\Filter\LogEntryFilterDto;
|
||||
use App\Repository\LogEntryRepository;
|
||||
use Knp\Component\Pager\PaginatorInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
@@ -15,6 +18,8 @@ use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
#[IsGranted('ROLE_ADMIN')]
|
||||
class IndexController extends AbstractController
|
||||
{
|
||||
use ListFilterTrait;
|
||||
|
||||
public function __construct(
|
||||
private readonly LogEntryRepository $logEntryRepository,
|
||||
private readonly PaginatorInterface $paginator,
|
||||
@@ -24,13 +29,18 @@ class IndexController extends AbstractController
|
||||
#[Route('/admin/log', name: 'app_admin_log')]
|
||||
public function index(Request $request): Response
|
||||
{
|
||||
$qb = $this
|
||||
->logEntryRepository
|
||||
->createQueryBuilder('log_entry')
|
||||
;
|
||||
$filter = new LogEntryFilterDto();
|
||||
|
||||
$filterView = $this->createListFilterView(
|
||||
$request,
|
||||
LogEntryFilterType::class,
|
||||
$filter,
|
||||
'app_admin_log',
|
||||
['channels' => $this->logEntryRepository->findChannels()],
|
||||
);
|
||||
|
||||
$pagination = $this->paginator->paginate(
|
||||
$qb,
|
||||
$this->logEntryRepository->createFilteredQueryBuilder($filter),
|
||||
$request->query->getInt('page', 1),
|
||||
$request->query->getInt('limit', 50),
|
||||
[
|
||||
@@ -41,6 +51,8 @@ class IndexController extends AbstractController
|
||||
|
||||
return $this->render('admin/log/index.html.twig', [
|
||||
'pagination' => $pagination,
|
||||
'filter' => $filter,
|
||||
'filter_form' => $filterView,
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Controller\Admin\User;
|
||||
|
||||
use App\Controller\Traits\ListFilterTrait;
|
||||
use App\Form\Admin\Filter\UserFilterType;
|
||||
use App\Form\Model\Filter\UserFilterDto;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
|
||||
#[IsGranted('ROLE_ADMIN')]
|
||||
class FilterController extends AbstractController
|
||||
{
|
||||
use ListFilterTrait;
|
||||
|
||||
#[Route('/admin/user/filter', name: 'app_admin_user_filter', methods: ['GET'])]
|
||||
public function filter(Request $request): Response
|
||||
{
|
||||
$filterView = $this->createListFilterView(
|
||||
$request,
|
||||
UserFilterType::class,
|
||||
new UserFilterDto(),
|
||||
'app_admin_user',
|
||||
['roles' => UserFilterType::ROLES],
|
||||
);
|
||||
|
||||
return $this->render('admin/_modal_filter.html.twig', [
|
||||
'form' => $filterView,
|
||||
'route' => 'app_admin_user',
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,9 @@ declare(strict_types=1);
|
||||
|
||||
namespace App\Controller\Admin\User;
|
||||
|
||||
use App\Controller\Traits\ListFilterTrait;
|
||||
use App\Form\Admin\Filter\UserFilterType;
|
||||
use App\Form\Model\Filter\UserFilterDto;
|
||||
use App\Repository\UserRepository;
|
||||
use Knp\Component\Pager\PaginatorInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
@@ -15,6 +18,8 @@ use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
#[IsGranted('ROLE_ADMIN')]
|
||||
class IndexController extends AbstractController
|
||||
{
|
||||
use ListFilterTrait;
|
||||
|
||||
public function __construct(
|
||||
private readonly UserRepository $userRepository,
|
||||
private readonly PaginatorInterface $paginator,
|
||||
@@ -24,13 +29,18 @@ class IndexController extends AbstractController
|
||||
#[Route('/admin/user', name: 'app_admin_user')]
|
||||
public function index(Request $request): Response
|
||||
{
|
||||
$qb = $this
|
||||
->userRepository
|
||||
->createQueryBuilder('user')
|
||||
;
|
||||
$filter = new UserFilterDto();
|
||||
|
||||
$filterView = $this->createListFilterView(
|
||||
$request,
|
||||
UserFilterType::class,
|
||||
$filter,
|
||||
'app_admin_user',
|
||||
['roles' => UserFilterType::ROLES],
|
||||
);
|
||||
|
||||
$pagination = $this->paginator->paginate(
|
||||
$qb,
|
||||
$this->userRepository->createFilteredQueryBuilder($filter),
|
||||
$request->query->getInt('page', 1),
|
||||
$request->query->getInt('limit', 50),
|
||||
[
|
||||
@@ -41,6 +51,8 @@ class IndexController extends AbstractController
|
||||
|
||||
return $this->render('admin/user/index.html.twig', [
|
||||
'pagination' => $pagination,
|
||||
'filter' => $filter,
|
||||
'filter_form' => $filterView,
|
||||
]);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user