feat: timeline for role house manager
closes #869b9vmmx
This commit is contained in:
@@ -2,10 +2,12 @@
|
||||
|
||||
namespace App\Controller\Administrative\Assignment;
|
||||
|
||||
use App\Entity\User;
|
||||
use App\Repository\AssignmentRepository;
|
||||
use App\Service\Assignment\TimelineService;
|
||||
use App\Service\Common\TimelineFilterHandler;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\ExpressionLanguage\Expression;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
@@ -20,17 +22,26 @@ class TimelineController extends AbstractController
|
||||
}
|
||||
|
||||
#[Route('/administrative/timeline', name: 'app_administrative_timeline')]
|
||||
#[IsGranted('ROLE_ADMINISTRATIVE')]
|
||||
#[IsGranted(new Expression('is_granted("ROLE_ADMINISTRATIVE") or is_granted("ROLE_HOUSE_MANAGER")'))]
|
||||
public function index(): Response
|
||||
{
|
||||
/** @var User $user */
|
||||
$user = $this->getUser();
|
||||
|
||||
$period = $this->timelineService->getActiveWindow();
|
||||
$this->filterHandler->setPeriod($period);
|
||||
|
||||
$filterDto = $this->filterHandler->getFilterSettings();
|
||||
|
||||
$hotelCodes = null;
|
||||
if ($this->isGranted('ROLE_HOUSE_MANAGER')) {
|
||||
$filterDto->setHotels([]);
|
||||
$hotelCodes = $user->getHotelCodes();
|
||||
}
|
||||
|
||||
$assignments = $this
|
||||
->assignmentRepository
|
||||
->getListQuery($filterDto, 'destination.dateFrom')
|
||||
->getListQuery($filterDto, 'destination.dateFrom', $hotelCodes)
|
||||
->getResult()
|
||||
;
|
||||
$timelineData = $this->timelineService->preprocess($assignments);
|
||||
|
||||
@@ -8,6 +8,7 @@ use App\Htmx\HxRedirectResponse;
|
||||
use App\Service\Assignment\TimelineService;
|
||||
use App\Service\Common\TimelineFilterHandler;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\ExpressionLanguage\Expression;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
@@ -26,10 +27,13 @@ class TimelineFilterController extends AbstractController
|
||||
}
|
||||
|
||||
#[Route('/common/timeline/filter', name: 'app_common_timeline_filter')]
|
||||
#[IsGranted('ROLE_ADMINISTRATIVE')]
|
||||
#[IsGranted(new Expression('is_granted("ROLE_ADMINISTRATIVE") or is_granted("ROLE_HOUSE_MANAGER")'))]
|
||||
public function index(Request $request): Response
|
||||
{
|
||||
$formData = $this->filterHandler->getFilterSettings();
|
||||
if ($this->isGranted('ROLE_HOUSE_MANAGER')) {
|
||||
$formData->setHotels([]);
|
||||
}
|
||||
|
||||
$form = $this->createForm(TimelineFilterType::class, $formData);
|
||||
$form->handleRequest($request);
|
||||
|
||||
@@ -4,6 +4,7 @@ namespace App\Form;
|
||||
|
||||
use App\Model\TimelineFilterDto;
|
||||
use App\Service\Assignment\TimelineService;
|
||||
use Symfony\Bundle\SecurityBundle\Security;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
@@ -13,6 +14,7 @@ class TimelineFilterType extends AbstractType
|
||||
{
|
||||
public function __construct(
|
||||
private readonly TimelineService $timelineService,
|
||||
private readonly Security $security,
|
||||
private readonly array $destinations,
|
||||
) {
|
||||
}
|
||||
@@ -50,21 +52,23 @@ class TimelineFilterType extends AbstractType
|
||||
])
|
||||
;
|
||||
|
||||
$destinations = $this->destinations;
|
||||
$hotelChoices = [];
|
||||
sort($destinations);
|
||||
foreach ($destinations as $item) {
|
||||
$hotelChoices[$item] = $item;
|
||||
}
|
||||
if (false === $this->security->isGranted('ROLE_HOUSE_MANAGER')) {
|
||||
$destinations = $this->destinations;
|
||||
$hotelChoices = [];
|
||||
sort($destinations);
|
||||
foreach ($destinations as $item) {
|
||||
$hotelChoices[$item] = $item;
|
||||
}
|
||||
|
||||
$builder
|
||||
->add('hotels', MultiselectType::class, [
|
||||
'label' => 'Haus/Destination',
|
||||
'required' => false,
|
||||
'empty_label' => 'nicht filtern',
|
||||
'choices' => $hotelChoices,
|
||||
])
|
||||
;
|
||||
$builder
|
||||
->add('hotels', MultiselectType::class, [
|
||||
'label' => 'Haus/Destination',
|
||||
'required' => false,
|
||||
'empty_label' => 'nicht filtern',
|
||||
'choices' => $hotelChoices,
|
||||
])
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
public function configureOptions(OptionsResolver $resolver): void
|
||||
|
||||
@@ -31,6 +31,15 @@ class HouseManagerMenuBuilder extends AbstractMenuBuilder
|
||||
],
|
||||
],
|
||||
]);
|
||||
$menu->addChild('Zeitleiste', [
|
||||
'route' => 'app_administrative_timeline',
|
||||
'linkAttributes' => [
|
||||
'title' => 'Zeitleiste',
|
||||
],
|
||||
'extras' => [
|
||||
'icon' => 'table',
|
||||
],
|
||||
]);
|
||||
|
||||
$this->addAdminItem($menu);
|
||||
$this->addManagerItem($menu);
|
||||
|
||||
@@ -32,7 +32,7 @@ class AssignmentRepository extends ServiceEntityRepository
|
||||
parent::__construct($registry, Assignment::class);
|
||||
}
|
||||
|
||||
public function getListQuery(AssignmentFilterDto $filterDto, ?string $orderBy = null): Query
|
||||
public function getListQuery(AssignmentFilterDto $filterDto, ?string $orderBy = null, ?array $hotelCodes = null): Query
|
||||
{
|
||||
$qb = $this->createQueryBuilder('assignment');
|
||||
|
||||
@@ -56,6 +56,7 @@ class AssignmentRepository extends ServiceEntityRepository
|
||||
}
|
||||
|
||||
$this->applyFilterSettings($filterDto, $qb);
|
||||
$this->applyHotelCodeRestriction($qb, $hotelCodes);
|
||||
|
||||
return $qb->getQuery();
|
||||
}
|
||||
@@ -231,6 +232,27 @@ class AssignmentRepository extends ServiceEntityRepository
|
||||
}
|
||||
}
|
||||
|
||||
private function applyHotelCodeRestriction(QueryBuilder $qb, ?array $hotelCodes = null): void
|
||||
{
|
||||
if (null === $hotelCodes) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ([] === $hotelCodes) {
|
||||
$qb->andWhere('1 = 0');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$qb
|
||||
->andWhere($qb->expr()->orX(
|
||||
$qb->expr()->in($qb->expr()->substring('destination.hotelCode', 1, 3), ':hotelCodes'),
|
||||
$qb->expr()->in($qb->expr()->substring('destination.hotelCode', -3, 3), ':hotelCodes'),
|
||||
))
|
||||
->setParameter('hotelCodes', $hotelCodes)
|
||||
;
|
||||
}
|
||||
|
||||
public function getBookmarkQueryForTeamer(Teamer $teamer): Query
|
||||
{
|
||||
// Find ids of assignments with available slots first
|
||||
|
||||
@@ -11,10 +11,14 @@
|
||||
}) }}" colspan="{{ colspan }}">
|
||||
{% if item.type == 'disposition' %}
|
||||
<div class="flex items-center space-x-2">
|
||||
<a href="{{ path('app_administrative_assignment_detail', { 'uuid': item.assignmentUuid, 'r': return_url() }) }}"
|
||||
class="inline-block text-xs font-semibold">
|
||||
{{ item.jobProfile }}
|
||||
</a>
|
||||
{% if is_granted('ROLE_HOUSE_MANAGER') %}
|
||||
<span class="inline-block text-xs font-semibold">{{ item.jobProfile }}</span>
|
||||
{% else %}
|
||||
<a href="{{ path('app_administrative_assignment_detail', { 'uuid': item.assignmentUuid, 'r': return_url() }) }}"
|
||||
class="inline-block text-xs font-semibold">
|
||||
{{ item.jobProfile }}
|
||||
</a>
|
||||
{% endif %}
|
||||
<span>|</span>
|
||||
<button type="button"
|
||||
class="flex items-center space-x-2"
|
||||
@@ -26,10 +30,14 @@
|
||||
</button>
|
||||
</div>
|
||||
{% else %}
|
||||
<a href="{{ path('app_administrative_assignment_detail', { 'uuid': item.assignmentUuid, 'r': return_url() }) }}"
|
||||
class="text-xs font-semibold">
|
||||
{{ item.jobProfile }}
|
||||
</a>
|
||||
{% if is_granted('ROLE_HOUSE_MANAGER') %}
|
||||
<span class="text-xs font-semibold">{{ item.jobProfile }}</span>
|
||||
{% else %}
|
||||
<a href="{{ path('app_administrative_assignment_detail', { 'uuid': item.assignmentUuid, 'r': return_url() }) }}"
|
||||
class="text-xs font-semibold">
|
||||
{{ item.jobProfile }}
|
||||
</a>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</td>
|
||||
{% endmacro %}
|
||||
|
||||
@@ -9,7 +9,9 @@
|
||||
{{ form_row(filterForm.dateFrom) }}
|
||||
{{ form_row(filterForm.dateTo) }}
|
||||
</div>
|
||||
{{ form_row(filterForm.hotels) }}
|
||||
{% if filterForm.hotels is defined %}
|
||||
{{ form_row(filterForm.hotels) }}
|
||||
{% endif %}
|
||||
<div class="flex items-center space-x-2">
|
||||
{{ form_widget(filterForm.apply, { 'attr': { 'class': 'btn' } }) }}
|
||||
{{ form_widget(filterForm.reset, { 'attr': { 'class': 'btn btn--secondary' } }) }}
|
||||
|
||||
Reference in New Issue
Block a user