From 95d9a75e463fc40d775853bb61847c99b3e8f68b Mon Sep 17 00:00:00 2001 From: Julie Lenaerts Date: Fri, 8 Aug 2025 15:09:52 +0200 Subject: [PATCH] feat: add invitation list - Introduced `MyInvitationsController` for managing user invitations - Added `InviteACLAwareRepository` and its interface for handling invite data operations - Created views for listing and displaying user-specific invitations - Updated user menu to include "My invitations list" option --- .../unreleased/Feature-20250808-120802.yaml | 6 + .../Controller/CalendarController.php | 2 +- .../Controller/MyInvitationsController.php | 62 +++++++ .../Menu/UserMenuBuilder.php | 7 + .../Repository/InviteACLAwareRepository.php | 68 +++++++ .../InviteACLAwareRepositoryInterface.php | 21 +++ .../views/Invitations/_list_item.html.twig | 172 ++++++++++++++++++ .../views/Invitations/listByUser.html.twig | 27 +++ 8 files changed, 364 insertions(+), 1 deletion(-) create mode 100644 .changes/unreleased/Feature-20250808-120802.yaml create mode 100644 src/Bundle/ChillCalendarBundle/Controller/MyInvitationsController.php create mode 100644 src/Bundle/ChillCalendarBundle/Repository/InviteACLAwareRepository.php create mode 100644 src/Bundle/ChillCalendarBundle/Repository/InviteACLAwareRepositoryInterface.php create mode 100644 src/Bundle/ChillCalendarBundle/Resources/views/Invitations/_list_item.html.twig create mode 100644 src/Bundle/ChillCalendarBundle/Resources/views/Invitations/listByUser.html.twig diff --git a/.changes/unreleased/Feature-20250808-120802.yaml b/.changes/unreleased/Feature-20250808-120802.yaml new file mode 100644 index 000000000..50d1eb8ba --- /dev/null +++ b/.changes/unreleased/Feature-20250808-120802.yaml @@ -0,0 +1,6 @@ +kind: Feature +body: Create invitation list in user menu +time: 2025-08-08T12:08:02.446361367+02:00 +custom: + Issue: "385" + SchemaChange: No schema change diff --git a/src/Bundle/ChillCalendarBundle/Controller/CalendarController.php b/src/Bundle/ChillCalendarBundle/Controller/CalendarController.php index 94db03b1f..ae8114ea7 100644 --- a/src/Bundle/ChillCalendarBundle/Controller/CalendarController.php +++ b/src/Bundle/ChillCalendarBundle/Controller/CalendarController.php @@ -266,7 +266,7 @@ class CalendarController extends AbstractController } if (!$this->getUser() instanceof User) { - throw new UnauthorizedHttpException('you are not an user'); + throw new UnauthorizedHttpException('you are not a user'); } $view = '@ChillCalendar/Calendar/listByUser.html.twig'; diff --git a/src/Bundle/ChillCalendarBundle/Controller/MyInvitationsController.php b/src/Bundle/ChillCalendarBundle/Controller/MyInvitationsController.php new file mode 100644 index 000000000..d39e21476 --- /dev/null +++ b/src/Bundle/ChillCalendarBundle/Controller/MyInvitationsController.php @@ -0,0 +1,62 @@ +denyAccessUnlessGranted('ROLE_USER'); + + $user = $this->getUser(); + + if (!$user instanceof User) { + throw new UnauthorizedHttpException('you are not a user'); + } + + $total = $this->inviteACLAwareRepository->countByUser($user); + $paginator = $this->paginator->create($total); + $invitations = $this->inviteACLAwareRepository->findByUser( + $user, + ['createdAt' => 'DESC'], + $paginator->getCurrentPageFirstItemNumber(), + $paginator->getItemsPerPage() + ); + + dump($invitations); + + $view = '@ChillCalendar/Invitations/listByUser.html.twig'; + + return $this->render($view, [ + 'invitations' => $invitations, + 'paginator' => $paginator, + ]); + } +} diff --git a/src/Bundle/ChillCalendarBundle/Menu/UserMenuBuilder.php b/src/Bundle/ChillCalendarBundle/Menu/UserMenuBuilder.php index 3a062f7b8..fe3083d96 100644 --- a/src/Bundle/ChillCalendarBundle/Menu/UserMenuBuilder.php +++ b/src/Bundle/ChillCalendarBundle/Menu/UserMenuBuilder.php @@ -30,6 +30,13 @@ class UserMenuBuilder implements LocalMenuBuilderInterface 'order' => 9, 'icon' => 'tasks', ]); + $menu->addChild('My invitations list', [ + 'route' => 'chill_calendar_invitations_list_my', + ]) + ->setExtras([ + 'order' => 9, + 'icon' => 'tasks', + ]); } } diff --git a/src/Bundle/ChillCalendarBundle/Repository/InviteACLAwareRepository.php b/src/Bundle/ChillCalendarBundle/Repository/InviteACLAwareRepository.php new file mode 100644 index 000000000..e79381e19 --- /dev/null +++ b/src/Bundle/ChillCalendarBundle/Repository/InviteACLAwareRepository.php @@ -0,0 +1,68 @@ +buildQueryByUser($user) + ->select('COUNT(i)') + ->getQuery() + ->getSingleScalarResult(); + } + + public function findByUser(User $user, ?array $orderBy = [], ?int $offset = null, ?int $limit = null): array + { + $qb = $this->buildQueryByUser($user) + ->select('i'); + + foreach ($orderBy as $sort => $order) { + $qb->addOrderBy('i.'.$sort, $order); + } + + if (null !== $offset) { + $qb->setFirstResult($offset); + } + + if (null !== $limit) { + $qb->setMaxResults($limit); + } + + return $qb->getQuery()->getResult(); + } + + public function buildQueryByUser(User $user): QueryBuilder + { + $qb = $this->em->createQueryBuilder() + ->from(Invite::class, 'i'); + + $qb->where('i.user = :user'); + + $qb->setParameter('user', $user); + + return $qb; + } +} diff --git a/src/Bundle/ChillCalendarBundle/Repository/InviteACLAwareRepositoryInterface.php b/src/Bundle/ChillCalendarBundle/Repository/InviteACLAwareRepositoryInterface.php new file mode 100644 index 000000000..c388b0c03 --- /dev/null +++ b/src/Bundle/ChillCalendarBundle/Repository/InviteACLAwareRepositoryInterface.php @@ -0,0 +1,21 @@ + 0 %} +
+ + {% for invitation in invitations %} + {% set calendar = invitation.getCalendar %} + + {% if calendar is not null %} +
+
+
+
+
+
+

+ {% if calendar.endDate.diff(calendar.startDate).days >= 1 %} + {{ calendar.startDate|format_datetime('short', 'short') }} + - {{ calendar.endDate|format_datetime('short', 'short') }} + {% else %} + {{ calendar.startDate|format_datetime('short', 'short') }} + - {{ calendar.endDate|format_datetime('none', 'short') }} + {% endif %} +

+ +
+ + {{ calendar.duration|date('%H:%I') }} + {% if false == calendar.sendSMS or null == calendar.sendSMS %} + + {% else %} + {% if calendar.smsStatus == 'sms_sent' %} + + + + + {% else %} + + + + + {% endif %} + {% endif %} +
+ +
+
+
+ +
+
    + {% if calendar.mainUser is not empty %} + {{ calendar.mainUser|chill_entity_render_box({'at_date': calendar.startDate}) }} + {% endif %} +
+
+ +
+
+ + {% if calendar.comment.comment is not empty + or calendar.users|length > 0 + or calendar.thirdParties|length > 0 + or calendar.users|length > 0 %} +
+
+ {% include '@ChillActivity/Activity/concernedGroups.html.twig' with { + 'context': calendar.context == 'person' ? 'calendar_person' : 'calendar_accompanyingCourse', + 'render': 'wrap-list', + 'entity': calendar + } %} +
+ +
+ {% endif %} + + {% if calendar.comment.comment is not empty %} +
+
+ {{ calendar.comment|chill_entity_render_box( { 'limit_lines': 3, 'metadata': false } ) }} +
+
+ {% endif %} + + {% if calendar.location is not empty %} +
+
+ {% if calendar.location.address is not same as(null) and calendar.location.name is not empty %} + {% endif %} + {% if calendar.location.name is not empty %}{{ calendar.location.name }}{% endif %} + {% if calendar.location.address is not same as(null) %}{{ calendar.location.address|chill_entity_render_box({'multiline': false, 'with_picto': (calendar.location.name is empty)}) }}{% else %} + {% endif %} + {% if calendar.location.phonenumber1 is not empty %} {{ calendar.location.phonenumber1|chill_format_phonenumber }}{% endif %} + {% if calendar.location.phonenumber2 is not empty %} {{ calendar.location.phonenumber2|chill_format_phonenumber }}{% endif %} +
+
+ {% endif %} + +
+
+ + {{ include('@ChillCalendar/Calendar/_documents.twig.html') }} +
+
+ + {% if calendar.activity is not null %} +
+
+
+
+

{{ 'Activity'|trans }}

+
+

+ + + {{ calendar.activity.type.name | localize_translatable_string }} + + {% if calendar.activity.emergency %} + {{ 'Emergency'|trans|upper }} + {% endif %} + +

+ +
    +
  • + + {{ 'Created by'|trans }} + {{ calendar.activity.createdBy|chill_entity_render_string({'at_date': calendar.activity.createdAt}) }}, {{ 'on'|trans }} {{ calendar.activity.createdAt|format_datetime('short', 'short') }} + +
  • + {% if is_granted('CHILL_ACTIVITY_SEE', calendar.activity) %} +
  • + +
  • + {% endif %} +
+ +
+
+
+
+
+ {% endif %} + +
+
    + + {% if (calendar.isInvited(app.user)) %} + {% set invite = calendar.inviteForUser(app.user) %} +
  • +
    +
  • + {% endif %} +
  • + +
  • +
+ +
+ +
+ {% endif %} + {% endfor %} + + {% if invitations|length < paginator.getTotalItems %} + {{ chill_pagination(paginator) }} + {% endif %} + +
+{% endif %} diff --git a/src/Bundle/ChillCalendarBundle/Resources/views/Invitations/listByUser.html.twig b/src/Bundle/ChillCalendarBundle/Resources/views/Invitations/listByUser.html.twig new file mode 100644 index 000000000..22ca9d7a8 --- /dev/null +++ b/src/Bundle/ChillCalendarBundle/Resources/views/Invitations/listByUser.html.twig @@ -0,0 +1,27 @@ +{% extends "@ChillMain/layout.html.twig" %} + +{% set activeRouteKey = 'chill_calendar_invitations_list' %} + +{% block title %}{{ 'My invitations list' |trans }}{% endblock title %} + +{% block content %} + +

{{ 'Invitation list' |trans }}

+ + {% if invitations|length == 0 %} +

+ {{ "There is no invitation items."|trans }} +

+ {% else %} + {{ include ('@ChillCalendar/Invitations/_list_item.html.twig') }} + {% endif %} + +{% endblock %} + +{% block js %} + {{ parent() }} +{% endblock %} + +{% block css %} + {{ parent() }} +{% endblock %}