From 25a016a02bf7bf7932200bb1efcf77478c8012ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Fromme?= Date: Tue, 3 Oct 2023 17:42:10 +0200 Subject: [PATCH] Feat: Implement availabilities --- assets/images/icons.svg | 12 +- .../System/Availability/CreateController.php | 55 +++++++++ .../System/Availability/DeleteController.php | 35 ++++++ .../System/Availability/IndexController.php | 44 +++++++ .../Admin/System/Fee/CreateController.php | 22 ++-- .../Admin/System/Fee/EditController.php | 46 ------- .../System/Training/CreateController.php | 22 ++-- .../Admin/System/Training/EditController.php | 45 ------- .../Profile/AvailabilitiesController.php | 60 ---------- .../Profile/Availability/AddController.php | 40 +++++++ .../Profile/Availability/CreateController.php | 65 ++++++++++ .../Profile/Availability/DeleteController.php | 45 +++++++ .../Profile/Availability/IndexController.php | 62 ++++++++++ src/Entity/Availability.php | 13 +- src/Entity/Teamer.php | 1 + src/Form/AvailabilityType.php | 32 +++++ src/Menu/AdminMenuBuilder.php | 31 ++--- src/Menu/TeamerMenuBuilder.php | 2 +- src/Repository/AvailabilityRepository.php | 18 ++- src/Security/Voter/AvailabilityVoter.php | 43 +++++++ .../system/availability/create.html.twig | 10 ++ .../admin/system/availability/index.html.twig | 68 +++++++++++ templates/admin/system/fee/_form.html.twig | 15 --- templates/admin/system/fee/create.html.twig | 22 ++-- templates/admin/system/fee/edit.html.twig | 12 -- templates/admin/system/fee/index.html.twig | 113 +++++++++--------- .../admin/system/training/_form.html.twig | 14 --- .../admin/system/training/create.html.twig | 21 ++-- .../admin/system/training/edit.html.twig | 12 -- .../admin/system/training/index.html.twig | 113 +++++++++--------- templates/paginator/sliding.html.twig | 2 +- .../teamer/profile/availabilities.html.twig | 39 ------ .../profile/availability/create.html.twig | 10 ++ .../profile/availability/index.html.twig | 99 +++++++++++++++ translations/messages.de.yaml | 6 +- 35 files changed, 827 insertions(+), 422 deletions(-) create mode 100644 src/Controller/Admin/System/Availability/CreateController.php create mode 100644 src/Controller/Admin/System/Availability/DeleteController.php create mode 100644 src/Controller/Admin/System/Availability/IndexController.php delete mode 100644 src/Controller/Admin/System/Fee/EditController.php delete mode 100644 src/Controller/Admin/System/Training/EditController.php delete mode 100644 src/Controller/Teamer/Profile/AvailabilitiesController.php create mode 100644 src/Controller/Teamer/Profile/Availability/AddController.php create mode 100644 src/Controller/Teamer/Profile/Availability/CreateController.php create mode 100644 src/Controller/Teamer/Profile/Availability/DeleteController.php create mode 100644 src/Controller/Teamer/Profile/Availability/IndexController.php create mode 100644 src/Form/AvailabilityType.php create mode 100644 src/Security/Voter/AvailabilityVoter.php create mode 100644 templates/admin/system/availability/create.html.twig create mode 100644 templates/admin/system/availability/index.html.twig delete mode 100644 templates/admin/system/fee/_form.html.twig delete mode 100644 templates/admin/system/fee/edit.html.twig delete mode 100644 templates/admin/system/training/_form.html.twig delete mode 100644 templates/admin/system/training/edit.html.twig delete mode 100644 templates/teamer/profile/availabilities.html.twig create mode 100644 templates/teamer/profile/availability/create.html.twig create mode 100644 templates/teamer/profile/availability/index.html.twig diff --git a/assets/images/icons.svg b/assets/images/icons.svg index 81b98a9..39dadb2 100644 --- a/assets/images/icons.svg +++ b/assets/images/icons.svg @@ -141,9 +141,15 @@ - - - + + + + + + + + + diff --git a/src/Controller/Admin/System/Availability/CreateController.php b/src/Controller/Admin/System/Availability/CreateController.php new file mode 100644 index 0000000..4bd42e8 --- /dev/null +++ b/src/Controller/Admin/System/Availability/CreateController.php @@ -0,0 +1,55 @@ +generateUrl('app_admin_system_availability_create'); + + $availability = new Availability(); + $form = $this->createForm(AvailabilityType::class, $availability, ['action' => $action, 'ajax_submit' => true]); + $form->handleRequest($request); + + if ($form->isSubmitted() && $form->isValid()) { + $this->entityManager->persist($availability); + $this->entityManager->flush(); + + $this->addFlash('success', 'Der Zeitraum wurde hinzugefügt.'); + $this->logger->info('Add availability', [ + 'availability' => $availability, + ]); + + $redirectUrl = $this->generateUrl('app_admin_system_availability_index'); + $response->setCloseAndRedirect($redirectUrl); + } else { + $content = $this->renderView('admin/system/availability/create.html.twig', [ + 'form' => $form, + ]); + $response->setContent($content); + } + + return $this->json($response); + } +} \ No newline at end of file diff --git a/src/Controller/Admin/System/Availability/DeleteController.php b/src/Controller/Admin/System/Availability/DeleteController.php new file mode 100644 index 0000000..74cb284 --- /dev/null +++ b/src/Controller/Admin/System/Availability/DeleteController.php @@ -0,0 +1,35 @@ +entityManager->remove($availability); + $this->entityManager->flush(); + + $this->addFlash('success', 'Die Verfügbarkeit wurde gelöscht'); + $this->logger->info('Delete availability', [ + 'availability' => $availability, + ]); + + return $this->redirectToRoute('app_admin_system_availability_index'); + } +} \ No newline at end of file diff --git a/src/Controller/Admin/System/Availability/IndexController.php b/src/Controller/Admin/System/Availability/IndexController.php new file mode 100644 index 0000000..91d67e6 --- /dev/null +++ b/src/Controller/Admin/System/Availability/IndexController.php @@ -0,0 +1,44 @@ +availabilityRepository + ->getListQuery() + ; + + $pagination = $this->paginator->paginate( + $query, + $request->query->getInt('page', 1), + 10, + [ + 'defaultSortFieldName' => 'availability.dateFrom', + 'defaultSortDirection' => 'asc', + ] + ); + + return $this->render('admin/system/availability/index.html.twig', [ + 'pagination' => $pagination, + ]); + } +} \ No newline at end of file diff --git a/src/Controller/Admin/System/Fee/CreateController.php b/src/Controller/Admin/System/Fee/CreateController.php index 2f7c962..016453c 100644 --- a/src/Controller/Admin/System/Fee/CreateController.php +++ b/src/Controller/Admin/System/Fee/CreateController.php @@ -4,11 +4,12 @@ namespace App\Controller\Admin\System\Fee; use App\Entity\Fee; use App\Form\FeeType; +use App\Model\AjaxModalResponseDto; use Doctrine\ORM\EntityManagerInterface; use Psr\Log\LoggerInterface; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; +use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Annotation\Route; use Symfony\Component\Security\Http\Attribute\IsGranted; @@ -22,10 +23,13 @@ class CreateController extends AbstractController #[Route('/admin/system/fee/create', name: 'app_admin_system_fee_create')] #[IsGranted('ROLE_ADMIN')] - public function index(Request $request): Response + public function index(Request $request): JsonResponse { + $response = new AjaxModalResponseDto(); + $action = $this->generateUrl('app_admin_system_fee_create'); + $fee = new Fee(); - $form = $this->createForm(FeeType::class, $fee); + $form = $this->createForm(FeeType::class, $fee, ['action' => $action, 'ajax_submit' => true]); $form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { @@ -37,11 +41,15 @@ class CreateController extends AbstractController 'fee' => $fee->getName(), ]); - return $this->redirectToRoute('app_admin_system_fee_index'); + $redirectUrl = $this->generateUrl('app_admin_system_fee_index'); + $response->setCloseAndRedirect($redirectUrl); + } else { + $content = $this->renderView('admin/system/fee/create.html.twig', [ + 'form' => $form + ]); + $response->setContent($content); } - return $this->render('admin/system/fee/create.html.twig', [ - 'form' => $form - ]); + return $this->json($response); } } \ No newline at end of file diff --git a/src/Controller/Admin/System/Fee/EditController.php b/src/Controller/Admin/System/Fee/EditController.php deleted file mode 100644 index 036ba1c..0000000 --- a/src/Controller/Admin/System/Fee/EditController.php +++ /dev/null @@ -1,46 +0,0 @@ -createForm(FeeType::class, $fee); - $form->handleRequest($request); - - if ($form->isSubmitted() && $form->isValid()) { - $this->entityManager->persist($fee); - $this->entityManager->flush(); - - $this->addFlash('success', 'Das Honorar wurde aktualisiert'); - $this->logger->info('Edit fee', [ - 'fee' => $fee->getName(), - ]); - - return $this->redirectToRoute('app_admin_system_fee_index'); - } - - return $this->render('admin/system/fee/edit.html.twig', [ - 'form' => $form - ]); - } -} \ No newline at end of file diff --git a/src/Controller/Admin/System/Training/CreateController.php b/src/Controller/Admin/System/Training/CreateController.php index add1cd4..600260a 100644 --- a/src/Controller/Admin/System/Training/CreateController.php +++ b/src/Controller/Admin/System/Training/CreateController.php @@ -4,11 +4,12 @@ namespace App\Controller\Admin\System\Training; use App\Entity\Training; use App\Form\TrainingType; +use App\Model\AjaxModalResponseDto; use Doctrine\ORM\EntityManagerInterface; use Psr\Log\LoggerInterface; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; +use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Annotation\Route; use Symfony\Component\Security\Http\Attribute\IsGranted; @@ -22,10 +23,13 @@ class CreateController extends AbstractController #[Route('/admin/system/training/create', name: 'app_admin_system_training_create')] #[IsGranted('ROLE_ADMIN')] - public function index(Request $request): Response + public function index(Request $request): JsonResponse { + $response = new AjaxModalResponseDto(); + $action = $this->generateUrl('app_admin_system_training_create'); + $training = new Training(); - $form = $this->createForm(TrainingType::class, $training); + $form = $this->createForm(TrainingType::class, $training, ['action' => $action, 'ajax_submit' => true]); $form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { @@ -37,11 +41,15 @@ class CreateController extends AbstractController 'training' => $training->getName(), ]); - return $this->redirectToRoute('app_admin_system_training_index'); + $redirectUrl = $this->generateUrl('app_admin_system_training_index'); + $response->setCloseAndRedirect($redirectUrl); + } else { + $content = $this->renderView('admin/system/training/create.html.twig', [ + 'form' => $form + ]); + $response->setContent($content); } - return $this->render('admin/system/training/create.html.twig', [ - 'form' => $form - ]); + return $this->json($response); } } \ No newline at end of file diff --git a/src/Controller/Admin/System/Training/EditController.php b/src/Controller/Admin/System/Training/EditController.php deleted file mode 100644 index 1eab263..0000000 --- a/src/Controller/Admin/System/Training/EditController.php +++ /dev/null @@ -1,45 +0,0 @@ -createForm(TrainingType::class, $training); - $form->handleRequest($request); - - if ($form->isSubmitted() && $form->isValid()) { - $this->entityManager->flush(); - - $this->addFlash('success', 'Die Fortbildung wurde aktualisiert'); - $this->logger->info('Edit training', [ - 'training' => $training->getName(), - ]); - - return $this->redirectToRoute('app_admin_system_training_index'); - } - - return $this->render('admin/system/training/edit.html.twig', [ - 'form' => $form - ]); - } -} \ No newline at end of file diff --git a/src/Controller/Teamer/Profile/AvailabilitiesController.php b/src/Controller/Teamer/Profile/AvailabilitiesController.php deleted file mode 100644 index b55e51e..0000000 --- a/src/Controller/Teamer/Profile/AvailabilitiesController.php +++ /dev/null @@ -1,60 +0,0 @@ -getUser(); - $teamer = $user->getTeamer(); - - $selectableAvailabilities = $this->availabilityRepository->getSelectable($teamer); - $form = $this->createFormBuilder($teamer) - ->add('availabilities', EntityType::class, [ - 'label' => false, - 'class' => Availability::class, - 'choice_label' => function($choice) { - return sprintf('%s - %s', $choice->getDateFrom()->format('d.m.Y'), $choice->getDateTo()->format('d.m.Y')); - }, - 'choices' => $selectableAvailabilities, - 'multiple' => true, - 'expanded' => true, - ]) - ->getForm() - ; - $form->handleRequest($request); - - if ($form->isSubmitted() && $form->isValid()) { - $this->entityManager->flush(); - - return $this->redirectToRoute('app_teamer_profile_availabilities'); - } - - return $this->render('teamer/profile/availabilities.html.twig', [ - 'availabilities' => $teamer->getAvailabilities(), - 'selectableAvailabilities' => $selectableAvailabilities, - 'form' => $form, - ]); - } -} \ No newline at end of file diff --git a/src/Controller/Teamer/Profile/Availability/AddController.php b/src/Controller/Teamer/Profile/Availability/AddController.php new file mode 100644 index 0000000..034e0e6 --- /dev/null +++ b/src/Controller/Teamer/Profile/Availability/AddController.php @@ -0,0 +1,40 @@ +getUser(); + $teamer = $user->getTeamer(); + + $teamer->addAvailability($availability); + $this->entityManager->flush(); + + $this->logger->info('Add availability', [ + 'user' => $user->getUserIdentifier(), + 'availability' => $availability, + ]); + + return $this->redirectToRoute('app_teamer_profile_availability_index'); + } +} \ No newline at end of file diff --git a/src/Controller/Teamer/Profile/Availability/CreateController.php b/src/Controller/Teamer/Profile/Availability/CreateController.php new file mode 100644 index 0000000..0b5e904 --- /dev/null +++ b/src/Controller/Teamer/Profile/Availability/CreateController.php @@ -0,0 +1,65 @@ +generateUrl('app_teamer_profile_availability_create'); + + $availability = new Availability(); + + $form = $this->createForm(AvailabilityType::class, $availability, ['action' => $action, 'ajax_submit' => true]); + $form->handleRequest($request); + + if ($form->isSubmitted() && $form->isValid()) { + /** @var User $user */ + $user = $this->getUser(); + $teamer = $user->getTeamer(); + $teamer + ->addAvailability($availability) + ->addCustomAvailability($availability) + ; + + $this->entityManager->persist($availability); + $this->entityManager->flush(); + + $this->addFlash('success', 'Der Zeitraum wurde hinzugefügt.'); + $this->logger->info('Add availability', [ + 'availability' => $availability, + ]); + + $redirectUrl = $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); + } +} \ No newline at end of file diff --git a/src/Controller/Teamer/Profile/Availability/DeleteController.php b/src/Controller/Teamer/Profile/Availability/DeleteController.php new file mode 100644 index 0000000..44b13e5 --- /dev/null +++ b/src/Controller/Teamer/Profile/Availability/DeleteController.php @@ -0,0 +1,45 @@ +getUser(); + $teamer = $user->getTeamer(); + + if (null === $availability->getOwner()) { + $teamer->removeAvailability($availability); + } elseif ($teamer === $availability->getOwner()) { + $this->entityManager->remove($availability); + } + + $this->entityManager->flush(); + + $this->addFlash('success', 'Der Zeitraum wurde entfernt/gelöscht.'); + $this->logger->info('Delete availability', [ + 'user' => $this->getUser()->getUserIdentifier(), + ]); + + return $this->redirectToRoute('app_teamer_profile_availability_index'); + } +} \ No newline at end of file diff --git a/src/Controller/Teamer/Profile/Availability/IndexController.php b/src/Controller/Teamer/Profile/Availability/IndexController.php new file mode 100644 index 0000000..57a93a7 --- /dev/null +++ b/src/Controller/Teamer/Profile/Availability/IndexController.php @@ -0,0 +1,62 @@ +getUser(); + $teamer = $user->getTeamer(); + + $availabilities = $teamer->getAvailabilities()->toArray(); + $selectedAvailabilities = $this->groupRecords($availabilities); + + $availabilities = $this->availabilityRepository->getSelectableForTeamer($teamer); + $selectableAvailabilities = $this->groupRecords($availabilities); + + return $this->render('teamer/profile/availability/index.html.twig', [ + 'selectedAvailabilities' => $selectedAvailabilities, + 'selectableAvailabilities' => $selectableAvailabilities, + ]); + } + + private function groupRecords(array $records): array + { + $selectableAvailabilities = []; + + foreach ($records as $record) { + /** @var Availability $record */ + $dateFrom = $record->getDateFrom(); + $year = $dateFrom->format('Y'); + $month = (new Carbon($dateFrom))->locale('de_DE')->monthName; + + if (false === isset($selectableAvailabilities[$year])) { + $selectableAvailabilities[$year] = []; + } + + if (false === isset($selectableAvailabilities[$year][$month])) { + $selectableAvailabilities[$year][$month] = []; + } + + $selectableAvailabilities[$year][$month][] = $record; + } + + return $selectableAvailabilities; + } +} \ No newline at end of file diff --git a/src/Entity/Availability.php b/src/Entity/Availability.php index f9da5fa..dc73cb1 100644 --- a/src/Entity/Availability.php +++ b/src/Entity/Availability.php @@ -9,6 +9,7 @@ use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\DBAL\Types\Types; use Doctrine\ORM\Mapping as ORM; +use Symfony\Component\Validator\Constraints as Assert; #[ORM\Entity(repositoryClass: AvailabilityRepository::class)] class Availability implements BlameableEntityInterface, TimestampableEntityInterface @@ -22,9 +23,12 @@ class Availability implements BlameableEntityInterface, TimestampableEntityInter private ?int $id = null; #[ORM\Column(type: Types::DATE_IMMUTABLE)] + #[Assert\NotNull(message: 'Bitte gib das Datum an')] private ?\DateTimeImmutable $dateFrom = null; #[ORM\Column(type: Types::DATE_IMMUTABLE)] + #[Assert\NotNull(message: 'Bitte gib das Datum an')] + #[Assert\GreaterThan(propertyPath: 'dateFrom', message: 'Das Datum muss nach dem Beginndatum liegen')] private ?\DateTimeImmutable $dateTo = null; #[ORM\ManyToOne(inversedBy: 'customAvailabilities')] @@ -38,6 +42,11 @@ class Availability implements BlameableEntityInterface, TimestampableEntityInter $this->teamers = new ArrayCollection(); } + public function __toString() + { + return sprintf('%s - %s', $this->getDateFrom()->format('d.m.Y'), $this->getDateTo()->format('d.m.Y')); + } + public function getId(): ?int { return $this->id; @@ -48,7 +57,7 @@ class Availability implements BlameableEntityInterface, TimestampableEntityInter return $this->dateFrom; } - public function setDateFrom(\DateTimeImmutable $dateFrom): static + public function setDateFrom(?\DateTimeImmutable $dateFrom): static { $this->dateFrom = $dateFrom; @@ -60,7 +69,7 @@ class Availability implements BlameableEntityInterface, TimestampableEntityInter return $this->dateTo; } - public function setDateTo(\DateTimeImmutable $dateTo): static + public function setDateTo(?\DateTimeImmutable $dateTo): static { $this->dateTo = $dateTo; diff --git a/src/Entity/Teamer.php b/src/Entity/Teamer.php index 5eefcab..8441ae6 100644 --- a/src/Entity/Teamer.php +++ b/src/Entity/Teamer.php @@ -84,6 +84,7 @@ class Teamer implements TimestampableEntityInterface private ?string $remarks = null; #[ORM\ManyToMany(targetEntity: Availability::class, inversedBy: 'teamers')] + #[ORM\OrderBy(['dateFrom' => 'ASC'])] private Collection $availabilities; #[ORM\OneToMany(mappedBy: 'owner', targetEntity: Availability::class)] diff --git a/src/Form/AvailabilityType.php b/src/Form/AvailabilityType.php new file mode 100644 index 0000000..b34603e --- /dev/null +++ b/src/Form/AvailabilityType.php @@ -0,0 +1,32 @@ +add('dateFrom', DatepickerType::class, [ + 'label' => 'Datum von', + 'min_date' => new \DateTimeImmutable(), + ]) + ->add('dateTo', DatepickerType::class, [ + 'label' => 'Datum bis', + 'min_date' => new \DateTimeImmutable(), + ]) + ; + } + + public function configureOptions(OptionsResolver $resolver): void + { + $resolver->setDefaults([ + 'data_class' => Availability::class, + ]); + } +} \ No newline at end of file diff --git a/src/Menu/AdminMenuBuilder.php b/src/Menu/AdminMenuBuilder.php index a660263..379e37a 100644 --- a/src/Menu/AdminMenuBuilder.php +++ b/src/Menu/AdminMenuBuilder.php @@ -41,35 +41,17 @@ class AdminMenuBuilder extends AbstractMenuBuilder 'title' => 'Einstellungen', 'icon' => 'settings', 'children' => [ + [ + 'route' => 'app_admin_system_availability_index', + 'title' => 'Verfügbarkeiten', + ], [ 'route' => 'app_admin_system_fee_index', 'title' => 'Honorare', - 'children' => [ - [ - 'route' => 'app_admin_system_fee_create', - 'title' => 'Honorar anlegen', - ], - [ - 'route' => 'app_admin_system_fee_edit', - 'routeParameters' => $this->getDefaultRouteParameters(), - 'title' => 'Honorar bearbeiten', - ], - ], ], [ 'route' => 'app_admin_system_training_index', 'title' => 'Fortbildungen', - 'children' => [ - [ - 'route' => 'app_admin_system_training_create', - 'title' => 'Fortbildung anlegen', - ], - [ - 'route' => 'app_admin_system_training_edit', - 'routeParameters' => $this->getDefaultRouteParameters(), - 'title' => 'Fortbildung bearbeiten', - ], - ], ], [ 'route' => 'app_admin_system_job_profile_index', @@ -79,6 +61,11 @@ class AdminMenuBuilder extends AbstractMenuBuilder 'route' => 'app_admin_system_job_profile_create', 'title' => 'Job-Profil anlegen', ], + [ + 'route' => 'app_admin_system_job_profile_edit', + 'routeParameters' => $this->getDefaultRouteParameters(), + 'title' => 'Job-Profil bearbeiten', + ], ], ], [ diff --git a/src/Menu/TeamerMenuBuilder.php b/src/Menu/TeamerMenuBuilder.php index 9ad4d6b..605fdf1 100644 --- a/src/Menu/TeamerMenuBuilder.php +++ b/src/Menu/TeamerMenuBuilder.php @@ -28,7 +28,7 @@ class TeamerMenuBuilder extends AbstractMenuBuilder 'title' => 'Jobprofile & Skills', ], [ - 'route' => 'app_teamer_profile_availabilities', + 'route' => 'app_teamer_profile_availability_index', 'title' => 'Meine Verfügbarkeit', ], ], diff --git a/src/Repository/AvailabilityRepository.php b/src/Repository/AvailabilityRepository.php index ab9b94f..f12918e 100644 --- a/src/Repository/AvailabilityRepository.php +++ b/src/Repository/AvailabilityRepository.php @@ -5,6 +5,7 @@ namespace App\Repository; use App\Entity\Availability; use App\Entity\Teamer; use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; +use Doctrine\ORM\Query; use Doctrine\Persistence\ManagerRegistry; /** @@ -22,7 +23,22 @@ class AvailabilityRepository extends ServiceEntityRepository parent::__construct($registry, Availability::class); } - public function getSelectable(Teamer $teamer): array + public function getListQuery(): Query + { + $qb = $this->createQueryBuilder('availability'); + + return $qb + ->where($qb->expr()->andX( + $qb->expr()->gt('availability.dateFrom', ':today'), + $qb->expr()->isNull('availability.owner') + )) + ->orderBy('availability.dateFrom', 'ASC') + ->setParameter('today', new \DateTimeImmutable()) + ->getQuery() + ; + } + + public function getSelectableForTeamer(Teamer $teamer): array { $qb = $this->createQueryBuilder('availability'); diff --git a/src/Security/Voter/AvailabilityVoter.php b/src/Security/Voter/AvailabilityVoter.php new file mode 100644 index 0000000..77b9d15 --- /dev/null +++ b/src/Security/Voter/AvailabilityVoter.php @@ -0,0 +1,43 @@ +security->isGranted('ROLE_ADMINISTRATIVE')) { + return true; + } + + /** @var User $user */ + $user = $this->security->getUser(); + $teamer = $user->getTeamer(); + + return null === $availability->getOwner() || $teamer === $availability->getOwner(); + } +} \ No newline at end of file diff --git a/templates/admin/system/availability/create.html.twig b/templates/admin/system/availability/create.html.twig new file mode 100644 index 0000000..296c843 --- /dev/null +++ b/templates/admin/system/availability/create.html.twig @@ -0,0 +1,10 @@ +{{ form_start(form) }} +
+ {{ form_row(form.dateFrom) }} + {{ form_row(form.dateTo) }} +
+ +{{ form_rest(form) }} +{{ form_end(form) }} \ No newline at end of file diff --git a/templates/admin/system/availability/index.html.twig b/templates/admin/system/availability/index.html.twig new file mode 100644 index 0000000..805f635 --- /dev/null +++ b/templates/admin/system/availability/index.html.twig @@ -0,0 +1,68 @@ +{% extends 'admin/layout.html.twig' %} + +{% block title %}Einstellungen - Verfügbarkeiten/Zeiträume{% endblock %} + +{% block content %} +

+ Verfügbarkeiten/Zeiträume +

+
+
+ + + + + + + + + + {% for availability in pagination %} + + + + + + {% else %} + + + + {% endfor %} + +
+ {{ knp_pagination_sortable(pagination, 'Datum von', 'availability.dateFrom') }} + + {{ knp_pagination_sortable(pagination, 'Datum bis', 'availability.dateTo') }} +
+ {{ availability.dateFrom|date('d.m.Y') }} + + {{ availability.dateTo|date('d.m.Y') }} + +
+ +
+
+
Keine Daten...
+
+ {{ knp_pagination_render(pagination) }} +
+
+ +{% endblock %} \ No newline at end of file diff --git a/templates/admin/system/fee/_form.html.twig b/templates/admin/system/fee/_form.html.twig deleted file mode 100644 index b40e1ee..0000000 --- a/templates/admin/system/fee/_form.html.twig +++ /dev/null @@ -1,15 +0,0 @@ -{{ form_start(form) }} -
- {{ form_row(form.name) }} - {{ form_row(form.value) }} -
-
- - - Abbrechen - -
-{{ form_rest(form) }} -{{ form_end(form) }} diff --git a/templates/admin/system/fee/create.html.twig b/templates/admin/system/fee/create.html.twig index fd4fe84..79bd00a 100644 --- a/templates/admin/system/fee/create.html.twig +++ b/templates/admin/system/fee/create.html.twig @@ -1,12 +1,10 @@ -{% extends 'admin/layout.html.twig' %} - -{% block title %}Einstellungen - Honorar anlegen{% endblock %} - -{% block content %} -
-

- Honorar anlegen -

- {% include 'admin/system/fee/_form.html.twig' %} -
-{% endblock %} \ No newline at end of file +{{ form_start(form) }} +
+ {{ form_row(form.name) }} + {{ form_row(form.value) }} +
+ +{{ form_rest(form) }} +{{ form_end(form) }} diff --git a/templates/admin/system/fee/edit.html.twig b/templates/admin/system/fee/edit.html.twig deleted file mode 100644 index 6751296..0000000 --- a/templates/admin/system/fee/edit.html.twig +++ /dev/null @@ -1,12 +0,0 @@ -{% extends 'admin/layout.html.twig' %} - -{% block title %}Einstellungen - Honorar bearbeiten{% endblock %} - -{% block content %} -
-

- Honorar bearbeiten -

- {% include 'admin/system/fee/_form.html.twig' %} -
-{% endblock %} \ No newline at end of file diff --git a/templates/admin/system/fee/index.html.twig b/templates/admin/system/fee/index.html.twig index 7107406..4da2fb7 100644 --- a/templates/admin/system/fee/index.html.twig +++ b/templates/admin/system/fee/index.html.twig @@ -3,62 +3,65 @@ {% block title %}Einstellungen - Honorare{% endblock %} {% block content %} -

- Honorare -

-
-
- - +

+ Honorare +

+
+
+
+ + + + + + + + + {% for fee in fees %} - - - + + + - - - {% for fee in fees %} - - - - - - {% else %} - - - - {% endfor %} - -
+ Bezeichnung + + Wert +
- Bezeichnung - - Wert - + {{ fee.name }} + + {{ fee.value|format_money }} + +
+ +
+
- {{ fee.name }} - - {{ fee.value|format_money }} - -
- - - {{ icon('edit') }} - -
-
-
Keine Daten...
-
-
+ {% else %} + + +
Keine Daten...
+ + + {% endfor %} + +
- - Neu - + + {% endblock %} \ No newline at end of file diff --git a/templates/admin/system/training/_form.html.twig b/templates/admin/system/training/_form.html.twig deleted file mode 100644 index ae500bf..0000000 --- a/templates/admin/system/training/_form.html.twig +++ /dev/null @@ -1,14 +0,0 @@ -{{ form_start(form) }} -
- {{ form_row(form.name) }} -
-
- - - Abbrechen - -
-{{ form_rest(form) }} -{{ form_end(form) }} diff --git a/templates/admin/system/training/create.html.twig b/templates/admin/system/training/create.html.twig index 9cbcca2..a7fa94b 100644 --- a/templates/admin/system/training/create.html.twig +++ b/templates/admin/system/training/create.html.twig @@ -1,12 +1,9 @@ -{% extends 'admin/layout.html.twig' %} - -{% block title %}Einstellungen - Fortbildung anlegen{% endblock %} - -{% block content %} -
-

- Fortbildung anlegen -

- {% include 'admin/system/training/_form.html.twig' %} -
-{% endblock %} \ No newline at end of file +{{ form_start(form) }} +
+ {{ form_row(form.name) }} +
+ +{{ form_rest(form) }} +{{ form_end(form) }} diff --git a/templates/admin/system/training/edit.html.twig b/templates/admin/system/training/edit.html.twig deleted file mode 100644 index af8179b..0000000 --- a/templates/admin/system/training/edit.html.twig +++ /dev/null @@ -1,12 +0,0 @@ -{% extends 'admin/layout.html.twig' %} - -{% block title %}Einstellungen - Fortbildung bearbeiten{% endblock %} - -{% block content %} -
-

- Fortbildung bearbeiten -

- {% include 'admin/system/training/_form.html.twig' %} -
-{% endblock %} \ No newline at end of file diff --git a/templates/admin/system/training/index.html.twig b/templates/admin/system/training/index.html.twig index ed2644d..f2daa19 100644 --- a/templates/admin/system/training/index.html.twig +++ b/templates/admin/system/training/index.html.twig @@ -3,62 +3,65 @@ {% block title %}Einstellungen - Fortbildungen{% endblock %} {% block content %} -

- Fortbildungen -

-
-
- - +

+ Fortbildungen +

+
+
+
+ + + + + + + + + {% for training in trainings %} - - - + + + - - - {% for training in trainings %} - - - - - - {% else %} - - - - {% endfor %} - -
+ Bezeichnung + + Teilnahmen +
- Bezeichnung - - Teilnahmen - + {{ training.name }} + + {{ training.trainingAttendances|length|default('-') }} + +
+ +
+
- {{ training.name }} - - {{ training.trainingAttendances|length|default('-') }} - -
- - - {{ icon('edit') }} - -
-
-
Keine Daten...
-
-
+ {% else %} + + +
Keine Daten...
+ + + {% endfor %} + +
- - Neu - + + {% endblock %} \ No newline at end of file diff --git a/templates/paginator/sliding.html.twig b/templates/paginator/sliding.html.twig index f152a03..539e9c6 100644 --- a/templates/paginator/sliding.html.twig +++ b/templates/paginator/sliding.html.twig @@ -1,7 +1,7 @@
-

{{ 'label.paginator.info'|trans({ '{from}': firstItemNumber, '{to}': lastItemNumber, '{total}': totalCount })|raw }}

+

{{ 'paginator.info'|trans({ '{from}': firstItemNumber, '{to}': lastItemNumber, '{total}': totalCount })|raw }}