feat: filter documents
This commit is contained in:
@@ -31,7 +31,6 @@ export default class extends Controller {
|
||||
}
|
||||
|
||||
clickOutside(e) {
|
||||
e.preventDefault()
|
||||
this.dropdownTarget.classList.toggle('hidden', true)
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace App\Controller\Administrative\Document;
|
||||
|
||||
use App\Repository\UploadRepository;
|
||||
use App\Service\Common\DocumentFilterHandler;
|
||||
use Knp\Component\Pager\PaginatorInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
@@ -14,7 +15,8 @@ class IndexController extends AbstractController
|
||||
{
|
||||
public function __construct(
|
||||
private readonly UploadRepository $uploadRepository,
|
||||
private readonly PaginatorInterface $paginator
|
||||
private readonly PaginatorInterface $paginator,
|
||||
private readonly DocumentFilterHandler $filterHandler
|
||||
) {
|
||||
}
|
||||
|
||||
@@ -22,9 +24,11 @@ class IndexController extends AbstractController
|
||||
#[IsGranted('ROLE_ADMINISTRATIVE')]
|
||||
public function index(Request $request): Response
|
||||
{
|
||||
$filterDto = $this->filterHandler->getFilterSettings();
|
||||
|
||||
$query = $this
|
||||
->uploadRepository
|
||||
->getUploadListQuery()
|
||||
->getUploadListQuery($filterDto)
|
||||
;
|
||||
|
||||
$pagination = $this->paginator->paginate(
|
||||
@@ -35,6 +39,7 @@ class IndexController extends AbstractController
|
||||
|
||||
return $this->render('administrative/document/index.html.twig', [
|
||||
'pagination' => $pagination,
|
||||
'filterDto' => $filterDto,
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controller\Common;
|
||||
|
||||
use App\Controller\Traits\ReturnUrlTrait;
|
||||
use App\Form\DocumentFilterType;
|
||||
use App\Htmx\HxRedirectResponse;
|
||||
use App\Service\Common\DocumentFilterHandler;
|
||||
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;
|
||||
|
||||
class DocumentFilterController extends AbstractController
|
||||
{
|
||||
use ReturnUrlTrait;
|
||||
|
||||
public function __construct(
|
||||
private readonly DocumentFilterHandler $filterHandler
|
||||
) {
|
||||
}
|
||||
|
||||
#[Route('/common/document/filter', name: 'app_common_document_filter')]
|
||||
#[IsGranted('ROLE_ADMINISTRATIVE')]
|
||||
public function index(Request $request): Response
|
||||
{
|
||||
$formData = $this->filterHandler->getFilterSettings();
|
||||
|
||||
$form = $this->createForm(DocumentFilterType::class, $formData);
|
||||
$form->handleRequest($request);
|
||||
|
||||
if ($form->isSubmitted() && $form->isValid()) {
|
||||
$this->filterHandler->handleRequest($form);
|
||||
$returnUrl = $this->getReturnUrl($request, 'app_administrative_document_index');
|
||||
|
||||
return new HxRedirectResponse($returnUrl);
|
||||
}
|
||||
|
||||
return $this->render('common/modal_document_filter.html.twig', [
|
||||
'filterForm' => $form->createView(),
|
||||
'filterDto' => $form->getData(),
|
||||
]);
|
||||
}
|
||||
|
||||
#[Route('/common/document/filter/reset', name: 'app_common_document_filter_reset')]
|
||||
public function reset(Request $request): Response
|
||||
{
|
||||
$this->filterHandler->resetFilterSettings();
|
||||
$returnUrl = $this->getReturnUrl($request, 'app_administrative_document_index');
|
||||
|
||||
return $this->redirect($returnUrl);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
namespace App\Form;
|
||||
|
||||
use App\Entity\Teamer;
|
||||
use App\Entity\Upload;
|
||||
use App\Model\DocumentFilterDto;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
||||
class DocumentFilterType extends AbstractType
|
||||
{
|
||||
public function buildForm(FormBuilderInterface $builder, array $options): void
|
||||
{
|
||||
$builder
|
||||
->add('teamer', AutocompleteEntityType::class, [
|
||||
'label' => 'Teamer',
|
||||
'class' => Teamer::class,
|
||||
'label_property' => 'name',
|
||||
'label_function' => fn(Teamer $teamer) => (string) $teamer,
|
||||
'endpoint_route' => 'app_admin_autocomplete_teamer',
|
||||
])
|
||||
->add('type', ChoiceType::class, [
|
||||
'label' => 'Typ',
|
||||
'required' => false,
|
||||
'placeholder' => 'nicht filtern',
|
||||
'choices' => [
|
||||
'Honorarnote' => Upload::TYPE_INVOICE,
|
||||
'Honorarvertrag' => Upload::TYPE_CONTRACT,
|
||||
],
|
||||
])
|
||||
->add('dateFrom', DatepickerType::class, [
|
||||
'label' => 'Einsatzzeitraum von',
|
||||
'attr' => [
|
||||
'placeholder' => 'nicht filtern',
|
||||
],
|
||||
])
|
||||
->add('dateTo', DatepickerType::class, [
|
||||
'label' => 'Einsatzzeitraum bis',
|
||||
'attr' => [
|
||||
'placeholder' => 'nicht filtern',
|
||||
],
|
||||
])
|
||||
->add('apply', SubmitType::class, [
|
||||
'label' => 'filtern',
|
||||
])
|
||||
->add('reset', SubmitType::class, [
|
||||
'label' => 'reset',
|
||||
])
|
||||
;
|
||||
}
|
||||
|
||||
public function configureOptions(OptionsResolver $resolver): void
|
||||
{
|
||||
$resolver
|
||||
->setDefaults([
|
||||
'data_class' => DocumentFilterDto::class,
|
||||
])
|
||||
;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
namespace App\Model;
|
||||
|
||||
use App\Entity\Teamer;
|
||||
|
||||
class DocumentFilterDto extends AbstractFilterDto
|
||||
{
|
||||
protected ?Teamer $teamer = null;
|
||||
protected ?string $type = null;
|
||||
protected ?\DateTimeImmutable $dateFrom = null;
|
||||
protected ?\DateTimeImmutable $dateTo = null;
|
||||
|
||||
public function getTeamer(): ?Teamer
|
||||
{
|
||||
return $this->teamer;
|
||||
}
|
||||
|
||||
public function setTeamer(?Teamer $teamer): static
|
||||
{
|
||||
$this->teamer = $teamer;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getType(): ?string
|
||||
{
|
||||
return $this->type;
|
||||
}
|
||||
|
||||
public function setType(?string $type): static
|
||||
{
|
||||
$this->type = $type;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getDateFrom(): ?\DateTimeImmutable
|
||||
{
|
||||
return $this->dateFrom;
|
||||
}
|
||||
|
||||
public function setDateFrom(?\DateTimeImmutable $dateFrom): static
|
||||
{
|
||||
$this->dateFrom = $dateFrom;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getDateTo(): ?\DateTimeImmutable
|
||||
{
|
||||
return $this->dateTo;
|
||||
}
|
||||
|
||||
public function setDateTo(?\DateTimeImmutable $dateTo): static
|
||||
{
|
||||
$this->dateTo = $dateTo;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace App\Repository;
|
||||
|
||||
use App\Entity\Upload;
|
||||
use App\Model\DocumentFilterDto;
|
||||
use App\Repository\Traits\QueryHelperTrait;
|
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
use Doctrine\ORM\Query;
|
||||
@@ -78,11 +79,11 @@ class UploadRepository extends ServiceEntityRepository
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function getUploadListQuery(): Query
|
||||
public function getUploadListQuery(DocumentFilterDto $filterDto): Query
|
||||
{
|
||||
$qb = $this->createQueryBuilder('upload');
|
||||
|
||||
return $qb
|
||||
$qb
|
||||
->select('upload', 'disposition', 'assignment', 'job_profile', 'destination', 'teamer')
|
||||
->innerJoin('upload.disposition', 'disposition')
|
||||
->innerJoin('disposition.assignment', 'assignment')
|
||||
@@ -92,8 +93,37 @@ class UploadRepository extends ServiceEntityRepository
|
||||
->addOrderBy('FIELD(upload.status, :new, :checked)', 'ASC')
|
||||
->setParameter('new', Upload::STATUS_NEW)
|
||||
->setParameter('checked', Upload::STATUS_CHECKED)
|
||||
->getQuery()
|
||||
;
|
||||
|
||||
if (null !== $teamer = $filterDto->getTeamer()) {
|
||||
$qb
|
||||
->andWhere($qb->expr()->eq('upload.teamer', ':teamer'))
|
||||
->setParameter('teamer', $teamer)
|
||||
;
|
||||
}
|
||||
|
||||
if (null !== $type = $filterDto->getType()) {
|
||||
$qb
|
||||
->andWhere($qb->expr()->eq('upload.type', ':type'))
|
||||
->setParameter('type', $type)
|
||||
;
|
||||
}
|
||||
|
||||
if (null !== $dateFrom = $filterDto->getDateFrom()) {
|
||||
$qb
|
||||
->andWhere($qb->expr()->gte('destination.dateFrom', ':dateFrom'))
|
||||
->setParameter('dateFrom', $dateFrom)
|
||||
;
|
||||
}
|
||||
|
||||
if (null !== $dateTo = $filterDto->getDateTo()) {
|
||||
$qb
|
||||
->andWhere($qb->expr()->lte('destination.dateTo', ':dateTo'))
|
||||
->setParameter('dateTo', $dateTo)
|
||||
;
|
||||
}
|
||||
|
||||
return $qb->getQuery();
|
||||
}
|
||||
|
||||
public function getNew(int $limit = 5): array
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
namespace App\Service\Common;
|
||||
|
||||
use App\Model\AbstractFilterDto;
|
||||
use App\Model\AssignmentFilterDto;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
use Symfony\Component\HttpFoundation\Session\SessionInterface;
|
||||
|
||||
abstract class AbstractFilterHandler
|
||||
{
|
||||
protected string $namespace = 'filter:default';
|
||||
|
||||
public function __construct(
|
||||
protected readonly RequestStack $requestStack,
|
||||
protected readonly EntityManagerInterface $entityManager
|
||||
) {
|
||||
}
|
||||
|
||||
public function setNamespace(string $namespace): static
|
||||
{
|
||||
$this->namespace = $namespace;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function handleRequest(FormInterface $form): AbstractFilterDto
|
||||
{
|
||||
$filterDto = $form->getData();
|
||||
|
||||
if ($form->get('reset')->isClicked()) {
|
||||
$filterDto = new AssignmentFilterDto();
|
||||
$this->resetFilterSettings();
|
||||
} elseif ($form->get('apply')->isClicked()) {
|
||||
$this->saveFilterSettings($filterDto);
|
||||
}
|
||||
|
||||
return $filterDto;
|
||||
}
|
||||
|
||||
public function resetFilterSettings(): void
|
||||
{
|
||||
$this->getSession()->remove($this->namespace);
|
||||
}
|
||||
|
||||
public function getFilterSettings(): AbstractFilterDto
|
||||
{
|
||||
}
|
||||
|
||||
protected function saveFilterSettings(AbstractFilterDto $filterDto): void
|
||||
{
|
||||
}
|
||||
|
||||
protected function getSession(): SessionInterface
|
||||
{
|
||||
return $this->requestStack->getSession();
|
||||
}
|
||||
}
|
||||
@@ -3,47 +3,12 @@
|
||||
namespace App\Service\Common;
|
||||
|
||||
use App\Entity\JobProfile;
|
||||
use App\Model\AbstractFilterDto;
|
||||
use App\Model\AssignmentFilterDto;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
use Symfony\Component\HttpFoundation\Session\SessionInterface;
|
||||
|
||||
class AssignmentFilterHandler
|
||||
class AssignmentFilterHandler extends AbstractFilterHandler
|
||||
{
|
||||
private string $namespace = 'filter:assignment';
|
||||
|
||||
public function __construct(
|
||||
private readonly RequestStack $requestStack,
|
||||
private readonly EntityManagerInterface $entityManager
|
||||
) {
|
||||
}
|
||||
|
||||
public function setNamespace(string $namespace): static
|
||||
{
|
||||
$this->namespace = $namespace;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function handleRequest(FormInterface $form): AssignmentFilterDto
|
||||
{
|
||||
$filterDto = $form->getData();
|
||||
|
||||
if ($form->get('reset')->isClicked()) {
|
||||
$filterDto = new AssignmentFilterDto();
|
||||
$this->resetFilterSettings();
|
||||
} elseif ($form->get('apply')->isClicked()) {
|
||||
$this->saveFilterSettings($filterDto);
|
||||
}
|
||||
|
||||
return $filterDto;
|
||||
}
|
||||
|
||||
public function resetFilterSettings(): void
|
||||
{
|
||||
$this->getSession()->remove($this->namespace);
|
||||
}
|
||||
protected string $namespace = 'filter:assignment';
|
||||
|
||||
public function getFilterSettings(): AssignmentFilterDto
|
||||
{
|
||||
@@ -83,8 +48,9 @@ class AssignmentFilterHandler
|
||||
return $filterDto;
|
||||
}
|
||||
|
||||
private function saveFilterSettings(AssignmentFilterDto $filterDto): void
|
||||
protected function saveFilterSettings(AbstractFilterDto $filterDto): void
|
||||
{
|
||||
/** @var AssignmentFilterDto $filterDto */
|
||||
$this->getSession()->set($this->namespace, [
|
||||
'date_from' => $filterDto->getDateFrom(),
|
||||
'date_to' => $filterDto->getDateTo(),
|
||||
@@ -97,9 +63,4 @@ class AssignmentFilterHandler
|
||||
'include_past' => $filterDto->isIncludePast(),
|
||||
]);
|
||||
}
|
||||
|
||||
private function getSession(): SessionInterface
|
||||
{
|
||||
return $this->requestStack->getSession();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
namespace App\Service\Common;
|
||||
|
||||
use App\Entity\Teamer;
|
||||
use App\Model\AbstractFilterDto;
|
||||
use App\Model\DocumentFilterDto;
|
||||
|
||||
class DocumentFilterHandler extends AbstractFilterHandler
|
||||
{
|
||||
protected string $namespace = 'filter:document';
|
||||
|
||||
public function getFilterSettings(): DocumentFilterDto
|
||||
{
|
||||
if (null === $data = $this->getSession()->get($this->namespace)) {
|
||||
return new DocumentFilterDto();
|
||||
}
|
||||
|
||||
$filterDto = new DocumentFilterDto();
|
||||
|
||||
$filterDto
|
||||
->setType($data['type'])
|
||||
->setDateFrom($data['date_from'])
|
||||
->setDateTo($data['date_to'])
|
||||
;
|
||||
|
||||
if (isset($data['teamer_id'])) {
|
||||
$teamer = $this
|
||||
->entityManager
|
||||
->getRepository(Teamer::class)
|
||||
->find($data['teamer_id'])
|
||||
;
|
||||
$filterDto->setTeamer($teamer);
|
||||
}
|
||||
|
||||
return $filterDto;
|
||||
}
|
||||
|
||||
protected function saveFilterSettings(AbstractFilterDto $filterDto): void
|
||||
{
|
||||
/** @var DocumentFilterDto $filterDto */
|
||||
$this->getSession()->set($this->namespace, [
|
||||
'teamer_id' => $filterDto->getTeamer()?->getId(),
|
||||
'type' => $filterDto->getType(),
|
||||
'date_from' => $filterDto->getDateFrom(),
|
||||
'date_to' => $filterDto->getDateTo(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -3,47 +3,12 @@
|
||||
namespace App\Service\Common;
|
||||
|
||||
use App\Entity\JobProfile;
|
||||
use App\Model\AbstractFilterDto;
|
||||
use App\Model\TeamerFilterDto;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
use Symfony\Component\HttpFoundation\Session\SessionInterface;
|
||||
|
||||
class TeamerFilterHandler
|
||||
class TeamerFilterHandler extends AbstractFilterHandler
|
||||
{
|
||||
private string $namespace = 'filter:teamer';
|
||||
|
||||
public function __construct(
|
||||
private readonly RequestStack $requestStack,
|
||||
private readonly EntityManagerInterface $entityManager
|
||||
) {
|
||||
}
|
||||
|
||||
public function setNamespace(string $namespace): static
|
||||
{
|
||||
$this->namespace = $namespace;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function handleRequest(FormInterface $form): TeamerFilterDto
|
||||
{
|
||||
$filterDto = $form->getData();
|
||||
|
||||
if ($form->get('reset')->isClicked()) {
|
||||
$filterDto = new TeamerFilterDto();
|
||||
$this->resetFilterSettings();
|
||||
} elseif ($form->get('apply')->isClicked()) {
|
||||
$this->saveFilterSettings($filterDto);
|
||||
}
|
||||
|
||||
return $filterDto;
|
||||
}
|
||||
|
||||
public function resetFilterSettings(): void
|
||||
{
|
||||
$this->getSession()->remove($this->namespace);
|
||||
}
|
||||
protected string $namespace = 'filter:teamer';
|
||||
|
||||
public function getFilterSettings(): TeamerFilterDto
|
||||
{
|
||||
@@ -74,8 +39,9 @@ class TeamerFilterHandler
|
||||
return $filterDto;
|
||||
}
|
||||
|
||||
private function saveFilterSettings(TeamerFilterDto $filterDto): void
|
||||
protected function saveFilterSettings(AbstractFilterDto $filterDto): void
|
||||
{
|
||||
/** @var TeamerFilterDto $filterDto */
|
||||
$this->getSession()->set($this->namespace, [
|
||||
'name' => $filterDto->getName(),
|
||||
'available_at' => $filterDto->getAvailableAt(),
|
||||
@@ -88,9 +54,4 @@ class TeamerFilterHandler
|
||||
}, $filterDto->getJobProfiles()),
|
||||
]);
|
||||
}
|
||||
|
||||
private function getSession(): SessionInterface
|
||||
{
|
||||
return $this->requestStack->getSession();
|
||||
}
|
||||
}
|
||||
@@ -3,104 +3,126 @@
|
||||
{% block title %}Dokumentenübersicht{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h1 class="text-2xl font-bold pb-8">
|
||||
<div class="flex items-start justify-between pb-4">
|
||||
<h1 class="text-2xl font-bold">
|
||||
Dokumentenübersicht
|
||||
</h1>
|
||||
<div class="data-table-wrapper">
|
||||
<div class="data-table-wrapper__inner">
|
||||
<table class="data-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>
|
||||
{{ knp_pagination_sortable(pagination, 'Einsatz­zeitraum', 'destination.dateFrom') }}
|
||||
</th>
|
||||
<th>
|
||||
{{ knp_pagination_sortable(pagination, 'Destination', 'destination.product') }}
|
||||
</th>
|
||||
<th>
|
||||
{{ knp_pagination_sortable(pagination, 'Jobprofil', 'job_profile.name') }}
|
||||
</th>
|
||||
<th>
|
||||
{{ knp_pagination_sortable(pagination, 'Dokument', 'upload.type') }}
|
||||
</th>
|
||||
<th>
|
||||
{{ knp_pagination_sortable(pagination, 'Teamer:in', 'teamer.lastName') }}
|
||||
</th>
|
||||
<th>
|
||||
{{ knp_pagination_sortable(pagination, 'Status', 'upload.status') }}
|
||||
</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for upload in pagination %}
|
||||
{% set disposition = upload.disposition %}
|
||||
{% set assignment = disposition.assignment %}
|
||||
<tr>
|
||||
<td>
|
||||
{{ assignment.destination.dateFrom|date('d.m.Y') }}
|
||||
-
|
||||
{{ assignment.destination.dateTo|date('d.m.Y') }}
|
||||
</td>
|
||||
<td>
|
||||
<div class="flex items-start space-x-2">
|
||||
{{ icon('flag-' ~ assignment.destination.country, 'w-5 h-5 shrink-0') }}
|
||||
<div class="flex-1">
|
||||
{{ assignment.destination.product }}
|
||||
<br>
|
||||
{{ assignment.destination.hotel }}
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
{{ assignment.jobProfile.name }}
|
||||
</td>
|
||||
<td>
|
||||
{{ ('label.document.type.' ~ upload.type)|trans }}
|
||||
</td>
|
||||
<td>
|
||||
{{ disposition.teamer }}
|
||||
</td>
|
||||
<td>
|
||||
{{ upload.status|upload_status_badge }}
|
||||
</td>
|
||||
<td>
|
||||
<div class="flex items-center space-x-2 justify-end">
|
||||
{% if is_granted('DELETE', upload) %}
|
||||
<button type="button"
|
||||
class="text-red-500"
|
||||
hx-get="{{ path('app_administrative_document_delete', { 'uuid': upload.uuid }) }}"
|
||||
hx-target="body"
|
||||
hx-swap="beforeend">
|
||||
{{ icon('delete') }}
|
||||
</button>
|
||||
{% endif %}
|
||||
{% if is_granted('CHECK', upload) %}
|
||||
<button type="button"
|
||||
hx-get="{{ path('app_administrative_document_check', { 'uuid': upload.uuid }) }}"
|
||||
hx-target="body"
|
||||
hx-swap="beforeend">
|
||||
{{ icon('edit') }}
|
||||
</button>
|
||||
{% endif %}
|
||||
<a href="{{ path('app_common_download', { 'uuid': upload.uuid, 'inline': true }) }}"
|
||||
target="_blank"
|
||||
title="Download">
|
||||
{{ icon('eye') }}
|
||||
</a>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{% else %}
|
||||
<tr>
|
||||
<td colspan="7">
|
||||
Keine Daten...
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{{ knp_pagination_render(pagination) }}
|
||||
</div>
|
||||
<div class="flex flex-col items-end space-y-2 md:flex-row md:items-center md:space-x-2 md:space-y-0">
|
||||
<button type="button"
|
||||
class="{{ html_classes('btn btn--small', { 'btn--secondary': filterDto.active }) }}"
|
||||
title="Filter"
|
||||
hx-get="{{ path('app_common_document_filter', { 'r': return_url() }) }}"
|
||||
hx-target="body"
|
||||
hx-swap="beforeend">
|
||||
{{ icon('filter', 'w-4 h-4 shrink-0') }}
|
||||
{% if filterDto.active %}
|
||||
<span class="whitespace-nowrap">{{ filterDto.activeFiltersCount }} Filter aktiv</span>
|
||||
{% else %}
|
||||
<span>Filter</span>
|
||||
{% endif %}
|
||||
</button>
|
||||
{% if filterDto.active %}
|
||||
<a href="{{ path('app_common_document_filter_reset', { 'r': return_url() }) }}" class="btn btn--small btn--secondary">
|
||||
Reset
|
||||
</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="data-table-wrapper">
|
||||
<div class="data-table-wrapper__inner">
|
||||
<table class="data-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>
|
||||
{{ knp_pagination_sortable(pagination, 'Einsatz­zeitraum', 'destination.dateFrom') }}
|
||||
</th>
|
||||
<th>
|
||||
{{ knp_pagination_sortable(pagination, 'Destination', 'destination.product') }}
|
||||
</th>
|
||||
<th>
|
||||
{{ knp_pagination_sortable(pagination, 'Jobprofil', 'job_profile.name') }}
|
||||
</th>
|
||||
<th>
|
||||
{{ knp_pagination_sortable(pagination, 'Dokument', 'upload.type') }}
|
||||
</th>
|
||||
<th>
|
||||
{{ knp_pagination_sortable(pagination, 'Teamer:in', 'teamer.lastName') }}
|
||||
</th>
|
||||
<th>
|
||||
{{ knp_pagination_sortable(pagination, 'Status', 'upload.status') }}
|
||||
</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for upload in pagination %}
|
||||
{% set disposition = upload.disposition %}
|
||||
{% set assignment = disposition.assignment %}
|
||||
<tr>
|
||||
<td>
|
||||
{{ assignment.destination.dateFrom|date('d.m.Y') }}
|
||||
-
|
||||
{{ assignment.destination.dateTo|date('d.m.Y') }}
|
||||
</td>
|
||||
<td>
|
||||
<div class="flex items-start space-x-2">
|
||||
{{ icon('flag-' ~ assignment.destination.country, 'w-5 h-5 shrink-0') }}
|
||||
<div class="flex-1">
|
||||
{{ assignment.destination.product }}
|
||||
<br>
|
||||
{{ assignment.destination.hotel }}
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
{{ assignment.jobProfile.name }}
|
||||
</td>
|
||||
<td>
|
||||
{{ ('label.document.type.' ~ upload.type)|trans }}
|
||||
</td>
|
||||
<td>
|
||||
{{ disposition.teamer }}
|
||||
</td>
|
||||
<td>
|
||||
{{ upload.status|upload_status_badge }}
|
||||
</td>
|
||||
<td>
|
||||
<div class="flex items-center space-x-2 justify-end">
|
||||
{% if is_granted('DELETE', upload) %}
|
||||
<button type="button"
|
||||
class="text-red-500"
|
||||
hx-get="{{ path('app_administrative_document_delete', { 'uuid': upload.uuid }) }}"
|
||||
hx-target="body"
|
||||
hx-swap="beforeend">
|
||||
{{ icon('delete') }}
|
||||
</button>
|
||||
{% endif %}
|
||||
{% if is_granted('CHECK', upload) %}
|
||||
<button type="button"
|
||||
hx-get="{{ path('app_administrative_document_check', { 'uuid': upload.uuid }) }}"
|
||||
hx-target="body"
|
||||
hx-swap="beforeend">
|
||||
{{ icon('edit') }}
|
||||
</button>
|
||||
{% endif %}
|
||||
<a href="{{ path('app_common_download', { 'uuid': upload.uuid, 'inline': true }) }}"
|
||||
target="_blank"
|
||||
title="Download">
|
||||
{{ icon('eye') }}
|
||||
</a>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{% else %}
|
||||
<tr>
|
||||
<td colspan="7">
|
||||
Keine Daten...
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{{ knp_pagination_render(pagination) }}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,19 @@
|
||||
{% extends 'htmx_modal.html.twig' %}
|
||||
|
||||
{% block title %}Dokumente filtern{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
{{ form_start(filterForm, { 'attr': { 'hx-post': app.request.uri, 'hx-target': '#htmx-modal', 'hx-swap': 'outerHTML' } }) }}
|
||||
<div class="flex flex-col space-y-2 pb-4">
|
||||
{{ form_row(filterForm.type) }}
|
||||
{{ form_row(filterForm.teamer) }}
|
||||
{{ form_row(filterForm.dateFrom) }}
|
||||
{{ form_row(filterForm.dateTo) }}
|
||||
</div>
|
||||
<div class="flex items-center space-x-2">
|
||||
{{ form_widget(filterForm.apply, { 'attr': { 'class': 'btn' } }) }}
|
||||
{{ form_widget(filterForm.reset, { 'attr': { 'class': 'btn btn--secondary' } }) }}
|
||||
</div>
|
||||
{{ form_rest(filterForm) }}
|
||||
{{ form_end(filterForm) }}
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user