Feat: Refactor assignment filter to modal

This commit is contained in:
Björn Fromme
2023-10-24 11:40:40 +02:00
parent 5e35af9665
commit cb06bcd636
9 changed files with 119 additions and 89 deletions
+2 -4
View File
@@ -3,7 +3,7 @@ import { useFetch } from '../mixins/use_fetch'
export default class extends Controller { export default class extends Controller {
static targets = [ 'title', 'content', 'spinner', 'backbutton' ] static targets = [ 'title', 'content', 'spinner' ]
static values = { loading: Boolean } static values = { loading: Boolean }
connect() { connect() {
@@ -41,9 +41,7 @@ export default class extends Controller {
this.loadingValue = true this.loadingValue = true
const form = event.target const form = event.target
const formData = new FormData(form) const formData = new FormData(form)
if (this.hasBackbuttonTarget && event.submitter === this.backbuttonTarget) { formData.append(event.submitter.name, event.submitter.value)
formData.append(this.backbuttonTarget.name, this.backbuttonTarget.value)
}
fetch(form.action, this.getInitObject('post', formData)) fetch(form.action, this.getInitObject('post', formData))
.then(this.checkStatus) .then(this.checkStatus)
.then(this.parseJSON) .then(this.parseJSON)
@@ -24,12 +24,7 @@ class IndexController extends AbstractController
#[IsGranted('ROLE_ADMINISTRATIVE')] #[IsGranted('ROLE_ADMINISTRATIVE')]
public function index(Request $request): Response public function index(Request $request): Response
{ {
$this->filterHandler->setNamespace('filter:assignment:admin'); $filterDto = $this->filterHandler->getFilterSettings();
$filterForm = $this->filterHandler->getForm();
$filterDto = $this->filterHandler->handleRequest($filterForm, $request);
if (true === $filterDto->isReset()) {
return $this->redirectToRoute('app_admin_assignment_index');
}
$query = $this $query = $this
->assignmentRepository ->assignmentRepository
@@ -48,7 +43,6 @@ class IndexController extends AbstractController
return $this->render('admin/assignment/index.html.twig', [ return $this->render('admin/assignment/index.html.twig', [
'pagination' => $pagination, 'pagination' => $pagination,
'filterForm' => $filterForm,
'filterDto' => $filterDto, 'filterDto' => $filterDto,
]); ]);
} }
@@ -0,0 +1,59 @@
<?php
namespace App\Controller\Common;
use App\Controller\Traits\ReturnUrlTrait;
use App\Form\AssignmentFilterType;
use App\Model\AjaxModalResponseDto;
use App\Repository\AssignmentRepository;
use App\Service\Common\AssignmentFilterHandler;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Http\Attribute\IsGranted;
class AssignmentFilterController extends AbstractController
{
use ReturnUrlTrait;
public function __construct(
private readonly AssignmentFilterHandler $filterHandler,
private readonly AssignmentRepository $assignmentRepository
) {
}
#[Route('/common/assignment/filter', name: 'app_common_assignment_filter')]
#[IsGranted('ROLE_USER')]
public function index(Request $request): JsonResponse
{
$response = new AjaxModalResponseDto();
$formAction = $this->generateUrl('app_common_assignment_filter', ['r' => $request->query->get('r')]);
$formData = $this->filterHandler->getFilterSettings();
$filterOptions = $this->assignmentRepository->getFilterOptions();
$formOptions = [
'action' => $formAction,
'ajax_submit' => true,
'min_date' => $filterOptions['minDate'],
'max_date' => $filterOptions['maxDate'],
'job_profiles' => $filterOptions['jobProfiles'],
'destinations' => $filterOptions['destinations'],
];
$form = $this->createForm(AssignmentFilterType::class, $formData, $formOptions);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$this->filterHandler->handleRequest($form);
$returnUrl = $this->getReturnUrl($request, 'app_admin_assignment_index');
$response->setCloseAndRedirect($returnUrl);
} else {
$response->setContent($this->renderView('common/assignment_filter.html.twig', [
'filterForm' => $form,
'filterDto' => $form->getData(),
]));
}
return $this->json($response);
}
}
+1 -7
View File
@@ -34,12 +34,7 @@ class IndexController extends AbstractController
// Validate teamer data to show missing data right away // Validate teamer data to show missing data right away
$errors = $this->validator->validate($teamer, null, ['profile_preflight']); $errors = $this->validator->validate($teamer, null, ['profile_preflight']);
$this->filterHandler->setNamespace('filter:assignment:teamer'); $filterDto = $this->filterHandler->getFilterSettings();
$filterForm = $this->filterHandler->getForm();
$filterDto = $this->filterHandler->handleRequest($filterForm, $request);
if (true === $filterDto->isReset()) {
return $this->redirectToRoute('app_teamer_index');
}
$query = $this $query = $this
->assignmentRepository ->assignmentRepository
@@ -60,7 +55,6 @@ class IndexController extends AbstractController
'teamer' => $teamer, 'teamer' => $teamer,
'errors' => $errors, 'errors' => $errors,
'pagination' => $pagination, 'pagination' => $pagination,
'filterForm' => $filterForm,
'filterDto' => $filterDto, 'filterDto' => $filterDto,
]); ]);
} }
+8 -36
View File
@@ -2,15 +2,11 @@
namespace App\Service\Common; namespace App\Service\Common;
use App\Entity\Assignment;
use App\Entity\Destination; use App\Entity\Destination;
use App\Entity\JobProfile; use App\Entity\JobProfile;
use App\Form\AssignmentFilterType;
use App\Model\AssignmentFilterDto; use App\Model\AssignmentFilterDto;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Form\FormFactoryInterface;
use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\FormInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Session\SessionInterface; use Symfony\Component\HttpFoundation\Session\SessionInterface;
@@ -20,8 +16,7 @@ class AssignmentFilterHandler
public function __construct( public function __construct(
private readonly RequestStack $requestStack, private readonly RequestStack $requestStack,
private readonly EntityManagerInterface $entityManager, private readonly EntityManagerInterface $entityManager
private readonly FormFactoryInterface $formFactory,
) { ) {
} }
@@ -32,44 +27,21 @@ class AssignmentFilterHandler
return $this; return $this;
} }
public function getForm(): FormInterface public function handleRequest(FormInterface $form): AssignmentFilterDto
{ {
$filterDto = $this->getFilterSettings();
$assignmentRepository = $this
->entityManager
->getRepository(Assignment::class)
;
$filterOptions = $assignmentRepository->getFilterOptions();
return $this->formFactory->create(AssignmentFilterType::class, $filterDto, [
'min_date' => $filterOptions['minDate'],
'max_date' => $filterOptions['maxDate'],
'job_profiles' => $filterOptions['jobProfiles'],
'destinations' => $filterOptions['destinations'],
]);
}
public function handleRequest(
FormInterface $form,
Request $request
): AssignmentFilterDto {
$form->handleRequest($request);
$filterDto = $form->getData(); $filterDto = $form->getData();
if ($form->isSubmitted() && $form->isValid()) { if ($form->get('reset')->isClicked()) {
if ($form->has('reset') && $form->get('reset')->isClicked()) { $filterDto = new AssignmentFilterDto(true);
$filterDto = new AssignmentFilterDto(true); $this->getSession()->remove($this->namespace);
$this->getSession()->remove($this->namespace); } elseif ($form->get('apply')->isClicked()) {
} elseif ($form->has('apply') && $form->get('apply')->isClicked()) { $this->saveFilterSettings($filterDto);
$this->saveFilterSettings($filterDto);
}
} }
return $filterDto; return $filterDto;
} }
private function getFilterSettings(): AssignmentFilterDto public function getFilterSettings(): AssignmentFilterDto
{ {
if (null === $data = $this->getSession()->get($this->namespace)) { if (null === $data = $this->getSession()->get($this->namespace)) {
return new AssignmentFilterDto(); return new AssignmentFilterDto();
@@ -1,25 +0,0 @@
{{ form_start(filterForm) }}
<div class="border border-gray-200 rounded-md p-2 mb-4" {{stimulus_controller('toggle', [], {'closed': 'hidden'}) }}>
<button type="button" {{ stimulus_action('toggle', 'toggle') }}
class="btn btn--small">
<div class="flex items-center space-x-2">
{{ icon('filter', 'w-5 h-5') }}
{% if filterDto.active %}<span>{{ filterDto.activeFiltersCount }} Filter aktiv</span>{% endif %}
</div>
</button>
<div class="hidden" {{ stimulus_target('toggle', 'toggle') }}>
<div class="grid grid-cols-2 md:grid-cols-5 gap-x-1 gap-y-2 py-2">
{{ form_row(filterForm.dateFrom) }}
{{ form_row(filterForm.dateTo) }}
{{ form_row(filterForm.jobProfile) }}
{{ form_row(filterForm.destination) }}
{{ form_row(filterForm.duration) }}
</div>
<div class="flex items-center space-x-2">
{{ form_widget(filterForm.apply, { 'attr': { 'class': 'btn btn--small' } }) }}
{{ form_widget(filterForm.reset, { 'attr': { 'class': 'btn btn--small btn--secondary' } }) }}
</div>
</div>
</div>
{{ form_rest(filterForm) }}
{{ form_end(filterForm) }}
+17 -5
View File
@@ -3,11 +3,23 @@
{% block title %}Einsatzübersicht{% endblock %} {% block title %}Einsatzübersicht{% endblock %}
{% block content %} {% block content %}
<h1 class="text-2xl font-bold pb-4"> <div class="flex items-start justify-between">
Einsatzübersicht <h1 class="text-2xl font-bold pb-4">
</h1> Einsatzübersicht
</h1>
{% include '_partials/_filterpanel.html.twig' %} <button type="button"
class="{{ html_classes('btn btn--small', { 'btn--secondary': filterDto.active }) }}"
{{ stimulus_controller('modal-button', [], [], {'ajax-modal': '#ajax-modal'}) }}
{{ stimulus_action('modal-button', 'ajax', null, {
'title': 'Einsätze filtern',
'url': path('app_common_assignment_filter', { 'r': return_url() })
}) }}>
<div class="flex items-center space-x-1">
{{ icon('filter', 'w-5 h-5 shrink-0') }}
{% if filterDto.active %}<span>{{ filterDto.activeFiltersCount }} Filter aktiv</span>{% endif %}
</div>
</button>
</div>
<div class="data-table-wrapper"> <div class="data-table-wrapper">
<div class="data-table-wrapper__inner"> <div class="data-table-wrapper__inner">
@@ -0,0 +1,14 @@
{{ form_start(filterForm) }}
<div class="flex flex-col space-y-2 pb-2">
{{ form_row(filterForm.dateFrom) }}
{{ form_row(filterForm.dateTo) }}
{{ form_row(filterForm.jobProfile) }}
{{ form_row(filterForm.destination) }}
{{ form_row(filterForm.duration) }}
</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) }}
+17 -5
View File
@@ -3,9 +3,23 @@
{% block title %}Einsatzübersicht{% endblock %} {% block title %}Einsatzübersicht{% endblock %}
{% block content %} {% block content %}
<h1 class="text-2xl font-bold pb-4"> <div class="flex items-start justify-between">
Einsatzübersicht <h1 class="text-2xl font-bold pb-4">
</h1> Einsatzübersicht
</h1>
<button type="button"
class="{{ html_classes('btn btn--small', { 'btn--secondary': filterDto.active }) }}"
{{ stimulus_controller('modal-button', [], [], {'ajax-modal': '#ajax-modal'}) }}
{{ stimulus_action('modal-button', 'ajax', null, {
'title': 'Einsätze filtern',
'url': path('app_common_assignment_filter', { 'r': return_url() })
}) }}>
<div class="flex items-center space-x-1">
{{ icon('filter', 'w-5 h-5 shrink-0') }}
{% if filterDto.active %}<span>{{ filterDto.activeFiltersCount }} Filter aktiv</span>{% endif %}
</div>
</button>
</div>
{% if errors|length %} {% if errors|length %}
<div class="border border-red-500 rounded-md p-4 text-red-500 mb-8"> <div class="border border-red-500 rounded-md p-4 text-red-500 mb-8">
<ul> <ul>
@@ -18,8 +32,6 @@
</div> </div>
{% endif %} {% endif %}
{% include '_partials/_filterpanel.html.twig' %}
{{ knp_pagination_render(pagination, 'paginator/sliding_boxes.html.twig') }} {{ knp_pagination_render(pagination, 'paginator/sliding_boxes.html.twig') }}
<div class="grid sm:grid-cols-2 md:grid-cols-3 gap-4 py-4"> <div class="grid sm:grid-cols-2 md:grid-cols-3 gap-4 py-4">
{% for assignment in pagination %} {% for assignment in pagination %}