feat: integrate with htmx

This commit is contained in:
Björn Fromme
2024-02-07 10:15:59 +01:00
parent 4d1799ca49
commit 1e572606f8
154 changed files with 1447 additions and 1461 deletions
+1
View File
@@ -1,3 +1,4 @@
import 'htmx.org';
import './bootstrap.js'; import './bootstrap.js';
/* /*
* Welcome to your app's main JavaScript file! * Welcome to your app's main JavaScript file!
@@ -1,86 +0,0 @@
import { Controller } from '@hotwired/stimulus'
import { useFetch } from '../mixins/use_fetch'
export default class extends Controller {
static targets = [ 'title', 'content', 'spinner' ]
static values = { loading: Boolean }
connect() {
useFetch(this)
}
show({ title, url }) {
this.titleTarget.innerHTML = title
this.element.classList.remove('hidden')
this.loadContent(url)
}
hide() {
this.element.classList.add('hidden')
}
loadContent(url) {
this.loadingValue = true
fetch(url, this.getInitObject())
.then(this.checkStatus)
.then(this.parseJSON)
.then(response => {
this.handleResponse(response)
})
.catch(error => {
this.handleResponse(this.createErrorResponse(error))
})
.finally(() => {
this.loadingValue = false
})
}
submitForm(event) {
event.preventDefault()
this.loadingValue = true
const form = event.target
const formData = new FormData(form)
formData.append(event.submitter.name, event.submitter.value)
fetch(form.action, this.getInitObject('post', formData))
.then(this.checkStatus)
.then(this.parseJSON)
.then(response => {
this.handleResponse(response)
})
.catch(error => {
this.handleResponse(this.createErrorResponse(error))
})
.finally(() => {
this.loadingValue = false
})
}
handleResponse(modalResponse) {
if (modalResponse.redirect) {
window.location = modalResponse.redirect
return
}
if (true === modalResponse.close) {
this.element.classList.add('hidden')
return
}
this.contentTarget.innerHTML = modalResponse.content
}
createErrorResponse(error) {
return {
close: false,
redirect: null,
content: error.message,
}
}
loadingValueChanged() {
this.spinnerTarget.classList.toggle('hidden', false === this.loadingValue)
this.contentTarget.classList.toggle('hidden', true === this.loadingValue)
}
}
@@ -1,17 +0,0 @@
import { Controller } from '@hotwired/stimulus'
export default class extends Controller {
static targets = [ 'form', 'title', 'content' ]
show({ targetUrl, title, content }) {
this.formTarget.action = targetUrl
this.titleTarget.innerText = title
this.contentTarget.innerHTML = content
this.element.classList.remove('hidden')
}
hide() {
this.element.classList.add('hidden')
}
}
@@ -1,35 +0,0 @@
import { Controller } from '@hotwired/stimulus'
import { useFetch } from '../mixins/use_fetch'
export default class extends Controller {
static targets = [ 'form', 'container', 'spinner' ]
static values = { url: String, loading: Boolean }
connect() {
useFetch(this)
}
update() {
this.loadingValue = true
const formData = new FormData(this.formTarget)
fetch(this.urlValue, { method: 'POST', body: formData })
.then(this.checkStatus)
.then(this.parseHTML)
.then(response => {
this.containerTarget.innerHTML = response
})
.catch(error => {
})
.finally(() => {
this.loadingValue = false
})
}
loadingValueChanged(loading) {
if (this.hasSpinnerTarget) {
this.spinnerTarget.classList.toggle('hidden', false === loading)
}
}
}
@@ -1,13 +0,0 @@
import { Controller } from '@hotwired/stimulus'
export default class extends Controller {
static outlets = [ 'confirmation-modal', 'ajax-modal' ]
confirmation({ params: { title, targetUrl, content } }) {
this.confirmationModalOutlet.show({ title, targetUrl, content })
}
ajax({ params: { title, url } }) {
this.ajaxModalOutlet.show({ title, url })
}
}
+7
View File
@@ -0,0 +1,7 @@
import { Controller } from '@hotwired/stimulus'
export default class extends Controller {
close() {
this.element.remove()
}
}
+10
View File
@@ -30,3 +30,13 @@
font-weight: 900; font-weight: 900;
src: url('../fonts/lato-v24-latin-900.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ src: url('../fonts/lato-v24-latin-900.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */
} }
.htmx-indicator{
@apply invisible;
}
.htmx-request .htmx-indicator{
@apply visible;
}
.htmx-request.htmx-indicator{
@apply visible;
}
+2 -1
View File
@@ -1,5 +1,6 @@
.btn { .btn {
@apply inline-flex justify-center rounded-lg text-sm uppercase font-semibold py-2.5 px-4 bg-primary text-white hover:bg-primary/80 shadow-md; @apply inline-flex space-x-1 justify-center rounded-lg text-sm uppercase font-semibold py-2.5 px-4;
@apply bg-primary text-white hover:bg-primary/80 shadow-md;
} }
.btn--small { .btn--small {
+6
View File
@@ -7,6 +7,7 @@
"name": "myep-team", "name": "myep-team",
"license": "UNLICENSED", "license": "UNLICENSED",
"dependencies": { "dependencies": {
"htmx.org": "^1.9.10",
"sortablejs": "^1.15.0" "sortablejs": "^1.15.0"
}, },
"devDependencies": { "devDependencies": {
@@ -5360,6 +5361,11 @@
"entities": "^2.0.0" "entities": "^2.0.0"
} }
}, },
"node_modules/htmx.org": {
"version": "1.9.10",
"resolved": "https://registry.npmjs.org/htmx.org/-/htmx.org-1.9.10.tgz",
"integrity": "sha512-UgchasltTCrTuU2DQLom3ohHrBvwr7OqpwyAVJ9VxtNBng4XKkVsqrv0Qr3srqvM9ZNI3f1MmvVQQqK7KW/bTA=="
},
"node_modules/http-deceiver": { "node_modules/http-deceiver": {
"version": "1.2.7", "version": "1.2.7",
"resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz",
+1
View File
@@ -36,6 +36,7 @@
"mjml": "mjml assets/mjml/layout.mjml -o templates/email/layout.html.twig" "mjml": "mjml assets/mjml/layout.mjml -o templates/email/layout.html.twig"
}, },
"dependencies": { "dependencies": {
"htmx.org": "^1.9.10",
"sortablejs": "^1.15.0" "sortablejs": "^1.15.0"
} }
} }
@@ -5,9 +5,11 @@ namespace App\Controller\Admin\Application;
use App\Entity\Application; use App\Entity\Application;
use App\Entity\Disposition; use App\Entity\Disposition;
use App\Event\DispositionCreatedEvent; use App\Event\DispositionCreatedEvent;
use App\Htmx\HxRedirectResponse;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Security\Http\Attribute\IsGranted; use Symfony\Component\Security\Http\Attribute\IsGranted;
@@ -25,8 +27,9 @@ class DisposeController extends AbstractController
#[Route('/admin/application/dispose/{uuid}', name: 'app_admin_application_dispose')] #[Route('/admin/application/dispose/{uuid}', name: 'app_admin_application_dispose')]
#[IsGranted('ROLE_ADMINISTRATIVE')] #[IsGranted('ROLE_ADMINISTRATIVE')]
#[IsGranted('DISPOSE', subject: 'application')] #[IsGranted('DISPOSE', subject: 'application')]
public function index(Application $application): Response public function index(Application $application, Request $request): Response
{ {
if (true === $request->isMethod('POST')) {
$disposition = new Disposition($application); $disposition = new Disposition($application);
$this->entityManager->persist($disposition); $this->entityManager->persist($disposition);
@@ -41,8 +44,15 @@ class DisposeController extends AbstractController
'teamer' => (string) $application->getTeamer(), 'teamer' => (string) $application->getTeamer(),
]); ]);
return $this->redirectToRoute('app_admin_assignment_detail', [ $redirectUrl = $this->generateUrl('app_admin_assignment_detail', [
'uuid' => $application->getAssignment()->getUuid(), 'uuid' => $application->getAssignment()->getUuid(),
]); ]);
return new HxRedirectResponse($redirectUrl);
}
return $this->render('admin/application/modal_dispose.html.twig', [
'application' => $application,
]);
} }
} }
@@ -3,21 +3,17 @@
namespace App\Controller\Admin\Application; namespace App\Controller\Admin\Application;
use App\Entity\Application; use App\Entity\Application;
use App\Model\AjaxModalResponseDto;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\Routing\Attribute\Route;
class InfoController extends AbstractController class InfoController extends AbstractController
{ {
#[Route('/admin/application/info/{uuid}', name: 'app_admin_application_info')] #[Route('/admin/application/info/{uuid}', name: 'app_admin_application_info')]
public function index(Application $application): JsonResponse public function index(Application $application): Response
{ {
$response = new AjaxModalResponseDto(); return $this->render('admin/application/modal_info.html.twig', [
$response->setContent($this->renderView('admin/application/info.html.twig', [
'application' => $application, 'application' => $application,
])); ]);
return $this->json($response);
} }
} }
@@ -5,13 +5,13 @@ namespace App\Controller\Admin\Application;
use App\Entity\Application; use App\Entity\Application;
use App\Event\ApplicationStatusEvent; use App\Event\ApplicationStatusEvent;
use App\Form\ApplicationStatusType; use App\Form\ApplicationStatusType;
use App\Model\AjaxModalResponseDto; use App\Htmx\HxRedirectResponse;
use App\Model\ApplicationStatusDto; use App\Model\ApplicationStatusDto;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Security\Http\Attribute\IsGranted; use Symfony\Component\Security\Http\Attribute\IsGranted;
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
@@ -28,12 +28,10 @@ class StatusController extends AbstractController
#[Route('/admin/application/status/{uuid}', name: 'app_admin_application_status')] #[Route('/admin/application/status/{uuid}', name: 'app_admin_application_status')]
#[IsGranted('ROLE_ADMINISTRATIVE')] #[IsGranted('ROLE_ADMINISTRATIVE')]
#[IsGranted('STATUS', subject: 'application')] #[IsGranted('STATUS', subject: 'application')]
public function index(Application $application, Request $request): JsonResponse public function index(Application $application, Request $request): Response
{ {
$response = new AjaxModalResponseDto();
$formAction = $this->generateUrl('app_admin_application_status', ['uuid' => $application->getUuid()]);
$statusDto = new ApplicationStatusDto($application); $statusDto = new ApplicationStatusDto($application);
$form = $this->createForm(ApplicationStatusType::class, $statusDto, ['action' => $formAction, 'ajax_submit' => true]); $form = $this->createForm(ApplicationStatusType::class, $statusDto);
$form->handleRequest($request); $form->handleRequest($request);
@@ -53,15 +51,13 @@ class StatusController extends AbstractController
'teamer' => (string) $application->getTeamer(), 'teamer' => (string) $application->getTeamer(),
]); ]);
$response->setCloseAndRedirect($this->generateUrl('app_admin_assignment_detail', [ return new HxRedirectResponse($this->generateUrl('app_admin_assignment_detail', [
'uuid' => $application->getAssignment()->getUuid(), 'uuid' => $application->getAssignment()->getUuid(),
])); ]));
} else {
$response->setContent($this->renderView('admin/application/status.html.twig', [
'form' => $form,
]));
} }
return $this->json($response); return $this->render('admin/application/modal_status.html.twig', [
'form' => $form->createView(),
]);
} }
} }
@@ -30,7 +30,13 @@ class CreateController extends AbstractController
$assignment = new Assignment(); $assignment = new Assignment();
$assignment->setOwner($user); $assignment->setOwner($user);
$form = $this->createForm(AssignmentType::class, $assignment); $form = $this->createForm(
AssignmentType::class,
$assignment,
[
'pickup_form_url' => $this->generateUrl('app_admin_assignment_pickup_form'),
]
);
$form->handleRequest($request); $form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) { if ($form->isSubmitted() && $form->isValid()) {
@@ -49,7 +55,7 @@ class CreateController extends AbstractController
} }
return $this->render('admin/assignment/create.html.twig', [ return $this->render('admin/assignment/create.html.twig', [
'form' => $form, 'form' => $form->createView(),
]); ]);
} }
} }
@@ -3,9 +3,11 @@
namespace App\Controller\Admin\Assignment; namespace App\Controller\Admin\Assignment;
use App\Entity\Assignment; use App\Entity\Assignment;
use App\Htmx\HxRedirectResponse;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Security\Http\Attribute\IsGranted; use Symfony\Component\Security\Http\Attribute\IsGranted;
@@ -20,8 +22,9 @@ class DeleteController extends AbstractController
#[Route('/admin/assignment/delete/{uuid}', name: 'app_admin_assignment_delete')] #[Route('/admin/assignment/delete/{uuid}', name: 'app_admin_assignment_delete')]
#[IsGranted('ROLE_ADMINISTRATIVE')] #[IsGranted('ROLE_ADMINISTRATIVE')]
public function index(Assignment $assignment): Response public function index(Assignment $assignment, Request $request): Response
{ {
if (true === $request->isMethod('POST')) {
$assignment->setDeleted(); $assignment->setDeleted();
$this->entityManager->flush(); $this->entityManager->flush();
@@ -33,6 +36,11 @@ class DeleteController extends AbstractController
$this->addFlash('success', 'Der Einsatz wurde gelöscht'); $this->addFlash('success', 'Der Einsatz wurde gelöscht');
return $this->redirectToRoute('app_admin_assignment_index'); return new HxRedirectResponse($this->generateUrl('app_admin_assignment_index'));
}
return $this->render('admin/assignment/modal_delete.html.twig', [
'assignment' => $assignment,
]);
} }
} }
@@ -26,7 +26,13 @@ class DuplicateController extends AbstractController
{ {
$copy = Assignment::duplicate($assignment); $copy = Assignment::duplicate($assignment);
$form = $this->createForm(AssignmentType::class, $copy); $form = $this->createForm(
AssignmentType::class,
$copy,
[
'pickup_form_url' => $this->generateUrl('app_admin_assignment_pickup_form'),
]
);
$form->handleRequest($request); $form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) { if ($form->isSubmitted() && $form->isValid()) {
@@ -48,7 +54,7 @@ class DuplicateController extends AbstractController
} }
return $this->render('admin/assignment/duplicate.html.twig', [ return $this->render('admin/assignment/duplicate.html.twig', [
'form' => $form, 'form' => $form->createView(),
]); ]);
} }
} }
@@ -24,7 +24,13 @@ class EditController extends AbstractController
#[IsGranted('EDIT', subject: 'assignment')] #[IsGranted('EDIT', subject: 'assignment')]
public function index(Assignment $assignment, Request $request): Response public function index(Assignment $assignment, Request $request): Response
{ {
$form = $this->createForm(AssignmentType::class, $assignment); $form = $this->createForm(
AssignmentType::class,
$assignment,
[
'pickup_form_url' => $this->generateUrl('app_admin_assignment_pickup_form'),
]
);
$form->handleRequest($request); $form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) { if ($form->isSubmitted() && $form->isValid()) {
@@ -42,7 +48,7 @@ class EditController extends AbstractController
} }
return $this->render('admin/assignment/edit.html.twig', [ return $this->render('admin/assignment/edit.html.twig', [
'form' => $form, 'form' => $form->createView(),
]); ]);
} }
} }
@@ -4,13 +4,13 @@ namespace App\Controller\Admin\Disposition;
use App\Entity\Disposition; use App\Entity\Disposition;
use App\Event\DispositionDeletedEvent; use App\Event\DispositionDeletedEvent;
use App\Model\AjaxModalResponseDto; use App\Htmx\HxRedirectResponse;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Form\Extension\Core\Type\TextareaType; use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Security\Http\Attribute\IsGranted; use Symfony\Component\Security\Http\Attribute\IsGranted;
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
@@ -27,12 +27,10 @@ class DeleteController extends AbstractController
#[Route('/admin/disposition/delete/{uuid}', name: 'app_admin_disposition_delete')] #[Route('/admin/disposition/delete/{uuid}', name: 'app_admin_disposition_delete')]
#[IsGranted('ROLE_ADMINISTRATIVE')] #[IsGranted('ROLE_ADMINISTRATIVE')]
#[IsGranted('DELETE', subject: 'disposition')] #[IsGranted('DELETE', subject: 'disposition')]
public function index(Disposition $disposition, Request $request): JsonResponse public function index(Disposition $disposition, Request $request): Response
{ {
$response = new AjaxModalResponseDto();
$formAction = $this->generateUrl('app_admin_disposition_delete', ['uuid' => $disposition->getUuid()]);
$form = $this $form = $this
->createFormBuilder($disposition, ['action' => $formAction, 'ajax_submit' => true]) ->createFormBuilder($disposition)
->add('remarks', TextareaType::class, [ ->add('remarks', TextareaType::class, [
'label' => 'Kommentar/Begründung', 'label' => 'Kommentar/Begründung',
'required' => false, 'required' => false,
@@ -56,15 +54,13 @@ class DeleteController extends AbstractController
$this->entityManager->remove($disposition); $this->entityManager->remove($disposition);
$this->entityManager->flush(); $this->entityManager->flush();
$response->setCloseAndRedirect($this->generateUrl('app_admin_assignment_detail', [ return new HxRedirectResponse($this->generateUrl('app_admin_assignment_detail', [
'uuid' => $disposition->getAssignment()->getUuid(), 'uuid' => $disposition->getAssignment()->getUuid(),
])); ]));
} else {
$response->setContent($this->renderView('admin/disposition/delete.html.twig', [
'form' => $form,
]));
} }
return $this->json($response); return $this->render('admin/disposition/modal_delete.html.twig', [
'form' => $form->createView(),
]);
} }
} }
@@ -5,14 +5,14 @@ namespace App\Controller\Admin\Document;
use App\Entity\Upload; use App\Entity\Upload;
use App\Event\DocumentRejectedEvent; use App\Event\DocumentRejectedEvent;
use App\Form\DocumentCheckType; use App\Form\DocumentCheckType;
use App\Model\AjaxModalResponseDto; use App\Htmx\HxRedirectResponse;
use App\Model\DocumentCheckDto; use App\Model\DocumentCheckDto;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\DependencyInjection\Attribute\Target; use Symfony\Component\DependencyInjection\Attribute\Target;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Security\Http\Attribute\IsGranted; use Symfony\Component\Security\Http\Attribute\IsGranted;
use Symfony\Component\Workflow\WorkflowInterface; use Symfony\Component\Workflow\WorkflowInterface;
@@ -32,20 +32,10 @@ class CheckController extends AbstractController
#[Route('/admin/document/check/{uuid}', name: 'app_admin_document_check')] #[Route('/admin/document/check/{uuid}', name: 'app_admin_document_check')]
#[IsGranted('ROLE_ADMINISTRATIVE')] #[IsGranted('ROLE_ADMINISTRATIVE')]
#[IsGranted('CHECK', subject: 'document')] #[IsGranted('CHECK', subject: 'document')]
public function index(Upload $document, Request $request): JsonResponse public function index(Upload $document, Request $request): Response
{ {
$response = new AjaxModalResponseDto();
$formData = new DocumentCheckDto($document); $formData = new DocumentCheckDto($document);
$formAction = $this->generateUrl('app_admin_document_check', ['uuid' => $document->getUuid()]); $form = $this->createForm(DocumentCheckType::class, $formData, ['document_type' => $document->getType()]);
$form = $this->createForm(
DocumentCheckType::class,
$formData,
[
'action' => $formAction,
'ajax_submit' => true,
'document_type' => $document->getType(),
]
);
$form->handleRequest($request); $form->handleRequest($request);
@@ -75,16 +65,13 @@ class CheckController extends AbstractController
]); ]);
} }
$returnUrl = $this->generateUrl('app_admin_document_index'); return new HxRedirectResponse($this->generateUrl('app_admin_document_index'));
$response->setCloseAndRedirect($returnUrl);
} else {
$response->setContent($this->renderView('admin/document/check.html.twig', [
'document' => $document,
'form' => $form,
]));
} }
return $this->json($response); return $this->render('admin/document/modal_check.html.twig', [
'document' => $document,
'form' => $form->createView(),
]);
} }
private function rejectDocument(Upload $document, string $comment = null): void private function rejectDocument(Upload $document, string $comment = null): void
@@ -3,9 +3,11 @@
namespace App\Controller\Admin\Document; namespace App\Controller\Admin\Document;
use App\Entity\Upload; use App\Entity\Upload;
use App\Htmx\HxRedirectResponse;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Security\Http\Attribute\IsGranted; use Symfony\Component\Security\Http\Attribute\IsGranted;
@@ -21,8 +23,9 @@ class DeleteController extends AbstractController
#[Route('/admin/document/delete/{uuid}', name: 'app_admin_document_delete')] #[Route('/admin/document/delete/{uuid}', name: 'app_admin_document_delete')]
#[IsGranted('ROLE_ADMINISTRATIVE')] #[IsGranted('ROLE_ADMINISTRATIVE')]
#[IsGranted('DELETE', subject: 'document')] #[IsGranted('DELETE', subject: 'document')]
public function index(Upload $document): Response public function index(Upload $document, Request $request): Response
{ {
if (true === $request->isMethod('POST')) {
$this->entityManager->remove($document); $this->entityManager->remove($document);
$this->entityManager->flush(); $this->entityManager->flush();
@@ -32,6 +35,11 @@ class DeleteController extends AbstractController
'owner' => $document->getOwner()->getFullName(), 'owner' => $document->getOwner()->getFullName(),
]); ]);
return $this->redirectToRoute('app_admin_document_index'); return new HxRedirectResponse($this->generateUrl('app_admin_document_index'));
}
return $this->render('admin/document/modal_delete.html.twig', [
'document' => $document,
]);
} }
} }
@@ -4,12 +4,12 @@ namespace App\Controller\Admin\Feedback;
use App\Entity\Feedback; use App\Entity\Feedback;
use App\Form\FeedbackApproveType; use App\Form\FeedbackApproveType;
use App\Model\AjaxModalResponseDto; use App\Htmx\HxRedirectResponse;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Security\Http\Attribute\IsGranted; use Symfony\Component\Security\Http\Attribute\IsGranted;
@@ -23,11 +23,9 @@ class ApproveController extends AbstractController
#[Route('/admin/feedback/approve/{uuid}', name: 'app_admin_feedback_approve')] #[Route('/admin/feedback/approve/{uuid}', name: 'app_admin_feedback_approve')]
#[IsGranted('ROLE_ADMIN')] #[IsGranted('ROLE_ADMIN')]
public function index(Feedback $feedback, Request $request): JsonResponse public function index(Feedback $feedback, Request $request): Response
{ {
$response = new AjaxModalResponseDto(); $form = $this->createForm(FeedbackApproveType::class, $feedback);
$action = $this->generateUrl('app_admin_feedback_approve', ['uuid' => $feedback->getUuid()]);
$form = $this->createForm(FeedbackApproveType::class, $feedback, ['action' => $action, 'ajax_submit' => true]);
$form->handleRequest($request); $form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) { if ($form->isSubmitted() && $form->isValid()) {
@@ -39,15 +37,12 @@ class ApproveController extends AbstractController
'feedback_uuid' => $feedback->getUuid(), 'feedback_uuid' => $feedback->getUuid(),
]); ]);
$returnUrl = $this->generateUrl('app_admin_index'); return new HxRedirectResponse($this->generateUrl('app_admin_index'));
$response->setCloseAndRedirect($returnUrl);
} else {
$response->setContent($this->renderView('admin/feedback/approve.html.twig', [
'feedback' => $feedback,
'form' => $form->createView(),
]));
} }
return $this->json($response); return $this->render('admin/feedback/modal_approve.html.twig', [
'feedback' => $feedback,
'form' => $form->createView(),
]);
} }
} }
@@ -4,12 +4,12 @@ namespace App\Controller\Admin\System\Availability;
use App\Entity\Availability; use App\Entity\Availability;
use App\Form\AvailabilityType; use App\Form\AvailabilityType;
use App\Model\AjaxModalResponseDto; use App\Htmx\HxRedirectResponse;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Security\Http\Attribute\IsGranted; use Symfony\Component\Security\Http\Attribute\IsGranted;
@@ -23,13 +23,10 @@ class CreateController extends AbstractController
#[Route('/admin/system/availability/create', name: 'app_admin_system_availability_create')] #[Route('/admin/system/availability/create', name: 'app_admin_system_availability_create')]
#[IsGranted('ROLE_ADMIN')] #[IsGranted('ROLE_ADMIN')]
public function index(Request $request): JsonResponse public function index(Request $request): Response
{ {
$response = new AjaxModalResponseDto();
$action = $this->generateUrl('app_admin_system_availability_create');
$availability = new Availability(); $availability = new Availability();
$form = $this->createForm(AvailabilityType::class, $availability, ['action' => $action, 'ajax_submit' => true]); $form = $this->createForm(AvailabilityType::class, $availability);
$form->handleRequest($request); $form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) { if ($form->isSubmitted() && $form->isValid()) {
@@ -42,15 +39,11 @@ class CreateController extends AbstractController
'availability_range' => (string) $availability, 'availability_range' => (string) $availability,
]); ]);
$redirectUrl = $this->generateUrl('app_admin_system_availability_index'); return new HxRedirectResponse($this->generateUrl('app_admin_system_availability_index'));
$response->setCloseAndRedirect($redirectUrl);
} else {
$content = $this->renderView('admin/system/availability/form.html.twig', [
'form' => $form,
]);
$response->setContent($content);
} }
return $this->json($response); return $this->render('admin/system/availability/modal_create.html.twig', [
'form' => $form->createView(),
]);
} }
} }
@@ -3,9 +3,11 @@
namespace App\Controller\Admin\System\Availability; namespace App\Controller\Admin\System\Availability;
use App\Entity\Availability; use App\Entity\Availability;
use App\Htmx\HxRedirectResponse;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Security\Http\Attribute\IsGranted; use Symfony\Component\Security\Http\Attribute\IsGranted;
@@ -20,8 +22,9 @@ class DeleteController extends AbstractController
#[Route('/admin/system/availability/delete/{id}', name: 'app_admin_system_availability_delete', methods: ['POST'])] #[Route('/admin/system/availability/delete/{id}', name: 'app_admin_system_availability_delete', methods: ['POST'])]
#[IsGranted('ROLE_ADMIN')] #[IsGranted('ROLE_ADMIN')]
public function index(Availability $availability): Response public function index(Availability $availability, Request $request): Response
{ {
if (true === $request->isMethod('POST')) {
$availability->setDeleted(); $availability->setDeleted();
$this->entityManager->flush(); $this->entityManager->flush();
@@ -31,6 +34,11 @@ class DeleteController extends AbstractController
'availability_range' => (string) $availability, 'availability_range' => (string) $availability,
]); ]);
return $this->redirectToRoute('app_admin_system_availability_index'); return new HxRedirectResponse($this->generateUrl('app_admin_system_availability_index'));
}
return $this->render('admin/system/availability/modal_delete.html.twig', [
'availability' => $availability,
]);
} }
} }
@@ -4,12 +4,12 @@ namespace App\Controller\Admin\System\Availability;
use App\Entity\Availability; use App\Entity\Availability;
use App\Form\AvailabilityType; use App\Form\AvailabilityType;
use App\Model\AjaxModalResponseDto; use App\Htmx\HxRedirectResponse;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Security\Http\Attribute\IsGranted; use Symfony\Component\Security\Http\Attribute\IsGranted;
@@ -23,14 +23,11 @@ class DuplicateController extends AbstractController
#[Route('/admin/system/availability/duplicate/{id}', name: 'app_admin_system_availability_duplicate')] #[Route('/admin/system/availability/duplicate/{id}', name: 'app_admin_system_availability_duplicate')]
#[IsGranted('ROLE_ADMIN')] #[IsGranted('ROLE_ADMIN')]
public function index(Availability $availability, Request $request): JsonResponse public function index(Availability $availability, Request $request): Response
{ {
$copy = Availability::duplicate($availability); $copy = Availability::duplicate($availability);
$response = new AjaxModalResponseDto(); $form = $this->createForm(AvailabilityType::class, $copy);
$action = $this->generateUrl('app_admin_system_availability_duplicate', ['id' => $availability->getId()]);
$form = $this->createForm(AvailabilityType::class, $copy, ['action' => $action, 'ajax_submit' => true]);
$form->handleRequest($request); $form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) { if ($form->isSubmitted() && $form->isValid()) {
@@ -45,15 +42,11 @@ class DuplicateController extends AbstractController
'duplicate_range' => (string) $copy, 'duplicate_range' => (string) $copy,
]); ]);
$redirectUrl = $this->generateUrl('app_admin_system_availability_index'); return new HxRedirectResponse($this->generateUrl('app_admin_system_availability_index'));
$response->setCloseAndRedirect($redirectUrl);
} else {
$content = $this->renderView('admin/system/availability/form.html.twig', [
'form' => $form,
]);
$response->setContent($content);
} }
return $this->json($response); return $this->render('admin/system/availability/modal_duplicate.html.twig', [
'form' => $form->createView(),
]);
} }
} }
@@ -4,12 +4,12 @@ namespace App\Controller\Admin\System\Availability;
use App\Entity\Availability; use App\Entity\Availability;
use App\Form\AvailabilityType; use App\Form\AvailabilityType;
use App\Model\AjaxModalResponseDto; use App\Htmx\HxRedirectResponse;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Security\Http\Attribute\IsGranted; use Symfony\Component\Security\Http\Attribute\IsGranted;
@@ -23,12 +23,9 @@ class EditController extends AbstractController
#[Route('/admin/system/availability/edit/{id}', name: 'app_admin_system_availability_edit')] #[Route('/admin/system/availability/edit/{id}', name: 'app_admin_system_availability_edit')]
#[IsGranted('ROLE_ADMIN')] #[IsGranted('ROLE_ADMIN')]
public function index(Availability $availability, Request $request): JsonResponse public function index(Availability $availability, Request $request): Response
{ {
$response = new AjaxModalResponseDto(); $form = $this->createForm(AvailabilityType::class, $availability);
$action = $this->generateUrl('app_admin_system_availability_edit', ['id' => $availability->getId()]);
$form = $this->createForm(AvailabilityType::class, $availability, ['action' => $action, 'ajax_submit' => true]);
$form->handleRequest($request); $form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) { if ($form->isSubmitted() && $form->isValid()) {
@@ -40,15 +37,11 @@ class EditController extends AbstractController
'availability_range' => (string) $availability, 'availability_range' => (string) $availability,
]); ]);
$redirectUrl = $this->generateUrl('app_admin_system_availability_index'); return new HxRedirectResponse($this->generateUrl('app_admin_system_availability_index'));
$response->setCloseAndRedirect($redirectUrl);
} else {
$content = $this->renderView('admin/system/availability/form.html.twig', [
'form' => $form
]);
$response->setContent($content);
} }
return $this->json($response); return $this->render('admin/system/availability/modal_edit.html.twig', [
'form' => $form->createView(),
]);
} }
} }
@@ -6,13 +6,13 @@ use App\Entity\Contact;
use App\Entity\Upload; use App\Entity\Upload;
use App\Entity\User; use App\Entity\User;
use App\Form\ContactType; use App\Form\ContactType;
use App\Model\AjaxModalResponseDto; use App\Htmx\HxRedirectResponse;
use App\Service\Upload\UploadHandler; use App\Service\Upload\UploadHandler;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Security\Http\Attribute\IsGranted; use Symfony\Component\Security\Http\Attribute\IsGranted;
@@ -27,11 +27,9 @@ class CreateController extends AbstractController
#[Route('/admin/system/contact/create', name: 'app_admin_system_contact_create')] #[Route('/admin/system/contact/create', name: 'app_admin_system_contact_create')]
#[IsGranted('ROLE_ADMINISTRATIVE')] #[IsGranted('ROLE_ADMINISTRATIVE')]
public function index(Request $request): JsonResponse public function index(Request $request): Response
{ {
$response = new AjaxModalResponseDto();
$contact = new Contact(); $contact = new Contact();
$formAction = $this->generateUrl('app_admin_system_contact_create');
// Handle upload independently from form submission to avoid issues with failing validation // Handle upload independently from form submission to avoid issues with failing validation
$uploadSession = $this->uploadHandler->getUploadSession(); $uploadSession = $this->uploadHandler->getUploadSession();
@@ -48,15 +46,7 @@ class CreateController extends AbstractController
$this->uploadHandler->destroyUploadSession(); $this->uploadHandler->destroyUploadSession();
} }
$form = $this->createForm( $form = $this->createForm(ContactType::class, $contact, ['upload_session' => $uploadSession]);
ContactType::class,
$contact,
[
'action' => $formAction,
'ajax_submit' => true,
'upload_session' => $uploadSession,
]
);
$form->handleRequest($request); $form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) { if ($form->isSubmitted() && $form->isValid()) {
@@ -68,13 +58,11 @@ class CreateController extends AbstractController
'contact_name' => $contact->getName(), 'contact_name' => $contact->getName(),
]); ]);
$response->setCloseAndRedirect($this->generateUrl('app_admin_system_contact_index')); return new HxRedirectResponse($this->generateUrl('app_admin_system_contact_index'));
} else {
$response->setContent($this->renderView('admin/system/contact/create.html.twig', [
'form' => $form,
]));
} }
return $this->json($response); return $this->render('admin/system/contact/modal_create.html.twig', [
'form' => $form->createView(),
]);
} }
} }
@@ -3,9 +3,11 @@
namespace App\Controller\Admin\System\Contact; namespace App\Controller\Admin\System\Contact;
use App\Entity\Contact; use App\Entity\Contact;
use App\Htmx\HxRedirectResponse;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Security\Http\Attribute\IsGranted; use Symfony\Component\Security\Http\Attribute\IsGranted;
@@ -20,8 +22,9 @@ class DeleteController extends AbstractController
#[Route('/admin/system/contact/delete/{id}', name: 'app_admin_system_contact_delete')] #[Route('/admin/system/contact/delete/{id}', name: 'app_admin_system_contact_delete')]
#[IsGranted('ROLE_ADMINISTRATIVE')] #[IsGranted('ROLE_ADMINISTRATIVE')]
public function index(Contact $contact): Response public function index(Contact $contact, Request $request): Response
{ {
if (true === $request->isMethod('POST')) {
$this->entityManager->remove($contact); $this->entityManager->remove($contact);
$this->entityManager->flush(); $this->entityManager->flush();
@@ -31,6 +34,11 @@ class DeleteController extends AbstractController
'contact_name' => $contact->getName(), 'contact_name' => $contact->getName(),
]); ]);
return $this->redirectToRoute('app_admin_system_contact_index'); return new HxRedirectResponse($this->generateUrl('app_admin_system_contact_index'));
}
return $this->render('admin/system/contact/modal_delete.html.twig', [
'contact' => $contact,
]);
} }
} }
@@ -6,13 +6,13 @@ use App\Entity\Contact;
use App\Entity\Upload; use App\Entity\Upload;
use App\Entity\User; use App\Entity\User;
use App\Form\ContactType; use App\Form\ContactType;
use App\Model\AjaxModalResponseDto; use App\Htmx\HxRedirectResponse;
use App\Service\Upload\UploadHandler; use App\Service\Upload\UploadHandler;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Security\Http\Attribute\IsGranted; use Symfony\Component\Security\Http\Attribute\IsGranted;
@@ -27,10 +27,8 @@ class EditController extends AbstractController
#[Route('/admin/system/contact/edit/{id}', name: 'app_admin_system_contact_edit')] #[Route('/admin/system/contact/edit/{id}', name: 'app_admin_system_contact_edit')]
#[IsGranted('ROLE_ADMINISTRATIVE')] #[IsGranted('ROLE_ADMINISTRATIVE')]
public function index(Contact $contact, Request $request): JsonResponse public function index(Contact $contact, Request $request): Response
{ {
$response = new AjaxModalResponseDto();
$formAction = $this->generateUrl('app_admin_system_contact_edit', ['id' => $contact->getId()]);
// Handle upload independently from form submission to avoid issues with failing validation // Handle upload independently from form submission to avoid issues with failing validation
$uploadSession = $this->uploadHandler->getUploadSession(); $uploadSession = $this->uploadHandler->getUploadSession();
if (true === $request->isMethod('POST') && 0 < $uploadSession->getCount()) { if (true === $request->isMethod('POST') && 0 < $uploadSession->getCount()) {
@@ -46,15 +44,7 @@ class EditController extends AbstractController
$this->uploadHandler->destroyUploadSession(); $this->uploadHandler->destroyUploadSession();
} }
$form = $this->createForm( $form = $this->createForm(ContactType::class, $contact, ['upload_session' => $uploadSession]);
ContactType::class,
$contact,
[
'action' => $formAction,
'ajax_submit' => true,
'upload_session' => $uploadSession,
]
);
$form->handleRequest($request); $form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) { if ($form->isSubmitted() && $form->isValid()) {
@@ -65,13 +55,11 @@ class EditController extends AbstractController
'contact_name' => $contact->getName(), 'contact_name' => $contact->getName(),
]); ]);
$response->setCloseAndRedirect($this->generateUrl('app_admin_system_contact_index')); return new HxRedirectResponse($this->generateUrl('app_admin_system_contact_index'));
} else {
$response->setContent($this->renderView('admin/system/contact/edit.html.twig', [
'form' => $form,
]));
} }
return $this->json($response); return $this->render('admin/system/contact/modal_edit.html.twig', [
'form' => $form->createView(),
]);
} }
} }
@@ -3,9 +3,11 @@
namespace App\Controller\Admin\System\Document; namespace App\Controller\Admin\System\Document;
use App\Entity\Upload; use App\Entity\Upload;
use App\Htmx\HxRedirectResponse;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Security\Http\Attribute\IsGranted; use Symfony\Component\Security\Http\Attribute\IsGranted;
@@ -21,8 +23,9 @@ class DeleteController extends AbstractController
#[Route('/admin/system/document/delete/{uuid}', name: 'app_admin_system_document_delete')] #[Route('/admin/system/document/delete/{uuid}', name: 'app_admin_system_document_delete')]
#[IsGranted('ROLE_ADMINISTRATIVE')] #[IsGranted('ROLE_ADMINISTRATIVE')]
#[IsGranted('DELETE', subject: 'document')] #[IsGranted('DELETE', subject: 'document')]
public function index(Upload $document): Response public function index(Upload $document, Request $request): Response
{ {
if (true === $request->isMethod('POST')) {
$this->entityManager->remove($document); $this->entityManager->remove($document);
$this->entityManager->flush(); $this->entityManager->flush();
@@ -32,6 +35,11 @@ class DeleteController extends AbstractController
'document_filename' => $document->getOriginalFilename(), 'document_filename' => $document->getOriginalFilename(),
]); ]);
return $this->redirectToRoute('app_admin_system_document_index'); return new HxRedirectResponse($this->generateUrl('app_admin_system_document_index'));
}
return $this->render('admin/system/document/modal_delete.html.twig', [
'document' => $document,
]);
} }
} }
@@ -3,14 +3,13 @@
namespace App\Controller\Admin\System\Document; namespace App\Controller\Admin\System\Document;
use App\Entity\Upload; use App\Entity\Upload;
use App\Model\AjaxModalResponseDto; use App\Htmx\HxRedirectResponse;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\TextType; use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Security\Http\Attribute\IsGranted; use Symfony\Component\Security\Http\Attribute\IsGranted;
@@ -24,15 +23,12 @@ class EditController extends AbstractController
#[Route('/admin/system/document/edit/{uuid}', name: 'app_admin_system_document_edit')] #[Route('/admin/system/document/edit/{uuid}', name: 'app_admin_system_document_edit')]
#[IsGranted('ROLE_ADMINISTRATIVE')] #[IsGranted('ROLE_ADMINISTRATIVE')]
public function index(Upload $upload, Request $request): JsonResponse public function index(Upload $upload, Request $request): Response
{ {
$response = new AjaxModalResponseDto();
$formAction = $this->generateUrl('app_admin_system_document_edit', ['uuid' => $upload->getUuid()]);
$nameBefore = $upload->getDisplayName(); $nameBefore = $upload->getDisplayName();
$form = $this $form = $this
->createFormBuilder($upload, ['action' => $formAction, 'ajax_submit' => true]) ->createFormBuilder($upload)
->add('displayName', TextType::class, [ ->add('displayName', TextType::class, [
'label' => 'angezeigter Name', 'label' => 'angezeigter Name',
'attr' => [ 'attr' => [
@@ -54,13 +50,11 @@ class EditController extends AbstractController
'document_name_after' => $upload->getDisplayName(), 'document_name_after' => $upload->getDisplayName(),
]); ]);
$response->setCloseAndRedirect($this->generateUrl('app_admin_system_document_index')); return new HxRedirectResponse($this->generateUrl('app_admin_system_document_index'));
} else {
$response->setContent($this->renderView('admin/system/document/edit.html.twig', [
'form' => $form->createView(),
]));
} }
return $this->json($response); return $this->render('admin/system/document/modal_edit.html.twig', [
'form' => $form->createView(),
]);
} }
} }
@@ -4,13 +4,13 @@ namespace App\Controller\Admin\System\Document;
use App\Entity\Upload; use App\Entity\Upload;
use App\Entity\User; use App\Entity\User;
use App\Model\AjaxModalResponseDto; use App\Htmx\HxRedirectResponse;
use App\Service\Upload\UploadHandler; use App\Service\Upload\UploadHandler;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Security\Http\Attribute\IsGranted; use Symfony\Component\Security\Http\Attribute\IsGranted;
@@ -25,7 +25,7 @@ class ReplaceController extends AbstractController
#[Route('/admin/system/document/replace/{uuid}', name: 'app_admin_system_document_replace')] #[Route('/admin/system/document/replace/{uuid}', name: 'app_admin_system_document_replace')]
#[IsGranted('ROLE_ADMINISTRATIVE')] #[IsGranted('ROLE_ADMINISTRATIVE')]
public function index(Upload $upload, Request $request): JsonResponse public function index(Upload $upload, Request $request): Response
{ {
// Handle upload independently from form submission to avoid issues with failing validation // Handle upload independently from form submission to avoid issues with failing validation
$uploadSession = $this->uploadHandler->getUploadSession(); $uploadSession = $this->uploadHandler->getUploadSession();
@@ -38,7 +38,6 @@ class ReplaceController extends AbstractController
$this->uploadHandler->destroyUploadSession(); $this->uploadHandler->destroyUploadSession();
} }
$response = new AjaxModalResponseDto();
$formAction = $this->generateUrl('app_admin_system_document_replace', ['uuid' => $upload->getUuid()]); $formAction = $this->generateUrl('app_admin_system_document_replace', ['uuid' => $upload->getUuid()]);
$filenameBefore = $upload->getOriginalFilename(); $filenameBefore = $upload->getOriginalFilename();
@@ -57,13 +56,11 @@ class ReplaceController extends AbstractController
'document_filename_after' => $upload->getOriginalFilename(), 'document_filename_after' => $upload->getOriginalFilename(),
]); ]);
$response->setCloseAndRedirect($this->generateUrl('app_admin_system_document_index')); return new HxRedirectResponse($this->generateUrl('app_admin_system_document_index'));
} else {
$response->setContent($this->renderView('admin/system/document/replace.html.twig', [
'form' => $form->createView(),
]));
} }
return $this->json($response); return $this->render('admin/system/document/modal_replace.html.twig', [
'form' => $form->createView(),
]);
} }
} }
@@ -4,13 +4,13 @@ namespace App\Controller\Admin\System\Document;
use App\Entity\Upload; use App\Entity\Upload;
use App\Entity\User; use App\Entity\User;
use App\Model\AjaxModalResponseDto; use App\Htmx\HxRedirectResponse;
use App\Service\Upload\UploadHandler; use App\Service\Upload\UploadHandler;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Security\Http\Attribute\IsGranted; use Symfony\Component\Security\Http\Attribute\IsGranted;
@@ -25,13 +25,10 @@ class UploadController extends AbstractController
#[Route('/admin/system/document/upload', name: 'app_admin_system_document_upload')] #[Route('/admin/system/document/upload', name: 'app_admin_system_document_upload')]
#[IsGranted('ROLE_ADMINISTRATIVE')] #[IsGranted('ROLE_ADMINISTRATIVE')]
public function index(Request $request): JsonResponse public function index(Request $request): Response
{ {
$response = new AjaxModalResponseDto();
$formAction = $this->generateUrl('app_admin_system_document_upload');
$form = $this $form = $this
->createFormBuilder(null, ['action' => $formAction, 'ajax_submit' => true]) ->createFormBuilder()
->getForm() ->getForm()
; ;
$form->handleRequest($request); $form->handleRequest($request);
@@ -53,7 +50,8 @@ class UploadController extends AbstractController
} }
if ($form->isSubmitted() && $form->isValid()) { if ($form->isSubmitted() && $form->isValid()) {
$this->addFlash('success', 'Das/die Dokument/e wurden hochgeladen'); $count = count($uploadedDocuments);
$this->addFlash('success', $count === 1 ? 'Das Dokument wurde hochgeladen' : 'Die Dokumente wurden hochgeladen');
$loggerContext = []; $loggerContext = [];
foreach ($uploadedDocuments as $document) { foreach ($uploadedDocuments as $document) {
$loggerContext[] = [ $loggerContext[] = [
@@ -63,13 +61,11 @@ class UploadController extends AbstractController
} }
$this->logger->info('Upload document(s)', $loggerContext); $this->logger->info('Upload document(s)', $loggerContext);
$response->setCloseAndRedirect($this->generateUrl('app_admin_system_document_index')); return new HxRedirectResponse($this->generateUrl('app_admin_system_document_index'));
} else {
$response->setContent($this->renderView('admin/system/document/upload.html.twig', [
'form' => $form->createView(),
]));
} }
return $this->json($response); return $this->render('admin/system/document/modal_upload.html.twig', [
'form' => $form->createView(),
]);
} }
} }
@@ -3,9 +3,11 @@
namespace App\Controller\Admin\System\Faq; namespace App\Controller\Admin\System\Faq;
use App\Entity\Faq; use App\Entity\Faq;
use App\Htmx\HxRedirectResponse;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Security\Http\Attribute\IsGranted; use Symfony\Component\Security\Http\Attribute\IsGranted;
@@ -18,10 +20,11 @@ class DeleteController extends AbstractController
) { ) {
} }
#[Route('/admin/system/faq/delete/{id}', name: 'app_admin_system_faq_delete', methods: ['POST'])] #[Route('/admin/system/faq/delete/{id}', name: 'app_admin_system_faq_delete')]
#[IsGranted('ROLE_ADMIN')] #[IsGranted('ROLE_ADMIN')]
public function index(Faq $faq): Response public function index(Faq $faq, Request $request): Response
{ {
if (true === $request->isMethod('POST')) {
$this->entityManager->remove($faq); $this->entityManager->remove($faq);
$this->entityManager->flush(); $this->entityManager->flush();
@@ -31,6 +34,11 @@ class DeleteController extends AbstractController
'faq_question' => $faq->getQuestion(), 'faq_question' => $faq->getQuestion(),
]); ]);
return $this->redirectToRoute('app_admin_system_faq_index'); return new HxRedirectResponse($this->generateUrl('app_admin_system_faq_index'));
}
return $this->render('admin/system/faq/modal_delete.html.twig', [
'faq' => $faq,
]);
} }
} }
@@ -4,12 +4,12 @@ namespace App\Controller\Admin\System\Fee;
use App\Entity\Fee; use App\Entity\Fee;
use App\Form\FeeType; use App\Form\FeeType;
use App\Model\AjaxModalResponseDto; use App\Htmx\HxRedirectResponse;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Security\Http\Attribute\IsGranted; use Symfony\Component\Security\Http\Attribute\IsGranted;
@@ -23,13 +23,10 @@ class CreateController extends AbstractController
#[Route('/admin/system/fee/create', name: 'app_admin_system_fee_create')] #[Route('/admin/system/fee/create', name: 'app_admin_system_fee_create')]
#[IsGranted('ROLE_ADMIN')] #[IsGranted('ROLE_ADMIN')]
public function index(Request $request): JsonResponse public function index(Request $request): Response
{ {
$response = new AjaxModalResponseDto();
$action = $this->generateUrl('app_admin_system_fee_create');
$fee = new Fee(); $fee = new Fee();
$form = $this->createForm(FeeType::class, $fee, ['action' => $action, 'ajax_submit' => true]); $form = $this->createForm(FeeType::class, $fee);
$form->handleRequest($request); $form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) { if ($form->isSubmitted() && $form->isValid()) {
@@ -42,15 +39,11 @@ class CreateController extends AbstractController
'fee_name' => $fee->getNameInternal() ?? $fee->getName(), 'fee_name' => $fee->getNameInternal() ?? $fee->getName(),
]); ]);
$redirectUrl = $this->generateUrl('app_admin_system_fee_index'); return new HxRedirectResponse($this->generateUrl('app_admin_system_fee_index'));
$response->setCloseAndRedirect($redirectUrl);
} else {
$content = $this->renderView('admin/system/fee/form.html.twig', [
'form' => $form
]);
$response->setContent($content);
} }
return $this->json($response); return $this->render('admin/system/fee/modal_create.html.twig', [
'form' => $form->createView(),
]);
} }
} }
@@ -3,9 +3,11 @@
namespace App\Controller\Admin\System\Fee; namespace App\Controller\Admin\System\Fee;
use App\Entity\Fee; use App\Entity\Fee;
use App\Htmx\HxRedirectResponse;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Security\Http\Attribute\IsGranted; use Symfony\Component\Security\Http\Attribute\IsGranted;
@@ -18,10 +20,11 @@ class DeleteController extends AbstractController
) { ) {
} }
#[Route('/admin/system/fee/delete/{id}', name: 'app_admin_system_fee_delete', methods: ['POST'])] #[Route('/admin/system/fee/delete/{id}', name: 'app_admin_system_fee_delete')]
#[IsGranted('ROLE_ADMIN')] #[IsGranted('ROLE_ADMIN')]
public function index(Fee $fee): Response public function index(Fee $fee, Request $request): Response
{ {
if (true === $request->isMethod('POST')) {
$fee->setDeleted(); $fee->setDeleted();
$this->entityManager->flush(); $this->entityManager->flush();
@@ -31,6 +34,11 @@ class DeleteController extends AbstractController
'fee_name' => $fee->getNameInternal() ?? $fee->getName(), 'fee_name' => $fee->getNameInternal() ?? $fee->getName(),
]); ]);
return $this->redirectToRoute('app_admin_system_fee_index'); return new HxRedirectResponse($this->generateUrl('app_admin_system_fee_index'));
}
return $this->render('admin/system/fee/modal_delete.html.twig', [
'fee' => $fee,
]);
} }
} }
@@ -4,12 +4,12 @@ namespace App\Controller\Admin\System\Fee;
use App\Entity\Fee; use App\Entity\Fee;
use App\Form\FeeType; use App\Form\FeeType;
use App\Model\AjaxModalResponseDto; use App\Htmx\HxRedirectResponse;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Security\Http\Attribute\IsGranted; use Symfony\Component\Security\Http\Attribute\IsGranted;
@@ -23,14 +23,10 @@ class DuplicateController extends AbstractController
#[Route('/admin/system/fee/duplicate/{id}', name: 'app_admin_system_fee_duplicate')] #[Route('/admin/system/fee/duplicate/{id}', name: 'app_admin_system_fee_duplicate')]
#[IsGranted('ROLE_ADMIN')] #[IsGranted('ROLE_ADMIN')]
public function index(Fee $fee, Request $request): JsonResponse public function index(Fee $fee, Request $request): Response
{ {
$copy = Fee::duplicate($fee); $copy = Fee::duplicate($fee);
$form = $this->createForm(FeeType::class, $copy);
$response = new AjaxModalResponseDto();
$action = $this->generateUrl('app_admin_system_fee_duplicate', ['id' => $fee->getId()]);
$form = $this->createForm(FeeType::class, $copy, ['action' => $action, 'ajax_submit' => true]);
$form->handleRequest($request); $form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) { if ($form->isSubmitted() && $form->isValid()) {
@@ -45,15 +41,11 @@ class DuplicateController extends AbstractController
'duplicate_name' => $copy->getNameInternal() ?? $copy->getName(), 'duplicate_name' => $copy->getNameInternal() ?? $copy->getName(),
]); ]);
$redirectUrl = $this->generateUrl('app_admin_system_fee_index'); return new HxRedirectResponse($this->generateUrl('app_admin_system_fee_index'));
$response->setCloseAndRedirect($redirectUrl);
} else {
$content = $this->renderView('admin/system/fee/form.html.twig', [
'form' => $form
]);
$response->setContent($content);
} }
return $this->json($response); return $this->render('admin/system/fee/modal_duplicate.html.twig', [
'form' => $form->createView(),
]);
} }
} }
@@ -4,12 +4,12 @@ namespace App\Controller\Admin\System\Fee;
use App\Entity\Fee; use App\Entity\Fee;
use App\Form\FeeType; use App\Form\FeeType;
use App\Model\AjaxModalResponseDto; use App\Htmx\HxRedirectResponse;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Security\Http\Attribute\IsGranted; use Symfony\Component\Security\Http\Attribute\IsGranted;
@@ -23,12 +23,9 @@ class EditController extends AbstractController
#[Route('/admin/system/fee/edit/{id}', name: 'app_admin_system_fee_edit')] #[Route('/admin/system/fee/edit/{id}', name: 'app_admin_system_fee_edit')]
#[IsGranted('ROLE_ADMIN')] #[IsGranted('ROLE_ADMIN')]
public function index(Fee $fee, Request $request): JsonResponse public function index(Fee $fee, Request $request): Response
{ {
$response = new AjaxModalResponseDto(); $form = $this->createForm(FeeType::class, $fee);
$action = $this->generateUrl('app_admin_system_fee_edit', ['id' => $fee->getId()]);
$form = $this->createForm(FeeType::class, $fee, ['action' => $action, 'ajax_submit' => true]);
$form->handleRequest($request); $form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) { if ($form->isSubmitted() && $form->isValid()) {
@@ -40,15 +37,11 @@ class EditController extends AbstractController
'fee_name' => $fee->getNameInternal() ?? $fee->getName(), 'fee_name' => $fee->getNameInternal() ?? $fee->getName(),
]); ]);
$redirectUrl = $this->generateUrl('app_admin_system_fee_index'); return new HxRedirectResponse($this->generateUrl('app_admin_system_fee_index'));
$response->setCloseAndRedirect($redirectUrl);
} else {
$content = $this->renderView('admin/system/fee/form.html.twig', [
'form' => $form
]);
$response->setContent($content);
} }
return $this->json($response); return $this->render('admin/system/fee/modal_edit.html.twig', [
'form' => $form->createView(),
]);
} }
} }
@@ -3,9 +3,11 @@
namespace App\Controller\Admin\System\FeedbackSet; namespace App\Controller\Admin\System\FeedbackSet;
use App\Entity\FeedbackSet; use App\Entity\FeedbackSet;
use App\Htmx\HxRedirectResponse;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Security\Http\Attribute\IsGranted; use Symfony\Component\Security\Http\Attribute\IsGranted;
@@ -18,11 +20,12 @@ class DeleteController extends AbstractController
) { ) {
} }
#[Route('/admin/system/feedback-set/delete/{id}', name: 'app_admin_system_feedback_set_delete', methods: ['POST'])] #[Route('/admin/system/feedback-set/delete/{id}', name: 'app_admin_system_feedback_set_delete')]
#[IsGranted('ROLE_ADMIN')] #[IsGranted('ROLE_ADMIN')]
#[IsGranted('DELETE', subject: 'feedbackSet')] #[IsGranted('DELETE', subject: 'feedbackSet')]
public function index(FeedbackSet $feedbackSet): Response public function index(FeedbackSet $feedbackSet, Request $request): Response
{ {
if (true === $request->isMethod('POST')) {
$this->entityManager->remove($feedbackSet); $this->entityManager->remove($feedbackSet);
$this->entityManager->flush(); $this->entityManager->flush();
@@ -32,6 +35,11 @@ class DeleteController extends AbstractController
'feedback_set_name' => $feedbackSet->getName(), 'feedback_set_name' => $feedbackSet->getName(),
]); ]);
return $this->redirectToRoute('app_admin_system_feedback_set_index'); return new HxRedirectResponse($this->generateUrl('app_admin_system_feedback_set_index'));
}
return $this->render('admin/system/feedback_set/modal_delete.html.twig', [
'feedbackSet' => $feedbackSet,
]);
} }
} }
@@ -3,9 +3,11 @@
namespace App\Controller\Admin\System\JobProfile; namespace App\Controller\Admin\System\JobProfile;
use App\Entity\JobProfile; use App\Entity\JobProfile;
use App\Htmx\HxRedirectResponse;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Security\Http\Attribute\IsGranted; use Symfony\Component\Security\Http\Attribute\IsGranted;
@@ -18,10 +20,11 @@ class DeleteController extends AbstractController
) { ) {
} }
#[Route('/admin/system/job-profile/delete/{id}', name: 'app_admin_system_job_profile_delete', methods: ['POST'])] #[Route('/admin/system/job-profile/delete/{id}', name: 'app_admin_system_job_profile_delete')]
#[IsGranted('ROLE_ADMIN')] #[IsGranted('ROLE_ADMIN')]
public function index(JobProfile $jobProfile): Response public function index(JobProfile $jobProfile, Request $request): Response
{ {
if (true === $request->isMethod('POST')) {
$jobProfile->setDeleted(); $jobProfile->setDeleted();
$this->entityManager->flush(); $this->entityManager->flush();
@@ -31,6 +34,11 @@ class DeleteController extends AbstractController
'job_profile_name' => $jobProfile->getName(), 'job_profile_name' => $jobProfile->getName(),
]); ]);
return $this->redirectToRoute('app_admin_system_job_profile_index'); return new HxRedirectResponse($this->generateUrl('app_admin_system_job_profile_index'));
}
return $this->render('admin/system/job_profile/modal_delete.html.twig', [
'jobProfile' => $jobProfile,
]);
} }
} }
@@ -4,12 +4,12 @@ namespace App\Controller\Admin\System\Training;
use App\Entity\Training; use App\Entity\Training;
use App\Form\TrainingType; use App\Form\TrainingType;
use App\Model\AjaxModalResponseDto; use App\Htmx\HxRedirectResponse;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Security\Http\Attribute\IsGranted; use Symfony\Component\Security\Http\Attribute\IsGranted;
@@ -23,13 +23,10 @@ class CreateController extends AbstractController
#[Route('/admin/system/training/create', name: 'app_admin_system_training_create')] #[Route('/admin/system/training/create', name: 'app_admin_system_training_create')]
#[IsGranted('ROLE_ADMIN')] #[IsGranted('ROLE_ADMIN')]
public function index(Request $request): JsonResponse public function index(Request $request): Response
{ {
$response = new AjaxModalResponseDto();
$action = $this->generateUrl('app_admin_system_training_create');
$training = new Training(); $training = new Training();
$form = $this->createForm(TrainingType::class, $training, ['action' => $action, 'ajax_submit' => true]); $form = $this->createForm(TrainingType::class, $training);
$form->handleRequest($request); $form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) { if ($form->isSubmitted() && $form->isValid()) {
@@ -42,15 +39,11 @@ class CreateController extends AbstractController
'training_name' => $training->getName(), 'training_name' => $training->getName(),
]); ]);
$redirectUrl = $this->generateUrl('app_admin_system_training_index'); return new HxRedirectResponse($this->generateUrl('app_admin_system_training_index'));
$response->setCloseAndRedirect($redirectUrl);
} else {
$content = $this->renderView('admin/system/training/form.html.twig', [
'form' => $form
]);
$response->setContent($content);
} }
return $this->json($response); return $this->render('admin/system/training/modal_create.hml.twig', [
'form' => $form->createView(),
]);
} }
} }
@@ -3,9 +3,11 @@
namespace App\Controller\Admin\System\Training; namespace App\Controller\Admin\System\Training;
use App\Entity\Training; use App\Entity\Training;
use App\Htmx\HxRedirectResponse;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Security\Http\Attribute\IsGranted; use Symfony\Component\Security\Http\Attribute\IsGranted;
@@ -18,10 +20,11 @@ class DeleteController extends AbstractController
) { ) {
} }
#[Route('/admin/system/training/delete/{id}', name: 'app_admin_system_training_delete', methods: ['POST'])] #[Route('/admin/system/training/delete/{id}', name: 'app_admin_system_training_delete')]
#[IsGranted('ROLE_ADMIN')] #[IsGranted('ROLE_ADMIN')]
public function index(Training $training): Response public function index(Training $training, Request $request): Response
{ {
if (true === $request->isMethod('POST')) {
$training->setDeleted(); $training->setDeleted();
$this->entityManager->flush(); $this->entityManager->flush();
@@ -31,6 +34,11 @@ class DeleteController extends AbstractController
'training_name' => $training->getName(), 'training_name' => $training->getName(),
]); ]);
return $this->redirectToRoute('app_admin_system_training_index'); return new HxRedirectResponse($this->generateUrl('app_admin_system_training_index'));
}
return $this->render('admin/system/training/modal_delete.html.twig', [
'training' => $training,
]);
} }
} }
@@ -4,12 +4,12 @@ namespace App\Controller\Admin\System\Training;
use App\Entity\Training; use App\Entity\Training;
use App\Form\TrainingType; use App\Form\TrainingType;
use App\Model\AjaxModalResponseDto; use App\Htmx\HxRedirectResponse;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Security\Http\Attribute\IsGranted; use Symfony\Component\Security\Http\Attribute\IsGranted;
@@ -23,12 +23,9 @@ class EditController extends AbstractController
#[Route('/admin/system/training/edit/{id}', name: 'app_admin_system_training_edit')] #[Route('/admin/system/training/edit/{id}', name: 'app_admin_system_training_edit')]
#[IsGranted('ROLE_ADMIN')] #[IsGranted('ROLE_ADMIN')]
public function index(Training $training, Request $request): JsonResponse public function index(Training $training, Request $request): Response
{ {
$response = new AjaxModalResponseDto(); $form = $this->createForm(TrainingType::class, $training);
$action = $this->generateUrl('app_admin_system_training_edit', ['id' => $training->getId()]);
$form = $this->createForm(TrainingType::class, $training, ['action' => $action, 'ajax_submit' => true]);
$form->handleRequest($request); $form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) { if ($form->isSubmitted() && $form->isValid()) {
@@ -40,15 +37,11 @@ class EditController extends AbstractController
'training_name' => $training->getName(), 'training_name' => $training->getName(),
]); ]);
$redirectUrl = $this->generateUrl('app_admin_system_training_index'); return new HxRedirectResponse($this->generateUrl('app_admin_system_training_index'));
$response->setCloseAndRedirect($redirectUrl);
} else {
$content = $this->renderView('admin/system/training/form.html.twig', [
'form' => $form
]);
$response->setContent($content);
} }
return $this->json($response); return $this->render('admin/system/training/modal_edit.hml.twig', [
'form' => $form->createView(),
]);
} }
} }
@@ -5,6 +5,7 @@ namespace App\Controller\Admin\Teamer\Availability;
use App\Controller\Traits\ReturnUrlTrait; use App\Controller\Traits\ReturnUrlTrait;
use App\Entity\Availability; use App\Entity\Availability;
use App\Entity\Teamer; use App\Entity\Teamer;
use App\Htmx\HxRedirectResponse;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
use Symfony\Bridge\Doctrine\Attribute\MapEntity; use Symfony\Bridge\Doctrine\Attribute\MapEntity;
@@ -33,6 +34,7 @@ class DeleteController extends AbstractController
Availability $availability, Availability $availability,
Request $request Request $request
): Response { ): Response {
if (true === $request->isMethod('POST')) {
if (null === $availability->getOwner()) { if (null === $availability->getOwner()) {
$teamer->removeAvailability($availability); $teamer->removeAvailability($availability);
} elseif ($teamer === $availability->getOwner()) { } elseif ($teamer === $availability->getOwner()) {
@@ -51,6 +53,11 @@ class DeleteController extends AbstractController
$redirectUrl = $this->getReturnUrl($request, 'app_admin_teamer_profile', ['uuid' => $teamer->getUuid()]); $redirectUrl = $this->getReturnUrl($request, 'app_admin_teamer_profile', ['uuid' => $teamer->getUuid()]);
return $this->redirect($redirectUrl); return new HxRedirectResponse($redirectUrl);
}
return $this->render('admin/teamer/availability/modal_delete.html.twig', [
'availability' => $availability,
]);
} }
} }
@@ -1,6 +1,6 @@
<?php <?php
namespace App\Controller\Admin\Teamer; namespace App\Controller\Admin\Teamer\Availability;
use App\Entity\Teamer; use App\Entity\Teamer;
use App\Service\Teamer\AvailabilityProcessor; use App\Service\Teamer\AvailabilityProcessor;
@@ -9,7 +9,7 @@ use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Security\Http\Attribute\IsGranted; use Symfony\Component\Security\Http\Attribute\IsGranted;
class AvailabilityController extends AbstractController class IndexController extends AbstractController
{ {
#[Route('/admin/teamer/availability/{uuid}', name: 'app_admin_teamer_availability')] #[Route('/admin/teamer/availability/{uuid}', name: 'app_admin_teamer_availability')]
#[IsGranted('ROLE_ADMINISTRATIVE')] #[IsGranted('ROLE_ADMINISTRATIVE')]
@@ -19,7 +19,7 @@ class AvailabilityController extends AbstractController
$availabilities = $teamer->getAvailabilities()->toArray(); $availabilities = $teamer->getAvailabilities()->toArray();
$groupedAvailabilities = $processor->groupRecords($availabilities); $groupedAvailabilities = $processor->groupRecords($availabilities);
return $this->render('admin/teamer/availability.html.twig', [ return $this->render('admin/teamer/availability/index.html.twig', [
'teamer' => $teamer, 'teamer' => $teamer,
'groupedAvailabilities' => $groupedAvailabilities, 'groupedAvailabilities' => $groupedAvailabilities,
]); ]);
@@ -3,10 +3,9 @@
namespace App\Controller\Admin\Teamer; namespace App\Controller\Admin\Teamer;
use App\Entity\Teamer; use App\Entity\Teamer;
use App\Model\AjaxModalResponseDto;
use App\Repository\DispositionRepository; use App\Repository\DispositionRepository;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\Routing\Attribute\Route;
class InfoController extends AbstractController class InfoController extends AbstractController
@@ -15,16 +14,13 @@ class InfoController extends AbstractController
{} {}
#[Route('/admin/teamer/info/{uuid}', name: 'app_admin_teamer_info')] #[Route('/admin/teamer/info/{uuid}', name: 'app_admin_teamer_info')]
public function index(Teamer $teamer): JsonResponse public function index(Teamer $teamer): Response
{ {
$recentDispositions = $this->dispositionRepository->findRecentDispositionsByTeamer($teamer); $recentDispositions = $this->dispositionRepository->findRecentDispositionsByTeamer($teamer);
$response = new AjaxModalResponseDto(); return $this->render('admin/teamer/modal_info.html.twig', [
$response->setContent($this->renderView('admin/teamer/info.html.twig', [
'teamer' => $teamer, 'teamer' => $teamer,
'recentDispositions' => $recentDispositions, 'recentDispositions' => $recentDispositions,
])); ]);
return $this->json($response);
} }
} }
@@ -6,14 +6,13 @@ use App\Entity\Teamer;
use App\Entity\Training; use App\Entity\Training;
use App\Entity\TrainingAttendance; use App\Entity\TrainingAttendance;
use App\Form\AbbreviatedDateType; use App\Form\AbbreviatedDateType;
use App\Form\FeeType; use App\Htmx\HxRedirectResponse;
use App\Model\AjaxModalResponseDto;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
use Symfony\Bridge\Doctrine\Attribute\MapEntity; use Symfony\Bridge\Doctrine\Attribute\MapEntity;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Security\Http\Attribute\IsGranted; use Symfony\Component\Security\Http\Attribute\IsGranted;
@@ -33,13 +32,7 @@ class CreateController extends AbstractController
#[MapEntity(mapping: ['teamer_id' => 'id'])] #[MapEntity(mapping: ['teamer_id' => 'id'])]
Teamer $teamer, Teamer $teamer,
Request $request Request $request
): JsonResponse { ): Response {
$response = new AjaxModalResponseDto();
$action = $this->generateUrl('app_admin_teamer_skills_training_attendance_create', [
'training_id' => $training->getId(),
'teamer_id' => $teamer->getId(),
]);
$attendance = new TrainingAttendance(); $attendance = new TrainingAttendance();
$attendance $attendance
->setTeamer($teamer) ->setTeamer($teamer)
@@ -47,7 +40,7 @@ class CreateController extends AbstractController
; ;
$form = $this $form = $this
->createFormBuilder($attendance, ['action' => $action, 'ajax_submit' => true]) ->createFormBuilder($attendance)
->add('date', AbbreviatedDateType::class, [ ->add('date', AbbreviatedDateType::class, [
'label' => 'Datum', 'label' => 'Datum',
]) ])
@@ -69,14 +62,12 @@ class CreateController extends AbstractController
]); ]);
$redirectUrl = $this->generateUrl('app_admin_teamer_skills', ['uuid' => $teamer->getUuid()]); $redirectUrl = $this->generateUrl('app_admin_teamer_skills', ['uuid' => $teamer->getUuid()]);
$response->setCloseAndRedirect($redirectUrl);
} else { return new HxRedirectResponse($redirectUrl);
$content = $this->renderView('admin/teamer/training_attendance/create.html.twig', [
'form' => $form
]);
$response->setContent($content);
} }
return $this->json($response); return $this->render('admin/teamer/training_attendance/modal_create.html.twig', [
'form' => $form->createView(),
]);
} }
} }
@@ -3,9 +3,11 @@
namespace App\Controller\Admin\Teamer\TrainingAttendance; namespace App\Controller\Admin\Teamer\TrainingAttendance;
use App\Entity\TrainingAttendance; use App\Entity\TrainingAttendance;
use App\Htmx\HxRedirectResponse;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Security\Http\Attribute\IsGranted; use Symfony\Component\Security\Http\Attribute\IsGranted;
@@ -18,10 +20,11 @@ class DeleteController extends AbstractController
) { ) {
} }
#[Route('/admin/teamer/skills/training-attendance/delete/{uuid}', name: 'app_admin_teamer_skills_training_attendance_delete', methods: ['POST'])] #[Route('/admin/teamer/skills/training-attendance/delete/{uuid}', name: 'app_admin_teamer_skills_training_attendance_delete')]
#[IsGranted('ROLE_ADMIN')] #[IsGranted('ROLE_ADMIN')]
public function index(TrainingAttendance $attendance): Response public function index(TrainingAttendance $attendance, Request $request): Response
{ {
if (true === $request->isMethod('POST')) {
$teamer = $attendance->getTeamer(); $teamer = $attendance->getTeamer();
$this->entityManager->remove($attendance); $this->entityManager->remove($attendance);
@@ -36,6 +39,13 @@ class DeleteController extends AbstractController
'training_name' => $attendance->getTraining()->getName(), 'training_name' => $attendance->getTraining()->getName(),
]); ]);
return $this->redirectToRoute('app_admin_teamer_skills', ['uuid' => $teamer->getUuid()]); return new HxRedirectResponse($this->generateUrl('app_admin_teamer_skills', [
'uuid' => $teamer->getUuid(),
]));
}
return $this->render('admin/teamer/training_attendance/modal_delete.html.twig', [
'attendance' => $attendance,
]);
} }
} }
@@ -4,11 +4,10 @@ namespace App\Controller\Common;
use App\Controller\Traits\ReturnUrlTrait; use App\Controller\Traits\ReturnUrlTrait;
use App\Form\AssignmentFilterType; use App\Form\AssignmentFilterType;
use App\Model\AjaxModalResponseDto; use App\Htmx\HxRedirectResponse;
use App\Repository\AssignmentRepository; use App\Repository\AssignmentRepository;
use App\Service\Common\AssignmentFilterHandler; use App\Service\Common\AssignmentFilterHandler;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\Routing\Attribute\Route;
@@ -26,15 +25,11 @@ class AssignmentFilterController extends AbstractController
#[Route('/common/assignment/filter', name: 'app_common_assignment_filter')] #[Route('/common/assignment/filter', name: 'app_common_assignment_filter')]
#[IsGranted('ROLE_USER')] #[IsGranted('ROLE_USER')]
public function index(Request $request): JsonResponse public function index(Request $request): Response
{ {
$response = new AjaxModalResponseDto();
$formAction = $this->generateUrl('app_common_assignment_filter', ['r' => $request->query->get('r')]);
$formData = $this->filterHandler->getFilterSettings(); $formData = $this->filterHandler->getFilterSettings();
$filterOptions = $this->assignmentRepository->getFilterOptions(); $filterOptions = $this->assignmentRepository->getFilterOptions();
$formOptions = [ $formOptions = [
'action' => $formAction,
'ajax_submit' => true,
'min_date' => $filterOptions['minDate'], 'min_date' => $filterOptions['minDate'],
'max_date' => $filterOptions['maxDate'], 'max_date' => $filterOptions['maxDate'],
'job_profiles' => $filterOptions['jobProfiles'], 'job_profiles' => $filterOptions['jobProfiles'],
@@ -47,15 +42,14 @@ class AssignmentFilterController extends AbstractController
if ($form->isSubmitted() && $form->isValid()) { if ($form->isSubmitted() && $form->isValid()) {
$this->filterHandler->handleRequest($form); $this->filterHandler->handleRequest($form);
$returnUrl = $this->getReturnUrl($request, 'app_admin_assignment_index'); $returnUrl = $this->getReturnUrl($request, 'app_admin_assignment_index');
$response->setCloseAndRedirect($returnUrl);
} else { return new HxRedirectResponse($returnUrl);
$response->setContent($this->renderView('common/assignment_filter.html.twig', [
'filterForm' => $form,
'filterDto' => $form->getData(),
]));
} }
return $this->json($response); return $this->render('common/modal_assignment_filter.html.twig', [
'filterForm' => $form->createView(),
'filterDto' => $form->getData(),
]);
} }
#[Route('/common/assignment/filter/reset', name: 'app_common_assignment_filter_reset')] #[Route('/common/assignment/filter/reset', name: 'app_common_assignment_filter_reset')]
@@ -4,11 +4,10 @@ namespace App\Controller\Common;
use App\Controller\Traits\ReturnUrlTrait; use App\Controller\Traits\ReturnUrlTrait;
use App\Form\TeamerFilterType; use App\Form\TeamerFilterType;
use App\Model\AjaxModalResponseDto; use App\Htmx\HxRedirectResponse;
use App\Repository\TeamerRepository; use App\Repository\TeamerRepository;
use App\Service\Common\TeamerFilterHandler; use App\Service\Common\TeamerFilterHandler;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\Routing\Attribute\Route;
@@ -26,29 +25,23 @@ class TeamerFilterController extends AbstractController
#[Route('/common/teamer/filter', name: 'app_common_teamer_filter')] #[Route('/common/teamer/filter', name: 'app_common_teamer_filter')]
#[IsGranted('ROLE_USER')] #[IsGranted('ROLE_USER')]
public function index(Request $request): JsonResponse public function index(Request $request): Response
{ {
$response = new AjaxModalResponseDto();
$formAction = $this->generateUrl('app_common_teamer_filter', ['r' => $request->query->get('r')]);
$formData = $this->filterHandler->getFilterSettings(); $formData = $this->filterHandler->getFilterSettings();
$form = $this->createForm(TeamerFilterType::class, $formData, [ $form = $this->createForm(TeamerFilterType::class, $formData);
'action' => $formAction,
'ajax_submit' => true,
]);
$form->handleRequest($request); $form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) { if ($form->isSubmitted() && $form->isValid()) {
$this->filterHandler->handleRequest($form); $this->filterHandler->handleRequest($form);
$returnUrl = $this->getReturnUrl($request, 'app_admin_teamer_index'); $returnUrl = $this->getReturnUrl($request, 'app_admin_teamer_index');
$response->setCloseAndRedirect($returnUrl);
} else { return new HxRedirectResponse($returnUrl);
$response->setContent($this->renderView('common/teamer_filter.html.twig', [
'filterForm' => $form,
'filterDto' => $form->getData(),
]));
} }
return $this->json($response); return $this->render('common/modal_teamer_filter.html.twig', [
'filterForm' => $form->createView(),
'filterDto' => $form->getData(),
]);
} }
#[Route('/common/teamer/filter/reset', name: 'app_common_teamer_filter_reset')] #[Route('/common/teamer/filter/reset', name: 'app_common_teamer_filter_reset')]
@@ -5,6 +5,7 @@ namespace App\Controller\Teamer\Application;
use App\Controller\Traits\ReturnUrlTrait; use App\Controller\Traits\ReturnUrlTrait;
use App\Entity\Application; use App\Entity\Application;
use App\Entity\User; use App\Entity\User;
use App\Htmx\HxRedirectResponse;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
@@ -27,6 +28,7 @@ class WithdrawController extends AbstractController
#[IsGranted('WITHDRAW', subject: 'application')] #[IsGranted('WITHDRAW', subject: 'application')]
public function index(Application $application, Request $request): Response public function index(Application $application, Request $request): Response
{ {
if (true === $request->isMethod('POST')) {
/** @var User $user */ /** @var User $user */
$user = $this->getUser(); $user = $this->getUser();
$teamer = $user->getTeamer(); $teamer = $user->getTeamer();
@@ -43,8 +45,11 @@ class WithdrawController extends AbstractController
'destination' => (string) $assignment->getDestination(), 'destination' => (string) $assignment->getDestination(),
]); ]);
$returnUrl = $this->getReturnUrl($request, 'app_teamer_index'); return new HxRedirectResponse($this->getReturnUrl($request, 'app_teamer_index'));
}
return $this->redirect($returnUrl); return $this->render('teamer/application/modal_withdraw.html.twig', [
'application' => $application,
]);
} }
} }
+4 -8
View File
@@ -3,9 +3,8 @@
namespace App\Controller\Teamer; namespace App\Controller\Teamer;
use App\Entity\Feedback; use App\Entity\Feedback;
use App\Model\AjaxModalResponseDto;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Security\Http\Attribute\IsGranted; use Symfony\Component\Security\Http\Attribute\IsGranted;
@@ -13,13 +12,10 @@ class FeedbackController extends AbstractController
{ {
#[Route('/teamer/feedback/{uuid}', name: 'app_teamer_feedback')] #[Route('/teamer/feedback/{uuid}', name: 'app_teamer_feedback')]
#[IsGranted('VIEW', subject: 'feedback')] #[IsGranted('VIEW', subject: 'feedback')]
public function index(Feedback $feedback): JsonResponse public function index(Feedback $feedback): Response
{ {
$response = new AjaxModalResponseDto(); return $this->render('teamer/feedback/modal.html.twig', [
$response->setContent($this->renderView('teamer/feedback/index.html.twig', [
'feedback' => $feedback, 'feedback' => $feedback,
])); ]);
return $this->json($response);
} }
} }
@@ -5,12 +5,12 @@ namespace App\Controller\Teamer\Profile\Availability;
use App\Entity\Availability; use App\Entity\Availability;
use App\Entity\User; use App\Entity\User;
use App\Form\AvailabilityType; use App\Form\AvailabilityType;
use App\Model\AjaxModalResponseDto; use App\Htmx\HxRedirectResponse;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Security\Http\Attribute\IsGranted; use Symfony\Component\Security\Http\Attribute\IsGranted;
@@ -24,14 +24,11 @@ class CreateController extends AbstractController
#[Route('/teamer/profile/availability/create', name: 'app_teamer_profile_availability_create')] #[Route('/teamer/profile/availability/create', name: 'app_teamer_profile_availability_create')]
#[IsGranted('ROLE_TEAMER')] #[IsGranted('ROLE_TEAMER')]
public function index(Request $request): JsonResponse public function index(Request $request): Response
{ {
$response = new AjaxModalResponseDto();
$action = $this->generateUrl('app_teamer_profile_availability_create');
$availability = new Availability(); $availability = new Availability();
$form = $this->createForm(AvailabilityType::class, $availability, ['action' => $action, 'ajax_submit' => true]); $form = $this->createForm(AvailabilityType::class, $availability);
$form->handleRequest($request); $form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) { if ($form->isSubmitted() && $form->isValid()) {
@@ -53,15 +50,11 @@ class CreateController extends AbstractController
'availability' => (string) $availability, 'availability' => (string) $availability,
]); ]);
$redirectUrl = $this->generateUrl('app_teamer_profile_availability_index'); return new HxRedirectResponse($this->generateUrl('app_teamer_profile_availability_index'));
$response->setCloseAndRedirect($redirectUrl);
} else {
$content = $this->renderView('teamer/profile/availability/create.html.twig', [
'form' => $form,
]);
$response->setContent($content);
} }
return $this->json($response); return $this->render('teamer/profile/availability/modal_create.html.twig', [
'form' => $form->createView(),
]);
} }
} }
@@ -4,9 +4,11 @@ namespace App\Controller\Teamer\Profile\Availability;
use App\Entity\Availability; use App\Entity\Availability;
use App\Entity\User; use App\Entity\User;
use App\Htmx\HxRedirectResponse;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Security\Http\Attribute\IsGranted; use Symfony\Component\Security\Http\Attribute\IsGranted;
@@ -21,8 +23,9 @@ class DeleteController extends AbstractController
#[Route('/teamer/profile/availability/delete/{id}', name: 'app_teamer_profile_availability_delete')] #[Route('/teamer/profile/availability/delete/{id}', name: 'app_teamer_profile_availability_delete')]
#[IsGranted('DELETE', subject: 'availability')] #[IsGranted('DELETE', subject: 'availability')]
public function index(Availability $availability): Response public function index(Availability $availability, Request $request): Response
{ {
if (true === $request->isMethod('POST')) {
/** @var User $user */ /** @var User $user */
$user = $this->getUser(); $user = $this->getUser();
$teamer = $user->getTeamer(); $teamer = $user->getTeamer();
@@ -42,6 +45,11 @@ class DeleteController extends AbstractController
'availability' => (string) $availability, 'availability' => (string) $availability,
]); ]);
return $this->redirectToRoute('app_teamer_profile_availability_index'); return new HxRedirectResponse($this->generateUrl('app_teamer_profile_availability_index'));
}
return $this->render('teamer/profile/availability/modal_delete.html.twig', [
'availability' => $availability,
]);
} }
} }
@@ -6,14 +6,14 @@ use App\Entity\License;
use App\Entity\Upload; use App\Entity\Upload;
use App\Entity\User; use App\Entity\User;
use App\Form\LicenseType; use App\Form\LicenseType;
use App\Model\AjaxModalResponseDto; use App\Htmx\HxRedirectResponse;
use App\Model\UploadSessionDto; use App\Model\UploadSessionDto;
use App\Service\Upload\UploadHandler; use App\Service\Upload\UploadHandler;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Security\Http\Attribute\IsGranted; use Symfony\Component\Security\Http\Attribute\IsGranted;
@@ -28,11 +28,8 @@ class AddController extends AbstractController
#[Route('/teamer/profile/license/add', name: 'app_teamer_profile_license_add')] #[Route('/teamer/profile/license/add', name: 'app_teamer_profile_license_add')]
#[IsGranted('ROLE_TEAMER')] #[IsGranted('ROLE_TEAMER')]
public function index(Request $request): JsonResponse public function index(Request $request): Response
{ {
$response = new AjaxModalResponseDto();
$action = $this->generateUrl('app_teamer_profile_license_add');
/** @var User $user */ /** @var User $user */
$user = $this->getUser(); $user = $this->getUser();
$license = new License(); $license = new License();
@@ -43,15 +40,7 @@ class AddController extends AbstractController
$this->updateCertificate($user, $license, $uploadSession); $this->updateCertificate($user, $license, $uploadSession);
} }
$form = $this->createForm( $form = $this->createForm(LicenseType::class, $license, ['upload_session' => $uploadSession]);
LicenseType::class,
$license,
[
'action' => $action,
'ajax_submit' => true,
'upload_session' => $uploadSession,
]
);
$form->handleRequest($request); $form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) { if ($form->isSubmitted() && $form->isValid()) {
@@ -69,16 +58,12 @@ class AddController extends AbstractController
'license_type' => $license->getType(), 'license_type' => $license->getType(),
]); ]);
$redirectUrl = $this->generateUrl('app_teamer_profile_skills'); return new HxRedirectResponse($this->generateUrl('app_teamer_profile_skills'));
$response->setCloseAndRedirect($redirectUrl);
} else {
$content = $this->renderView('teamer/profile/license/add.html.twig', [
'form' => $form,
]);
$response->setContent($content);
} }
return $this->json($response); return $this->render('teamer/profile/license/modal_add.html.twig', [
'form' => $form->createView(),
]);
} }
private function updateCertificate(User $user, License $license, UploadSessionDto $uploadSession): void private function updateCertificate(User $user, License $license, UploadSessionDto $uploadSession): void
@@ -3,9 +3,11 @@
namespace App\Controller\Teamer\Profile\License; namespace App\Controller\Teamer\Profile\License;
use App\Entity\License; use App\Entity\License;
use App\Htmx\HxRedirectResponse;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Security\Http\Attribute\IsGranted; use Symfony\Component\Security\Http\Attribute\IsGranted;
@@ -20,8 +22,9 @@ class DeleteController extends AbstractController
#[Route('//teamer/profile/license/delete/{uuid}', name: 'app_teamer_profile_license_delete')] #[Route('//teamer/profile/license/delete/{uuid}', name: 'app_teamer_profile_license_delete')]
#[IsGranted('DELETE', subject: 'license')] #[IsGranted('DELETE', subject: 'license')]
public function index(License $license): Response public function index(License $license, Request $request): Response
{ {
if (true === $request->isMethod('POST')) {
$teamer = $license->getTeamer(); $teamer = $license->getTeamer();
$this->entityManager->remove($license); $this->entityManager->remove($license);
@@ -34,6 +37,11 @@ class DeleteController extends AbstractController
'license_type' => $license->getType(), 'license_type' => $license->getType(),
]); ]);
return $this->redirectToRoute('app_teamer_profile_skills'); return new HxRedirectResponse($this->generateUrl('app_teamer_profile_skills'));
}
return $this->render('teamer/profile/license/modal_delete.html.twig', [
'license' => $license,
]);
} }
} }
+7 -1
View File
@@ -54,7 +54,12 @@ class AssignmentType extends AbstractType
'label_property' => 'product', 'label_property' => 'product',
'label_function' => fn(Destination $destination) => (string) $destination, 'label_function' => fn(Destination $destination) => (string) $destination,
'endpoint_route' => 'app_admin_autocomplete_destination', 'endpoint_route' => 'app_admin_autocomplete_destination',
'controller_action' => 'select->form-partial#update', 'attr' => [
'hx-post' => $options['pickup_form_url'],
'hx-trigger' => 'select',
'hx-target' => '#pickup-form',
'hx-swap' => 'innerHTML',
],
]) ])
->add('jobProfile', EntityType::class, [ ->add('jobProfile', EntityType::class, [
'label' => 'Jobprofil', 'label' => 'Jobprofil',
@@ -189,6 +194,7 @@ class AssignmentType extends AbstractType
public function configureOptions(OptionsResolver $resolver): void public function configureOptions(OptionsResolver $resolver): void
{ {
$resolver->setDefaults([ $resolver->setDefaults([
'pickup_form_url' => null,
'data_class' => Assignment::class, 'data_class' => Assignment::class,
'anti_xss' => true, 'anti_xss' => true,
]); ]);
@@ -1,32 +0,0 @@
<?php
namespace App\Form\Extension;
use Symfony\Component\Form\AbstractTypeExtension;
use Symfony\Component\Form\Extension\Core\Type\FormType;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormView;
use Symfony\Component\OptionsResolver\OptionsResolver;
class AjaxSubmitExtension extends AbstractTypeExtension
{
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'ajax_submit' => false,
'ajax_action' => 'ajax-modal#submitForm',
]);
}
public function buildView(FormView $view, FormInterface $form, array $options): void
{
if (true === $options['ajax_submit']) {
$view->vars['attr'] = array_merge($view->vars['attr'], ['data-action' => $options['ajax_action']]);
}
}
public static function getExtendedTypes(): iterable
{
return [FormType::class];
}
}
+13
View File
@@ -0,0 +1,13 @@
<?php
namespace App\Htmx;
use Symfony\Component\HttpFoundation\Response;
class HxRedirectResponse extends Response
{
public function __construct(string $url)
{
return parent::__construct(null, Response::HTTP_OK, ['HX-Redirect' => $url]);
}
}
-53
View File
@@ -1,53 +0,0 @@
<?php
namespace App\Model;
class AjaxModalResponseDto
{
private string $content;
private string $redirect;
private bool $close = false;
public function getContent(): ?string
{
return $this->content;
}
public function setContent(string $content): self
{
$this->content = $content;
return $this;
}
public function getRedirect(): ?string
{
return $this->redirect;
}
public function setRedirect(string $redirect): self
{
$this->redirect = $redirect;
$this->close = false;
return $this;
}
public function setCloseAndRedirect(string $redirect): self
{
$this->redirect = $redirect;
$this->close = true;
return $this;
}
public function isClose(): bool
{
return $this->close;
}
public function setClose(bool $close): void
{
$this->close = $close;
}
}
+7 -2
View File
@@ -4,6 +4,7 @@ namespace App\Security\Voter;
use App\Entity\Application; use App\Entity\Application;
use App\Entity\User; use App\Entity\User;
use Symfony\Bundle\SecurityBundle\Security;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\Voter\Voter; use Symfony\Component\Security\Core\Authorization\Voter\Voter;
@@ -15,6 +16,10 @@ class ApplicationVoter extends Voter
public const DISPOSE = 'DISPOSE'; public const DISPOSE = 'DISPOSE';
public const STATUS = 'STATUS'; public const STATUS = 'STATUS';
public function __construct(private readonly Security $security)
{
}
protected function supports(string $attribute, mixed $subject): bool protected function supports(string $attribute, mixed $subject): bool
{ {
if (!$subject instanceof Application) { if (!$subject instanceof Application) {
@@ -36,7 +41,7 @@ class ApplicationVoter extends Voter
$adminAttributes = [static::VIEW, static::DELETE, static::DISPOSE, static::STATUS]; $adminAttributes = [static::VIEW, static::DELETE, static::DISPOSE, static::STATUS];
$teamerAttributes = [static::VIEW, static::WITHDRAW, static::DELETE, static::STATUS]; $teamerAttributes = [static::VIEW, static::WITHDRAW, static::DELETE, static::STATUS];
if ($user->hasRole('ROLE_ADMINISTRATIVE') && in_array($attribute, $adminAttributes)) { if ($this->security->isGranted('ROLE_ADMINISTRATIVE') && in_array($attribute, $adminAttributes)) {
$assignment = $application->getAssignment(); $assignment = $application->getAssignment();
return match ($attribute) { return match ($attribute) {
static::VIEW, static::STATUS => Application::STATUS_REJECTED !== $status, static::VIEW, static::STATUS => Application::STATUS_REJECTED !== $status,
@@ -47,7 +52,7 @@ class ApplicationVoter extends Voter
}; };
} }
if ($user->hasRole('ROLE_TEAMER') && in_array($attribute, $teamerAttributes)) { if ($this->security->isGranted('ROLE_TEAMER') && in_array($attribute, $teamerAttributes)) {
$teamer = $user->getTeamer(); $teamer = $user->getTeamer();
return match ($attribute) { return match ($attribute) {
static::WITHDRAW => $teamer === $application->getTeamer(), static::WITHDRAW => $teamer === $application->getTeamer(),
+8 -4
View File
@@ -7,6 +7,7 @@ use App\Entity\Assignment;
use App\Entity\Disposition; use App\Entity\Disposition;
use App\Entity\User; use App\Entity\User;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\SecurityBundle\Security;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\Voter\Voter; use Symfony\Component\Security\Core\Authorization\Voter\Voter;
@@ -16,8 +17,11 @@ class AssignmentVoter extends Voter
public const EDIT = 'EDIT'; public const EDIT = 'EDIT';
public const APPLY = 'APPLY'; public const APPLY = 'APPLY';
public function __construct(private readonly EntityManagerInterface $entityManager) public function __construct(
{} private readonly Security $security,
private readonly EntityManagerInterface $entityManager
) {
}
protected function supports(string $attribute, mixed $subject): bool protected function supports(string $attribute, mixed $subject): bool
{ {
@@ -40,7 +44,7 @@ class AssignmentVoter extends Voter
// Only users with administrative role may edit assignments // Only users with administrative role may edit assignments
if (static::EDIT === $attribute) { if (static::EDIT === $attribute) {
return in_array('ROLE_ADMINISTRATIVE', $token->getRoleNames()); return $this->security->isGranted('ROLE_ADMINISTRATIVE');
} }
// Only allow applications to open assignments // Only allow applications to open assignments
@@ -61,7 +65,7 @@ class AssignmentVoter extends Voter
} }
// Only teamers without existing applications may apply to the assignment // Only teamers without existing applications may apply to the assignment
if (in_array('ROLE_TEAMER', $token->getRoleNames())) { if ($this->security->isGranted('ROLE_TEAMER')) {
/** @var User $user */ /** @var User $user */
$user = $token->getUser(); $user = $token->getUser();
$teamer = $user->getTeamer(); $teamer = $user->getTeamer();
+8 -5
View File
@@ -5,6 +5,7 @@ namespace App\Security\Voter;
use App\BusProNet\DataProvider\HotelDataProvider; use App\BusProNet\DataProvider\HotelDataProvider;
use App\BusProNet\Model\Hotel; use App\BusProNet\Model\Hotel;
use App\Entity\Disposition; use App\Entity\Disposition;
use Symfony\Bundle\SecurityBundle\Security;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\Voter\Voter; use Symfony\Component\Security\Core\Authorization\Voter\Voter;
@@ -17,8 +18,10 @@ class DispositionVoter extends Voter
public const INVOICE = 'INVOICE'; public const INVOICE = 'INVOICE';
public const FEEDBACK = 'FEEDBACK'; public const FEEDBACK = 'FEEDBACK';
public function __construct(private readonly HotelDataProvider $hotelDataProvider) public function __construct(
{ private readonly Security $security,
private readonly HotelDataProvider $hotelDataProvider
) {
} }
protected function supports(string $attribute, mixed $subject): bool protected function supports(string $attribute, mixed $subject): bool
@@ -52,12 +55,12 @@ class DispositionVoter extends Voter
private function assertAdministrativeAccess(TokenInterface $token): bool private function assertAdministrativeAccess(TokenInterface $token): bool
{ {
return in_array('ROLE_ADMINISTRATIVE', $token->getRoleNames()); return $this->security->isGranted('ROLE_ADMINISTRATIVE');
} }
private function assertHouseManagerAccess(TokenInterface $token, Disposition $disposition): bool private function assertHouseManagerAccess(TokenInterface $token, Disposition $disposition): bool
{ {
if (false === in_array('ROLE_HOUSE_MANAGER', $token->getRoleNames())) { if (false === $this->security->isGranted('ROLE_HOUSE_MANAGER')) {
return false; return false;
} }
@@ -79,7 +82,7 @@ class DispositionVoter extends Voter
private function assertTeamerAccess(TokenInterface $token, Disposition $disposition): bool private function assertTeamerAccess(TokenInterface $token, Disposition $disposition): bool
{ {
if (false === in_array('ROLE_TEAMER', $token->getRoleNames())) { if (false === $this->security->isGranted('ROLE_TEAMER')) {
return false; return false;
} }
+6 -1
View File
@@ -4,6 +4,7 @@ namespace App\Security\Voter;
use App\Entity\Upload; use App\Entity\Upload;
use App\Entity\User; use App\Entity\User;
use Symfony\Bundle\SecurityBundle\Security;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\Voter\Voter; use Symfony\Component\Security\Core\Authorization\Voter\Voter;
@@ -14,6 +15,10 @@ class UploadVoter extends Voter
public const DOWNLOAD = 'DOWNLOAD'; public const DOWNLOAD = 'DOWNLOAD';
public const CHECK = 'CHECK'; public const CHECK = 'CHECK';
public function __construct(private readonly Security $security)
{
}
protected function supports(string $attribute, mixed $subject): bool protected function supports(string $attribute, mixed $subject): bool
{ {
if (! $subject instanceof Upload) { if (! $subject instanceof Upload) {
@@ -29,7 +34,7 @@ class UploadVoter extends Voter
$upload = $subject; $upload = $subject;
// Administrative users have full access // Administrative users have full access
if (true === in_array('ROLE_ADMINISTRATIVE', $token->getRoleNames())) { if (true === $this->security->isGranted('ROLE_ADMINISTRATIVE')) {
// Only new documents may be checked // Only new documents may be checked
if (static::CHECK === $attribute) { if (static::CHECK === $attribute) {
return in_array($upload->getStatus(), [Upload::STATUS_NEW, Upload::STATUS_PENDING]); return in_array($upload->getStatus(), [Upload::STATUS_NEW, Upload::STATUS_PENDING]);
-22
View File
@@ -1,22 +0,0 @@
<div id="ajax-modal"
class="fixed inset-0 w-full h-full z-50 hidden"
{{ stimulus_controller('ajax-modal') }}
>
<div class="absolute inset-0 w-full h-full bg-black/80" {{ stimulus_action('ajax-modal', 'hide', 'click') }}></div>
<div class="absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 px-4 w-full max-w-2xl">
<div class="bg-white p-8 rounded-md">
<div class="flex justify-between pb-4">
<div class="text-2xl font-bold" {{ stimulus_target('ajax-modal', 'title') }}></div>
<button type="button"
class="inline-block"
{{ stimulus_action('ajax-modal', 'hide') }}>
{{ icon('close', 'w-6 h-6')}}
</button>
</div>
<div class="hidden" {{ stimulus_target('ajax-modal', 'content') }}></div>
<div {{ stimulus_target('ajax-modal', 'spinner') }}>
{% include '_partials/_spinner.html.twig' with { 'class': 'w-8 h-8 mx-auto'} %}
</div>
</div>
</div>
</div>
@@ -1,28 +0,0 @@
<div id="confirmation-modal"
class="fixed top-0 left-0 z-50 inset-0 hidden"
{{ stimulus_controller('confirmation-modal') }}
>
<div class="absolute top-0 left-0 inset-0 bg-black/80" {{ stimulus_action('confirmation-modal', 'hide', 'click') }}></div>
<div class="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 bg-white p-8 w-full max-w-3xl rounded-md">
<div class="flex justify-between border-b border-gray-200 pb-2 mb-4">
<div class="flex items-center space-x-2">
{{ icon('alert', 'w-8 h-8') }}
<span class="text-xl font-bold" {{ stimulus_target('confirmation-modal', 'title') }}></span>
</div>
<button class="inline-block" {{ stimulus_action('confirmation-modal', 'hide') }}>
{{ icon('close', 'w-8 h-8') }}
</button>
</div>
<form method="post" {{ stimulus_target('confirmation-modal', 'form') }}>
<div {{ stimulus_target('confirmation-modal', 'content') }}></div>
<div class="mt-6 flex items-center justify-between">
<button type="submit" class="btn bg-red-500">
Ja
</button>
<button type="button" class="btn" {{ stimulus_action('confirmation-modal', 'hide') }}>
Abbrechen
</button>
</div>
</form>
</div>
</div>
+4 -6
View File
@@ -56,7 +56,7 @@
</a> </a>
</td> </td>
<td> <td>
{% if assignment.pickup %} {% if assignment.pickup and assignment.destination.pickup(assignment.pickup) %}
{% set pickup = assignment.destination.pickup(assignment.pickup) %} {% set pickup = assignment.destination.pickup(assignment.pickup) %}
<a href="{{ path('app_admin_assignment_detail', { 'uuid': assignment.uuid, 'r': return_url() }) }}"> <a href="{{ path('app_admin_assignment_detail', { 'uuid': assignment.uuid, 'r': return_url() }) }}">
<span class="whitespace-nowrap">ab {{ pickup.city }}</span> <span class="whitespace-nowrap">ab {{ pickup.city }}</span>
@@ -77,11 +77,9 @@
role="button" role="button"
title="Bewerber:innen-Info anzeigen" title="Bewerber:innen-Info anzeigen"
aria-label="Bewerber:innen-Info anzeigen" aria-label="Bewerber:innen-Info anzeigen"
{{ stimulus_controller('modal-button', [], [], {'ajax-modal': '#ajax-modal'}) }} hx-get="{{ path('app_admin_teamer_info', { 'uuid': application.teamer.uuid }) }}"
{{ stimulus_action('modal-button', 'ajax', 'click', { hx-target="body"
'title': 'Teamer:innen-Info ' ~ application.teamer, hx-swap="beforeend">
'url': path('app_admin_teamer_info', { 'uuid': application.teamer.uuid })
}) }}>
{% set requirementsMet = true %} {% set requirementsMet = true %}
{% if assignment.pickup and not application.matchesPickup %} {% if assignment.pickup and not application.matchesPickup %}
{{ icon('bus', 'w-5 h-5 text-red-500 shrink-0') }} {{ icon('bus', 'w-5 h-5 text-red-500 shrink-0') }}
@@ -1,44 +0,0 @@
<div class="flex items-start">
<div class="flex-1 pr-8">
{% include '_partials/_assignment_requirements_info.html.twig' with {
'assignment': application.assignment,
'teamer': application.teamer
} %}
<ul class="pb-8 divide-y divide-gray-200">
{% for type in ['ski', 'snowboard'] %}
<li class="py-2">
<div class="flex items-center justify-between">
<span class="flex-1">{{ type|license_label }}</span>
{% set license = application.teamer.licenseOfType(type) %}
{% if license %}
<div class="flex items-center space-x-2">
<span>{{ license.date|date('m/Y') }}</span>
{% if is_granted('DOWNLOAD', license.certificate) %}
<a href="{{ path('app_common_download', { 'uuid': license.certificate.uuid, 'inline': true }) }}"
target="_blank"
title="Download Nachweis">
{{ icon('download', 'w-4 h-4') }}
</a>
{% endif %}
</div>
{% else %}
{{ icon('minus', 'w-4 h-4') }}
{% endif %}
</div>
</li>
{% endfor %}
</ul>
</div>
<div>
{% set teamer = application.teamer %}
{% if teamer.photo %}
<img src="{{ asset(teamer.photo.filename | imagine_filter('profile')) }}"
class="w-32 h-auto border-2 border-primary"
alt="{{ teamer.firstName }}">
{% else %}
<div class="border-2 border-primary">
{{ icon('user', 'w-32 h-32 text-gray-200') }}
</div>
{% endif %}
</div>
</div>
@@ -0,0 +1,7 @@
{% extends 'htmx_confirmation_modal.html.twig' %}
{% block content %}
<div>
Möchtest du die Bewerbung von {{ application.teamer }} wirklich löschen?
</div>
{% endblock %}
@@ -0,0 +1,7 @@
{% extends 'htmx_confirmation_modal.html.twig' %}
{% block content %}
<div>
Möchtest du {{ application.teamer }} wirklich einteilen?
</div>
{% endblock %}
@@ -0,0 +1,50 @@
{% extends 'htmx_modal.html.twig' %}
{% block title %}Teamer:inneninfo {{ application.teamer }}{% endblock %}
{% block content %}
<div class="flex items-start">
<div class="flex-1 pr-8">
{% include '_partials/_assignment_requirements_info.html.twig' with {
'assignment': application.assignment,
'teamer': application.teamer
} %}
<ul class="pb-8 divide-y divide-gray-200">
{% for type in ['ski', 'snowboard'] %}
<li class="py-2">
<div class="flex items-center justify-between">
<span class="flex-1">{{ type|license_label }}</span>
{% set license = application.teamer.licenseOfType(type) %}
{% if license %}
<div class="flex items-center space-x-2">
<span>{{ license.date|date('m/Y') }}</span>
{% if is_granted('DOWNLOAD', license.certificate) %}
<a href="{{ path('app_common_download', { 'uuid': license.certificate.uuid, 'inline': true }) }}"
target="_blank"
title="Download Nachweis">
{{ icon('download', 'w-4 h-4') }}
</a>
{% endif %}
</div>
{% else %}
{{ icon('minus', 'w-4 h-4') }}
{% endif %}
</div>
</li>
{% endfor %}
</ul>
</div>
<div>
{% set teamer = application.teamer %}
{% if teamer.photo %}
<img src="{{ asset(teamer.photo.filename | imagine_filter('profile')) }}"
class="w-32 h-auto border-2 border-primary"
alt="{{ teamer.firstName }}">
{% else %}
<div class="border-2 border-primary">
{{ icon('user', 'w-32 h-32 text-gray-200') }}
</div>
{% endif %}
</div>
</div>
{% endblock %}
@@ -0,0 +1,17 @@
{% extends 'htmx_modal.html.twig' %}
{% block title %}Bewerbungsstatus bearbeiten{% endblock %}
{% block content %}
{{ form_start(form, { 'attr': { 'hx-post': app.request.uri, 'hx-target': '#htmx-modal', 'hx-swap': 'outerHTML' } }) }}
<div class="flex flex-col space-y-4 pb-4">
{{ form_row(form.status) }}
{{ form_row(form.comment) }}
{{ form_row(form.commentVisible) }}
</div>
<button type="submit" class="btn">
Aktualisieren
</button>
{{ form_rest(form) }}
{{ form_end(form) }}
{% endblock %}
@@ -1,11 +0,0 @@
{{ form_start(form) }}
<div class="flex flex-col space-y-4 pb-4">
{{ form_row(form.status) }}
{{ form_row(form.comment) }}
{{ form_row(form.commentVisible) }}
</div>
<button type="submit" class="btn">
Aktualisieren
</button>
{{ form_rest(form) }}
{{ form_end(form) }}
+2 -8
View File
@@ -10,8 +10,7 @@
</div> </div>
{% endmacro %} {% endmacro %}
<div {{ stimulus_controller('form-partial', { 'url': path('app_admin_assignment_pickup_form') }) }}> {{ form_start(form) }}
{{ form_start(form, { 'attr': { 'data-form-partial-target': 'form' } }) }}
<div class="flex flex-col space-y-4 pb-8"> <div class="flex flex-col space-y-4 pb-8">
<div class="grid lg:grid-cols-6 gap-x-4 gap-y-4"> <div class="grid lg:grid-cols-6 gap-x-4 gap-y-4">
<div class="lg:col-span-3"> <div class="lg:col-span-3">
@@ -33,15 +32,11 @@
{{ form_row(form.contact) }} {{ form_row(form.contact) }}
</div> </div>
<div class="relative"> <div class="relative">
<div class="grid lg:grid-cols-2 gap-x-8 gap-y-4" {{ stimulus_target('form-partial', 'container') }}> <div class="grid lg:grid-cols-2 gap-x-8 gap-y-4" id="pickup-form">
{% block partial_form %} {% block partial_form %}
{{ form_row(form.pickup) }} {{ form_row(form.pickup) }}
{#{{ form_row(form.pickupDate) }}#}
{% endblock %} {% endblock %}
</div> </div>
<div class="absolute top-0 left-0 inset-0 bg-white/90 flex items-center justify-center" {{ stimulus_target('form-partial', 'spinner') }}>
{% include '_partials/_spinner.html.twig' with { 'class': 'w-8 h-8'} %}
</div>
</div> </div>
<div class="grid lg:grid-cols-2 gap-x-8 gap-y-4"> <div class="grid lg:grid-cols-2 gap-x-8 gap-y-4">
{{ form_row(form.fees) }} {{ form_row(form.fees) }}
@@ -58,4 +53,3 @@
</div> </div>
{{ form_rest(form) }} {{ form_rest(form) }}
{{ form_end(form) }} {{ form_end(form) }}
</div>
+26 -33
View File
@@ -39,11 +39,10 @@
<td> <td>
<button type="button" <button type="button"
class="flex items-center space-x-1" class="flex items-center space-x-1"
{{ stimulus_controller('modal-button', [], [], {'ajax-modal': '#ajax-modal'}) }} title="Teamer:inneninfo {{ application.teamer }}"
{{ stimulus_action('modal-button', 'ajax', null, { hx-get="{{ path('app_admin_application_info', { 'uuid': application.uuid }) }}"
'title': 'Teamer:inneninfo ' ~ application.teamer, hx-target="body"
'url': path('app_admin_application_info', { 'uuid': application.uuid }) hx-swap="beforeend">
}) }}>
<span>{{ application.teamer }}</span> <span>{{ application.teamer }}</span>
{{ icon('info', 'w-4 h-4') }} {{ icon('info', 'w-4 h-4') }}
</button> </button>
@@ -63,34 +62,30 @@
{% if is_granted('DISPOSE', application) %} {% if is_granted('DISPOSE', application) %}
<button type="button" <button type="button"
class="text-green-500" class="text-green-500"
{{ stimulus_controller('modal-button', [], [], {'confirmation-modal': '#confirmation-modal'}) }} title="einteilen"
{{ stimulus_action('modal-button', 'confirmation', null, { hx-get="{{ path('app_admin_application_dispose', { 'uuid': application.uuid }) }}"
'title': 'Bist du sicher?', hx-target="body"
'content': 'Möchtest du ' ~ application.teamer ~ ' wirklich einteilen?', hx-swap="beforeend">
'target-url': path('app_admin_application_dispose', { 'uuid': application.uuid })
}) }}>
{{ icon('check') }} {{ icon('check') }}
</button> </button>
{% endif %} {% endif %}
{% if is_granted('STATUS', application) %} {% if is_granted('STATUS', application) %}
<button type="button" <button type="button"
class="text-primary" class="text-primary"
{{ stimulus_controller('modal-button', [], [], {'ajax-modal': '#ajax-modal'}) }} title="Bewerbungsstatus bearbeiten"
{{ stimulus_action('modal-button', 'ajax', null, { hx-get="{{ path('app_admin_application_status', { 'uuid': application.uuid }) }}"
'title': 'Bewerbungsstatus bearbeiten', hx-target="body"
'url': path('app_admin_application_status', { 'uuid': application.uuid }) hx-swap="beforeend">
}) }}>
{{ icon('power') }} {{ icon('power') }}
</button> </button>
{% endif %} {% endif %}
{% if is_granted('DELETE', application) %} {% if is_granted('DELETE', application) %}
<button type="button" class="text-red-500" <button type="button"
{{ stimulus_controller('modal-button', [], [], {'confirmation-modal': '#confirmation-modal'}) }} class="text-red-500"
{{ stimulus_action('modal-button', 'confirmation', null, { title="Bewerbung löschen"
'title': 'Bist du sicher?', hx-get="{{ path('app_admin_application_delete', { 'uuid': application.uuid }) }}"
'content': 'Möchtest du die Bewerbung von ' ~ application.teamer ~ ' wirklich löschen?', hx-target="body"
'target-url': path('app_admin_application_delete', { 'uuid': application.uuid }) hx-swap="beforeend">
}) }}>
{{ icon('delete') }} {{ icon('delete') }}
</button> </button>
{% endif %} {% endif %}
@@ -134,11 +129,10 @@
<td> <td>
<button type="button" <button type="button"
class="flex items-center space-x-1" class="flex items-center space-x-1"
{{ stimulus_controller('modal-button', [], [], {'ajax-modal': '#ajax-modal'}) }} title="Teamer:inneninfo {{ disposition.teamer }}"
{{ stimulus_action('modal-button', 'ajax', null, { hx-get="{{ path('app_admin_teamer_info', { 'uuid': disposition.teamer.uuid }) }}"
'title': 'Teamer:inneninfo ' ~ disposition.teamer, hx-target="body"
'url': path('app_admin_teamer_info', { 'uuid': disposition.teamer.uuid }) hx-swap="beforeend">
}) }}>
<span>{{ disposition.teamer }}</span> <span>{{ disposition.teamer }}</span>
{{ icon('info', 'w-4 h-4') }} {{ icon('info', 'w-4 h-4') }}
</button> </button>
@@ -155,11 +149,10 @@
{% if is_granted('DELETE', disposition) %} {% if is_granted('DELETE', disposition) %}
<button type="button" <button type="button"
class="text-red-500" class="text-red-500"
{{ stimulus_controller('modal-button', [], [], {'ajax-modal': '#ajax-modal'}) }} title="Einteilung löschen"
{{ stimulus_action('modal-button', 'ajax', null, { hx-get="{{ path('app_admin_disposition_delete', { 'uuid': disposition.uuid }) }}"
'title': 'Einteilung löschen', hx-target="body"
'url': path('app_admin_disposition_delete', { 'uuid': disposition.uuid }) hx-swap="beforeend">
}) }}>
{{ icon('delete') }} {{ icon('delete') }}
</button> </button>
{% endif %} {% endif %}
+7 -13
View File
@@ -10,19 +10,16 @@
<div class="flex flex-col items-end space-y-2 md:flex-row md:items-center md:space-x-2 md:space-y-0"> <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" <button type="button"
class="{{ html_classes('btn btn--small', { 'btn--secondary': filterDto.active }) }}" class="{{ html_classes('btn btn--small', { 'btn--secondary': filterDto.active }) }}"
{{ stimulus_controller('modal-button', [], [], {'ajax-modal': '#ajax-modal'}) }} title="Filter"
{{ stimulus_action('modal-button', 'ajax', null, { hx-get="{{ path('app_common_assignment_filter', { 'r': return_url() }) }}"
'title': 'Einsätze filtern', hx-target="body"
'url': path('app_common_assignment_filter', { 'r': return_url() }) hx-swap="beforeend">
}) }}>
<div class="flex items-center space-x-1">
{{ icon('filter', 'w-4 h-4 shrink-0') }} {{ icon('filter', 'w-4 h-4 shrink-0') }}
{% if filterDto.active %} {% if filterDto.active %}
<span class="whitespace-nowrap">{{ filterDto.activeFiltersCount }} Filter aktiv</span> <span class="whitespace-nowrap">{{ filterDto.activeFiltersCount }} Filter aktiv</span>
{% else %} {% else %}
<span>Filter</span> <span>Filter</span>
{% endif %} {% endif %}
</div>
</button> </button>
{% if filterDto.active %} {% if filterDto.active %}
<a href="{{ path('app_common_assignment_filter_reset', { 'r': return_url() }) }}" class="btn btn--small btn--secondary"> <a href="{{ path('app_common_assignment_filter_reset', { 'r': return_url() }) }}" class="btn btn--small btn--secondary">
@@ -109,12 +106,9 @@
<div class="flex items-center space-x-1 justify-end"> <div class="flex items-center space-x-1 justify-end">
<button type="button" <button type="button"
class="text-red-500" class="text-red-500"
{{ stimulus_controller('modal-button', [], [], {'confirmation-modal': '#confirmation-modal'}) }} hx-get="{{ path('app_admin_assignment_delete', { 'uuid': assignment.uuid }) }}"
{{ stimulus_action('modal-button', 'confirmation', null, { hx-target="body"
'title': 'Bist du sicher?', hx-swap="beforeend">
'content': 'Möchtest du den Einsatz wirklich löschen?',
'target-url': path('app_admin_assignment_delete', { 'uuid': assignment.uuid })
}) }}>
{{ icon('delete') }} {{ icon('delete') }}
</button> </button>
<a href="{{ path('app_admin_assignment_duplicate', { 'uuid': assignment.uuid, 'r': return_url() }) }}"> <a href="{{ path('app_admin_assignment_duplicate', { 'uuid': assignment.uuid, 'r': return_url() }) }}">
@@ -0,0 +1,7 @@
{% extends 'htmx_confirmation_modal.html.twig' %}
{% block content %}
<div>
Möchtest du den Einsatz <em>{{ assignment.destination.product }}</em> wirklich löschen?
</div>
{% endblock %}
@@ -1,9 +0,0 @@
{{ form_start(form) }}
<div class="flex flex-col space-y-4 pb-4">
{{ form_row(form.remarks) }}
</div>
<button type="submit" class="btn">
Löschen
</button>
{{ form_rest(form) }}
{{ form_end(form) }}
@@ -0,0 +1,15 @@
{% extends 'htmx_modal.html.twig' %}
{% block title %}Einteilung löschen{% endblock %}
{% block content %}
{{ form_start(form, { 'attr': { 'hx-post': app.request.uri, 'hx-target': '#htmx-modal', 'hx-swap': 'outerHTML' } }) }}
<div class="flex flex-col space-y-4 pb-4">
{{ form_row(form.remarks) }}
</div>
<button type="submit" class="btn">
Löschen
</button>
{{ form_rest(form) }}
{{ form_end(form) }}
{% endblock %}
-13
View File
@@ -1,13 +0,0 @@
{{ form_start(form) }}
<h2 class="font-bold text-lg pb-4">
{{ ('label.document.type.' ~ document.type)|trans }} {{ document.disposition.teamer }} vom {{ document.createdAt|date('d.m.Y') }}
</h2>
<div class="flex flex-col space-y-4 pb-4">
{{ form_row(form.status) }}
{{ form_row(form.comment) }}
</div>
<button type="submit" class="btn">
Aktualisieren
</button>
{{ form_rest(form) }}
{{ form_end(form) }}
+6 -11
View File
@@ -69,22 +69,17 @@
{% if is_granted('DELETE', upload) %} {% if is_granted('DELETE', upload) %}
<button type="button" <button type="button"
class="text-red-500" class="text-red-500"
{{ stimulus_controller('modal-button', [], [], {'confirmation-modal': '#confirmation-modal'}) }} hx-get="{{ path('app_admin_document_delete', { 'uuid': upload.uuid }) }}"
{{ stimulus_action('modal-button', 'confirmation', null, { hx-target="body"
'title': 'Bist du sicher?', hx-swap="beforeend">
'content': 'Möchtest du das Dokument wirklich löschen?',
'target-url': path('app_admin_document_delete', { 'uuid': upload.uuid })
}) }}>
{{ icon('delete') }} {{ icon('delete') }}
</button> </button>
{% endif %} {% endif %}
{% if is_granted('CHECK', upload) %} {% if is_granted('CHECK', upload) %}
<button type="button" <button type="button"
{{ stimulus_controller('modal-button', [], [], {'ajax-modal': '#ajax-modal'}) }} hx-get="{{ path('app_admin_document_check', { 'uuid': upload.uuid }) }}"
{{ stimulus_action('modal-button', 'ajax', null, { hx-target="body"
'title': 'Dokumentenstatus bearbeiten', hx-swap="beforeend">
'url': path('app_admin_document_check', { 'uuid': upload.uuid })
}) }}>
{{ icon('edit') }} {{ icon('edit') }}
</button> </button>
{% endif %} {% endif %}
@@ -0,0 +1,19 @@
{% extends 'htmx_modal.html.twig' %}
{% block title %}Dokumentenstatus bearbeiten{% endblock %}
{% block content %}
{{ form_start(form, { 'attr': { 'hx-post': app.request.uri, 'hx-target': '#htmx-modal', 'hx-swap': 'outerHTML' } }) }}
<h2 class="font-bold text-lg pb-4">
{{ ('label.document.type.' ~ document.type)|trans }} {{ document.disposition.teamer }} vom {{ document.createdAt|date('d.m.Y') }}
</h2>
<div class="flex flex-col space-y-4 pb-4">
{{ form_row(form.status) }}
{{ form_row(form.comment) }}
</div>
<button type="submit" class="btn">
Aktualisieren
</button>
{{ form_rest(form) }}
{{ form_end(form) }}
{% endblock %}
@@ -0,0 +1,7 @@
{% extends 'htmx_confirmation_modal.html.twig' %}
{% block content %}
<div>
Möchtest du das Dokument <em>{{ ('label.document.type.' ~ document.type)|trans }}</em> wirklich löschen?
</div>
{% endblock %}
@@ -1,10 +0,0 @@
{{ form_start(form) }}
<div class="flex flex-col space-y-4 pb-4">
{{ form_row(form.comment) }}
{{ form_row(form.commentInternal) }}
</div>
<button type="submit" class="btn">
Speichern und freigeben
</button>
{{ form_rest(form) }}
{{ form_end(form) }}
@@ -0,0 +1,16 @@
{% extends 'htmx_modal.html.twig' %}
{% block title %}Feedback freigeben{% endblock %}
{% block content %}
{{ form_start(form, { 'attr': { 'hx-post': app.request.uri, 'hx-target': '#htmx-modal', 'hx-swap': 'outerHTML' } }) }}
<div class="flex flex-col space-y-4 pb-4">
{{ form_row(form.comment) }}
{{ form_row(form.commentInternal) }}
</div>
<button type="submit" class="btn">
Speichern und freigeben
</button>
{{ form_rest(form) }}
{{ form_end(form) }}
{% endblock %}
+6 -8
View File
@@ -127,20 +127,18 @@
{% for feedback in feedbacks %} {% for feedback in feedbacks %}
<li class="py-2 first:pt-0 last:pb-0"> <li class="py-2 first:pt-0 last:pb-0">
<button type="button" <button type="button"
{{ stimulus_controller('modal-button', [], [], {'ajax-modal': '#ajax-modal'}) }} hx-get="{{ path('app_admin_feedback_approve', { 'uuid': feedback.uuid }) }}"
{{ stimulus_action('modal-button', 'ajax', null, { hx-target="body"
'title': 'Feedback freigeben', hx-swap="beforeend">
'url': path('app_admin_feedback_approve', { 'uuid': feedback.uuid }) <span class="flex items-center space-x-1">
}) }}>
<div class="flex items-center space-x-1">
{{ icon('feedback', 'w-4 h-4 shrink-0') }} {{ icon('feedback', 'w-4 h-4 shrink-0') }}
<div class="flex items-center space-x-1 truncate"> <div class="flex items-center space-x-1 truncate">
<span class="whitespace-nowrap">{{ feedback.teamer }}</span> <span class="whitespace-nowrap">{{ feedback.teamer }}</span>
{% include '_partials/_dot.html.twig' %} {% include '_partials/_dot.html.twig' %}
<span class="whitespace-nowrap">{{ feedback.destinationName }}</span> <span class="whitespace-nowrap">{{ feedback.destinationName }}</span>
</div> </div>
</div> </span>
<div class="pl-5 whitespace-nowrap">{{ feedback.jobProfileName }}</div> <span class="pl-5 whitespace-nowrap">{{ feedback.jobProfileName }}</span>
</button> </button>
</li> </li>
{% else %} {% else %}
@@ -1,4 +1,4 @@
{{ form_start(form) }} {{ form_start(form, { 'attr': { 'hx-post': app.request.uri, 'hx-target': '#htmx-modal', 'hx-swap': 'outerHTML' } }) }}
<div class="flex flex-col space-y-4 pb-8"> <div class="flex flex-col space-y-4 pb-8">
{{ form_row(form.dateFrom) }} {{ form_row(form.dateFrom) }}
{{ form_row(form.dateTo) }} {{ form_row(form.dateTo) }}
@@ -1,11 +0,0 @@
{{ form_start(form) }}
<div class="flex flex-col space-y-4 pb-8">
{{ form_row(form.dateFrom) }}
{{ form_row(form.dateTo) }}
{{ form_row(form.description) }}
</div>
<button type="submit" class="btn">
Speichern
</button>
{{ form_rest(form) }}
{{ form_end(form) }}
@@ -39,28 +39,24 @@
<div class="flex items-center space-x-2 justify-end"> <div class="flex items-center space-x-2 justify-end">
<button type="button" <button type="button"
class="text-red-500" class="text-red-500"
{{ stimulus_controller('modal-button', [], [], {'confirmation-modal': '#confirmation-modal'}) }} title="Zeitraum löschen"
{{ stimulus_action('modal-button', 'confirmation', null, { hx-get="{{ path('app_admin_system_availability_delete', { 'id': availability.id }) }}"
'title': 'Bist du sicher?', hx-target="body"
'content': 'Möchtest du den Zeitraum wirklich löschen?', hx-swap="beforeend">
'target-url': path('app_admin_system_availability_delete', { 'id': availability.id })
}) }}>
{{ icon('delete') }} {{ icon('delete') }}
</button> </button>
<button type="button" <button type="button"
{{ stimulus_controller('modal-button', [], [], {'ajax-modal': '#ajax-modal'}) }} title="Verfügbarkeit bearbeiten"
{{ stimulus_action('modal-button', 'ajax', null, { hx-get="{{ path('app_admin_system_availability_edit', { 'id': availability.id }) }}"
'title': 'Verfügbarkeit bearbeiten', hx-target="body"
'url': path('app_admin_system_availability_edit', { 'id': availability.id }) hx-swap="beforeend">
}) }}>
{{ icon('edit') }} {{ icon('edit') }}
</button> </button>
<button type="button" <button type="button"
{{ stimulus_controller('modal-button', [], [], {'ajax-modal': '#ajax-modal'}) }} title="Verfügbarkeit duplizieren"
{{ stimulus_action('modal-button', 'ajax', null, { hx-get="{{ path('app_admin_system_availability_duplicate', { 'id': availability.id }) }}"
'title': 'Verfügbarkeit duplizieren', hx-target="body"
'url': path('app_admin_system_availability_duplicate', { 'id': availability.id }) hx-swap="beforeend">
}) }}>
{{ icon('copy') }} {{ icon('copy') }}
</button> </button>
</div> </div>
@@ -80,11 +76,10 @@
</div> </div>
<button type="button" <button type="button"
class="btn" class="btn"
{{ stimulus_controller('modal-button', [], [], {'ajax-modal': '#ajax-modal'}) }} title="Zeitraum hinzufügen"
{{ stimulus_action('modal-button', 'ajax', null, { hx-get="{{ path('app_admin_system_availability_create') }}"
'title': 'Zeitraum hinzufügen', hx-target="body"
'url': path('app_admin_system_availability_create') hx-swap="beforeend">
}) }}>
Zeitraum hinzufügen Zeitraum hinzufügen
</button> </button>
{% endblock %} {% endblock %}
@@ -0,0 +1,7 @@
{% extends 'htmx_modal.html.twig' %}
{% block title %}Zeitraum hinzufügen{% endblock %}
{% block content %}
{% include 'admin/system/availability/_form.html.twig' %}
{% endblock %}
@@ -0,0 +1,7 @@
{% extends 'htmx_confirmation_modal.html.twig' %}
{% block content %}
<div>
Möchtest du den Zeitraum wirklich löschen?
</div>
{% endblock %}
@@ -0,0 +1,7 @@
{% extends 'htmx_modal.html.twig' %}
{% block title %}Zeitraum duplizieren{% endblock %}
{% block content %}
{% include 'admin/system/availability/_form.html.twig' %}
{% endblock %}
@@ -0,0 +1,7 @@
{% extends 'htmx_modal.html.twig' %}
{% block title %}Zeitraum bearbeiten{% endblock %}
{% block content %}
{% include 'admin/system/availability/_form.html.twig' %}
{% endblock %}
@@ -1,4 +1,4 @@
{{ form_start(form) }} {{ form_start(form, { 'attr': { 'hx-post': app.request.uri, 'hx-target': '#htmx-modal', 'hx-swap': 'outerHTML' } }) }}
<div class="flex flex-col space-y-4 pb-4"> <div class="flex flex-col space-y-4 pb-4">
{{ form_row(form.name) }} {{ form_row(form.name) }}
{{ form_row(form.email) }} {{ form_row(form.email) }}
@@ -1 +0,0 @@
{% include 'admin/system/contact/_form.html.twig' %}
@@ -1 +0,0 @@
{% include 'admin/system/contact/_form.html.twig' %}
+12 -16
View File
@@ -39,20 +39,17 @@
<div class="flex items-center space-x-2 justify-end"> <div class="flex items-center space-x-2 justify-end">
<button type="button" <button type="button"
class="text-red-500" class="text-red-500"
{{ stimulus_controller('modal-button', [], [], {'confirmation-modal': '#confirmation-modal'}) }} title="Ansprechperson löschen"
{{ stimulus_action('modal-button', 'confirmation', null, { hx-get="{{ path('app_admin_system_contact_delete', { 'id': contact.id }) }}"
'title': 'Bist du sicher?', hx-target="body"
'content': 'Möchtest du die Ansprechperson wirklich löschen?', hx-swap="beforeend">
'target-url': path('app_admin_system_contact_delete', { 'id': contact.id })
}) }}>
{{ icon('delete') }} {{ icon('delete') }}
</button> </button>
<button type="button" <button type="button"
{{ stimulus_controller('modal-button', [], [], {'ajax-modal': '#ajax-modal'}) }} title="Ansprechperson bearbeiten"
{{ stimulus_action('modal-button', 'ajax', null, { hx-get="{{ path('app_admin_system_contact_edit', { 'id': contact.id }) }}"
'title': 'Ansprechperson bearbeiten', hx-target="body"
'url': path('app_admin_system_contact_edit', { 'id': contact.id }) hx-swap="beforeend">
}) }}>
{{ icon('edit') }} {{ icon('edit') }}
</button> </button>
</div> </div>
@@ -71,11 +68,10 @@
</div> </div>
<button type="button" <button type="button"
class="btn" class="btn"
{{ stimulus_controller('modal-button', [], [], {'ajax-modal': '#ajax-modal'}) }} title="Ansprechperson hinzufügen"
{{ stimulus_action('modal-button', 'ajax', null, { hx-get="{{ path('app_admin_system_contact_create') }}"
'title': 'Ansprechperson hinzufügen', hx-target="body"
'url': path('app_admin_system_contact_create') hx-swap="beforeend">
}) }}>
Neu Neu
</button> </button>
{% endblock %} {% endblock %}
@@ -0,0 +1,7 @@
{% extends 'htmx_modal.html.twig' %}
{% block title %}Ansprechperson hinzufügen{% endblock %}
{% block content %}
{% include 'admin/system/contact/_form.html.twig' %}
{% endblock %}
@@ -0,0 +1,7 @@
{% extends 'htmx_confirmation_modal.html.twig' %}
{% block content %}
<div>
Möchtest du <em>{{ contact }}</em> als Ansprechperson wirklich löschen?
</div>
{% endblock %}
@@ -0,0 +1,7 @@
{% extends 'htmx_modal.html.twig' %}
{% block title %}Ansprechperson bearbeiten{% endblock %}
{% block content %}
{% include 'admin/system/contact/_form.html.twig' %}
{% endblock %}
@@ -1,9 +0,0 @@
{{ form_start(form) }}
<div class="pb-4">
{{ form_row(form.displayName) }}
</div>
<button type="submit" class="btn">
aktualisieren
</button>
{{ form_rest(form) }}
{{ form_end(form) }}

Some files were not shown because too many files have changed in this diff Show More