From 2de9ba5832d058bea58e73badbc763ba7f58747d Mon Sep 17 00:00:00 2001 From: christianbeeznst Date: Sun, 24 Mar 2024 17:34:06 -0500 Subject: [PATCH] Platform: Improve event management by type in calendar - refs #5270 --- .../ccalendarevent/CCalendarEventList.vue | 57 ++++++++++++++++--- src/CoreBundle/ApiResource/CalendarEvent.php | 13 +++++ .../Extension/CCalendarEventExtension.php | 9 ++- .../CalendarEventTransformer.php | 8 ++- src/CoreBundle/Filter/GlobalEventFilter.php | 37 ++++-------- .../Repository/CCalendarEventRepository.php | 32 +++++++++++ 6 files changed, 117 insertions(+), 39 deletions(-) diff --git a/assets/vue/views/ccalendarevent/CCalendarEventList.vue b/assets/vue/views/ccalendarevent/CCalendarEventList.vue index 0499f88590..408fe2b736 100644 --- a/assets/vue/views/ccalendarevent/CCalendarEventList.vue +++ b/assets/vue/views/ccalendarevent/CCalendarEventList.vue @@ -1,10 +1,10 @@ @@ -213,11 +214,23 @@ async function getCalendarEvents({ startStr, endStr }) { const calendarEvents = await cCalendarEventService.findAll({ params }).then((response) => response.json()) - return calendarEvents["hydra:member"].map((event) => ({ - ...event, - start: event.startDate, - end: event.endDate, - })) + return calendarEvents["hydra:member"].map((event) => { + let color = '#007BFF' + if (event.type === 'global') { + color = '#FF0000' + } else if (event.type === 'course') { + color = '#28a745' + } else if (event.type === 'session') { + color = '#800080' + } + + return { + ...event, + start: event.startDate, + end: event.endDate, + color, + } + }) } const calendarLocale = allLocales.find( @@ -299,6 +312,32 @@ const calendarOptions = ref({ }, }) +const currentContext = computed(() => { + if (route.query.type === 'global') { + return 'global' + } else if (course.value) { + return 'course' + } else if (session.value) { + return 'session' + } else { + return 'personal' + } +}); + +const allowAction = (eventType) => { + const contextRules = { + global: ['global'], + course: ['course'], + session: ['session'], + personal: ['personal'] + }; + + return contextRules[currentContext.value].includes(eventType); +}; + +const showEditButton = computed(() => allowAction(item.value.type)); +const showDeleteButton = computed(() => allowAction(item.value.type)); + const cal = ref(null) function reFetch() { diff --git a/src/CoreBundle/ApiResource/CalendarEvent.php b/src/CoreBundle/ApiResource/CalendarEvent.php index 0d235f2e98..189e5f2ad6 100644 --- a/src/CoreBundle/ApiResource/CalendarEvent.php +++ b/src/CoreBundle/ApiResource/CalendarEvent.php @@ -43,7 +43,20 @@ class CalendarEvent extends AbstractResource #[Groups(['calendar_event:read'])] public ?ResourceNode $resourceNode = null, ?array $resourceLinkListFromEntity = null, + #[Groups(['calendar_event:read'])] + public ?string $type = null, ) { $this->resourceLinkListFromEntity = $resourceLinkListFromEntity; } + + public function getType(): ?string + { + return $this->type; + } + + public function setType(?string $type): self + { + $this->type = $type; + return $this; + } } diff --git a/src/CoreBundle/DataProvider/Extension/CCalendarEventExtension.php b/src/CoreBundle/DataProvider/Extension/CCalendarEventExtension.php index 12bce35c2c..64541fbbda 100644 --- a/src/CoreBundle/DataProvider/Extension/CCalendarEventExtension.php +++ b/src/CoreBundle/DataProvider/Extension/CCalendarEventExtension.php @@ -35,15 +35,20 @@ final class CCalendarEventExtension implements QueryCollectionExtensionInterface ?Operation $operation = null, array $context = [] ): void { - $this->addWhere($queryBuilder, $resourceClass); + $this->addWhere($queryBuilder, $resourceClass, $context); } - private function addWhere(QueryBuilder $qb, string $resourceClass): void + private function addWhere(QueryBuilder $qb, string $resourceClass, array $context): void { if (CCalendarEvent::class !== $resourceClass) { return; } + $isGlobalType = isset($context['filters']['type']) && $context['filters']['type'] === 'global'; + if ($isGlobalType) { + return; + } + $courseId = $this->cidReqHelper->getCourseId(); $sessionId = $this->cidReqHelper->getSessionId(); $groupId = $this->cidReqHelper->getGroupId(); diff --git a/src/CoreBundle/DataTransformer/CalendarEventTransformer.php b/src/CoreBundle/DataTransformer/CalendarEventTransformer.php index e6145cf33c..2daf88edfe 100644 --- a/src/CoreBundle/DataTransformer/CalendarEventTransformer.php +++ b/src/CoreBundle/DataTransformer/CalendarEventTransformer.php @@ -12,6 +12,7 @@ use Chamilo\CoreBundle\Entity\Session; use Chamilo\CoreBundle\Entity\SessionRelCourse; use Chamilo\CoreBundle\Repository\Node\UsergroupRepository; use Chamilo\CourseBundle\Entity\CCalendarEvent; +use Chamilo\CourseBundle\Repository\CCalendarEventRepository; use Symfony\Component\Routing\Generator\UrlGeneratorInterface; use Symfony\Component\Routing\RouterInterface; @@ -20,6 +21,7 @@ class CalendarEventTransformer implements DataTransformerInterface public function __construct( private readonly RouterInterface $router, private readonly UsergroupRepository $usergroupRepository, + private readonly CCalendarEventRepository $calendarEventRepository ) {} public function transform($object, string $to, array $context = []): object @@ -48,7 +50,8 @@ class CalendarEventTransformer implements DataTransformerInterface $subscriptionItemTitle = $this->usergroupRepository->find($object->getSubscriptionItemId())?->getTitle(); } - return new CalendarEvent( + $eventType = $this->calendarEventRepository->determineEventType($object); + $calendarEvent = new CalendarEvent( 'calendar_event_'.$object->getIid(), $object->getTitle(), $object->getContent(), @@ -65,6 +68,9 @@ class CalendarEventTransformer implements DataTransformerInterface $object->getResourceNode(), $object->getResourceLinkListFromEntity(), ); + $calendarEvent->setType($eventType); + + return $calendarEvent; } private function mapSessionToDto(object $object): CalendarEvent diff --git a/src/CoreBundle/Filter/GlobalEventFilter.php b/src/CoreBundle/Filter/GlobalEventFilter.php index 5171f70f8a..b2454ec01c 100644 --- a/src/CoreBundle/Filter/GlobalEventFilter.php +++ b/src/CoreBundle/Filter/GlobalEventFilter.php @@ -35,37 +35,20 @@ class GlobalEventFilter extends AbstractFilter array $context = [] ): void { $isGlobalType = isset($context['filters']['type']) && $context['filters']['type'] === 'global'; + if (!$isGlobalType) { + return; + } $rootAlias = $queryBuilder->getRootAliases()[0]; $resourceNodeAlias = $queryNameGenerator->generateJoinAlias('resourceNode'); $resourceLinkAlias = $queryNameGenerator->generateJoinAlias('resourceLink'); - if ($isGlobalType) { - $queryBuilder - ->innerJoin("$rootAlias.resourceNode", $resourceNodeAlias) - ->innerJoin("$resourceNodeAlias.resourceLinks", $resourceLinkAlias) - ->andWhere("$resourceLinkAlias.course IS NULL") - ->andWhere("$resourceLinkAlias.session IS NULL") - ->andWhere("$resourceLinkAlias.group IS NULL") - ->andWhere("$resourceLinkAlias.user IS NULL"); - - return; - } - - if (!$isGlobalType) { - $subQueryBuilder = $queryBuilder->getEntityManager()->createQueryBuilder(); - $subRN = $queryNameGenerator->generateJoinAlias('subResourceNode'); - $subRL = $queryNameGenerator->generateJoinAlias('subResourceLink'); - $subQueryBuilder->select('1') - ->from(ResourceNode::class, $subRN) - ->innerJoin("$subRN.resourceLinks", $subRL) - ->where("$subRL.course IS NULL") - ->andWhere("$subRL.session IS NULL") - ->andWhere("$subRL.group IS NULL") - ->andWhere("$subRL.user IS NULL") - ->andWhere("$subRN.id = $rootAlias.resourceNode"); - - $queryBuilder->andWhere($queryBuilder->expr()->not($queryBuilder->expr()->exists($subQueryBuilder->getDQL()))); - } + $queryBuilder + ->innerJoin("$rootAlias.resourceNode", $resourceNodeAlias) + ->innerJoin("$resourceNodeAlias.resourceLinks", $resourceLinkAlias) + ->andWhere("$resourceLinkAlias.course IS NULL") + ->andWhere("$resourceLinkAlias.session IS NULL") + ->andWhere("$resourceLinkAlias.group IS NULL") + ->andWhere("$resourceLinkAlias.user IS NULL"); } public function getDescription(string $resourceClass): array diff --git a/src/CourseBundle/Repository/CCalendarEventRepository.php b/src/CourseBundle/Repository/CCalendarEventRepository.php index 47970cf9f8..fa8aa38e6f 100644 --- a/src/CourseBundle/Repository/CCalendarEventRepository.php +++ b/src/CourseBundle/Repository/CCalendarEventRepository.php @@ -8,6 +8,7 @@ namespace Chamilo\CourseBundle\Repository; use Chamilo\CoreBundle\Entity\AbstractResource; use Chamilo\CoreBundle\Entity\Course; +use Chamilo\CoreBundle\Entity\ResourceLink; use Chamilo\CoreBundle\Entity\Session; use Chamilo\CoreBundle\Entity\User; use Chamilo\CoreBundle\Repository\ResourceRepository; @@ -76,4 +77,35 @@ final class CCalendarEventRepository extends ResourceRepository return $event; } + + public function determineEventType(CCalendarEvent $event): string + { + $em = $this->getEntityManager(); + $queryBuilder = $em->createQueryBuilder(); + + $queryBuilder + ->select('rl') + ->from(ResourceLink::class, 'rl') + ->innerJoin('rl.resourceNode', 'rn') + ->where('rn.id = :resourceNodeId') + ->setParameter('resourceNodeId', $event->getResourceNode()->getId()); + + $resourceLinks = $queryBuilder->getQuery()->getResult(); + + foreach ($resourceLinks as $link) { + if (null === $link->getCourse() && null === $link->getSession() && null === $link->getGroup() && null === $link->getUser()) { + return 'global'; + } + + if (null !== $link->getCourse()) { + return 'course'; + } + + if (null !== $link->getSession()) { + return 'session'; + } + } + + return 'personal'; + } }