mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-09-10 16:55:00 +00:00
Compare commits
11 Commits
389-displa
...
issue719_f
Author | SHA1 | Date | |
---|---|---|---|
0b7651f519 | |||
033e1f9aa1 | |||
08df1c4ac8 | |||
8d6cd0cf63 | |||
f762f35386 | |||
3cc56e7431 | |||
243e148c00 | |||
382d3ddd42 | |||
7fd823f1ee | |||
1c80e0b5f5 | |||
3923a13b30 |
@@ -13,6 +13,7 @@ namespace Chill\ActivityBundle\Controller;
|
||||
|
||||
use Chill\ActivityBundle\Entity\Activity;
|
||||
use Chill\ActivityBundle\Entity\ActivityReason;
|
||||
use Chill\ActivityBundle\Form\ActivityFilterType;
|
||||
use Chill\ActivityBundle\Form\ActivityType;
|
||||
use Chill\ActivityBundle\Repository\ActivityACLAwareRepositoryInterface;
|
||||
use Chill\ActivityBundle\Repository\ActivityRepository;
|
||||
@@ -294,6 +295,10 @@ final class ActivityController extends AbstractController
|
||||
|
||||
[$person, $accompanyingPeriod] = $this->getEntity($request);
|
||||
|
||||
$form = $this->createForm(ActivityFilterType::class);
|
||||
|
||||
$form->handleRequest($request);
|
||||
|
||||
if ($person instanceof Person) {
|
||||
$this->denyAccessUnlessGranted(ActivityVoter::SEE, $person);
|
||||
$activities = $this->activityACLAwareRepository
|
||||
@@ -309,15 +314,43 @@ final class ActivityController extends AbstractController
|
||||
} elseif ($accompanyingPeriod instanceof AccompanyingPeriod) {
|
||||
$this->denyAccessUnlessGranted(ActivityVoter::SEE, $accompanyingPeriod);
|
||||
|
||||
$activities = $this->activityACLAwareRepository
|
||||
->findByAccompanyingPeriod($accompanyingPeriod, ActivityVoter::SEE, 0, null, ['date' => 'DESC', 'id' => 'DESC']);
|
||||
|
||||
$view = 'ChillActivityBundle:Activity:listAccompanyingCourse.html.twig';
|
||||
if ($form->isSubmitted() && $form->isValid()) {
|
||||
$data = $form->getData();
|
||||
$activities = $this->activityACLAwareRepository
|
||||
->findByAccompanyingPeriod(
|
||||
$accompanyingPeriod,
|
||||
ActivityVoter::SEE,
|
||||
0,
|
||||
$data['dateTo'],
|
||||
$data['dateFrom'],
|
||||
$data['jobs']->getValues(),
|
||||
$data['types']->getValues(),
|
||||
$data['onlyMe'],
|
||||
null,
|
||||
['date' => 'DESC', 'id' => 'DESC']
|
||||
);
|
||||
} else {
|
||||
$activities = $this->activityACLAwareRepository
|
||||
->findByAccompanyingPeriod(
|
||||
$accompanyingPeriod,
|
||||
ActivityVoter::SEE,
|
||||
0,
|
||||
null,
|
||||
null,
|
||||
[],
|
||||
[],
|
||||
false,
|
||||
null,
|
||||
['date' => 'DESC', 'id' => 'DESC']
|
||||
);
|
||||
}
|
||||
}
|
||||
$view = 'ChillActivityBundle:Activity:listAccompanyingCourse.html.twig';
|
||||
|
||||
return $this->render(
|
||||
$view,
|
||||
[
|
||||
'form' => $form->createView(),
|
||||
'activities' => $activities,
|
||||
'person' => $person,
|
||||
'accompanyingCourse' => $accompanyingPeriod,
|
||||
|
107
src/Bundle/ChillActivityBundle/Form/ActivityFilterType.php
Normal file
107
src/Bundle/ChillActivityBundle/Form/ActivityFilterType.php
Normal file
@@ -0,0 +1,107 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\ActivityBundle\Form;
|
||||
|
||||
use Chill\MainBundle\Entity\UserJob;
|
||||
use Chill\MainBundle\Form\Type\ChillDateType;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
|
||||
use Doctrine\ORM\EntityRepository;
|
||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Form\FormError;
|
||||
use Symfony\Component\Form\FormEvent;
|
||||
use Symfony\Component\Form\FormEvents;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
use Chill\ActivityBundle\Entity\ActivityType;
|
||||
|
||||
class ActivityFilterType extends AbstractType
|
||||
{
|
||||
private TranslatableStringHelperInterface $translatableString;
|
||||
|
||||
protected TranslatorInterface $translator;
|
||||
|
||||
public function __construct(TranslatableStringHelperInterface $translatableString, TranslatorInterface $translator)
|
||||
{
|
||||
$this->translatableString = $translatableString;
|
||||
|
||||
$this->translator = $translator;
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder, array $options): void
|
||||
{
|
||||
|
||||
$builder
|
||||
->add('types', EntityType::class, [
|
||||
'class' => ActivityType::class,
|
||||
'label' => 'Activity type',
|
||||
'multiple' => true,
|
||||
'query_builder' => static function (EntityRepository $er) {
|
||||
$qb = $er->createQueryBuilder('t');
|
||||
$qb->andWhere($qb->expr()->eq('t.active', "'TRUE'"));
|
||||
|
||||
return $qb;
|
||||
},
|
||||
'choice_label' => function (ActivityType $t) {
|
||||
return $this->translatableString->localize($t->getName());
|
||||
},
|
||||
'required' => false,
|
||||
])
|
||||
->add('jobs', EntityType::class, [
|
||||
'class' => UserJob::class,
|
||||
'label' => 'user job',
|
||||
'multiple' => true,
|
||||
'query_builder' => static function (EntityRepository $er) {
|
||||
$qb = $er->createQueryBuilder('j');
|
||||
$qb->andWhere($qb->expr()->eq('j.active', "'TRUE'"));
|
||||
|
||||
return $qb;
|
||||
},
|
||||
'choice_label' => function (UserJob $j) {
|
||||
return $this->translatableString->localize($j->getLabel());
|
||||
},
|
||||
'required' => false,
|
||||
])
|
||||
->add('dateFrom', ChillDateType::class, [
|
||||
'label' => 'Activities after this date',
|
||||
'required' => false,
|
||||
])
|
||||
->add('dateTo', ChillDateType::class, [
|
||||
'label' => 'Activities before this date',
|
||||
'required' => false,
|
||||
])
|
||||
->add('onlyMe', CheckboxType::class, [
|
||||
'label' => 'My activities only',
|
||||
'required' => false,
|
||||
]);
|
||||
|
||||
$builder->addEventListener(FormEvents::POST_SUBMIT, function (FormEvent $event) {
|
||||
|
||||
$form = $event->getForm();
|
||||
$dateFrom = $form->get('dateFrom')->getData();
|
||||
$dateTo = $form->get('dateTo')->getData();
|
||||
|
||||
// check that date_from is before date_to
|
||||
if (
|
||||
(null !== $dateFrom && null !== $dateTo)
|
||||
&& $dateFrom >= $dateTo
|
||||
) {
|
||||
$form->get('dateTo')->addError(new FormError(
|
||||
$this->translator->trans('This date should be after '
|
||||
. 'the date given in "Implied in an activity after '
|
||||
. 'this date" field')
|
||||
));
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
public function configureOptions(OptionsResolver $resolver): void
|
||||
{
|
||||
$resolver->setDefaults([
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
@@ -22,14 +22,15 @@ use Chill\MainBundle\Security\Authorization\AuthorizationHelper;
|
||||
use Chill\MainBundle\Security\Resolver\CenterResolverDispatcherInterface;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod;
|
||||
use Chill\PersonBundle\Entity\Person;
|
||||
use DateTime;
|
||||
use Doctrine\DBAL\Types\Types;
|
||||
use Doctrine\ORM\AbstractQuery;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Doctrine\ORM\Query\ResultSetMappingBuilder;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
|
||||
|
||||
use Symfony\Component\Security\Core\Role\Role;
|
||||
use Symfony\Component\Security\Core\Security;
|
||||
|
||||
use function count;
|
||||
use function in_array;
|
||||
|
||||
@@ -63,21 +64,31 @@ final class ActivityACLAwareRepository implements ActivityACLAwareRepositoryInte
|
||||
$this->security = $security;
|
||||
}
|
||||
|
||||
public function findByAccompanyingPeriod(AccompanyingPeriod $period, string $role, ?int $start = 0, ?int $limit = 1000, ?array $orderBy = []): array
|
||||
{
|
||||
$user = $this->security->getUser();
|
||||
$center = $this->centerResolverDispatcher->resolveCenter($period);
|
||||
/* public function findByAccompanyingPeriod(
|
||||
AccompanyingPeriod $period,
|
||||
string $role,
|
||||
?int $start = 0,
|
||||
?DateTime $before = null,
|
||||
?DateTime $after = null,
|
||||
?array $userJob = [],
|
||||
?array $activityTypes = [],
|
||||
bool $onlyMe = false,
|
||||
?int $limit = 1000,
|
||||
?array $orderBy = []
|
||||
): array {
|
||||
$user = $this->security->getUser();
|
||||
$center = $this->centerResolverDispatcher->resolveCenter($period);
|
||||
|
||||
if (0 === count($orderBy)) {
|
||||
$orderBy = ['date' => 'DESC'];
|
||||
}
|
||||
if (0 === count($orderBy)) {
|
||||
$orderBy = ['date' => 'DESC'];
|
||||
}
|
||||
|
||||
$scopes = $this->authorizationHelper
|
||||
->getReachableCircles($user, $role, $center);
|
||||
$scopes = $this->authorizationHelper
|
||||
->getReachableCircles($user, $role, $center);
|
||||
|
||||
return $this->em->getRepository(Activity::class)
|
||||
->findByAccompanyingPeriod($period, $scopes, true, $limit, $start, $orderBy);
|
||||
}
|
||||
return $this->em->getRepository(Activity::class)
|
||||
->findByAccompanyingPeriod($period, $scopes, true, $before, $after, $userJob, $activityTypes, $onlyMe, $limit, $start, $orderBy);
|
||||
}*/
|
||||
|
||||
public function findByAccompanyingPeriodSimplified(AccompanyingPeriod $period, ?int $limit = 1000): array
|
||||
{
|
||||
@@ -199,6 +210,62 @@ final class ActivityACLAwareRepository implements ActivityACLAwareRepositoryInte
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Activity[]
|
||||
*/
|
||||
private function findByAccompanyingPeriod(
|
||||
AccompanyingPeriod $period,
|
||||
string $role,
|
||||
?int $start = 0,
|
||||
?DateTime $before = null,
|
||||
?DateTime $after = null,
|
||||
?array $userJob = [],
|
||||
?array $activityTypes = [],
|
||||
bool $onlyMe = false,
|
||||
?int $limit = 100,
|
||||
?int $offset = 0,
|
||||
?array $orderBy = ['date' => 'desc']
|
||||
): array {
|
||||
$qb = $this->createQueryBuilder('a');
|
||||
$qb->select('a');
|
||||
|
||||
$user = $this->security->getUser();
|
||||
$center = $this->centerResolverDispatcher->resolveCenter($period);
|
||||
|
||||
if (0 === count($orderBy)) {
|
||||
$orderBy = ['date' => 'DESC'];
|
||||
}
|
||||
|
||||
$scopes = $this->authorizationHelper
|
||||
->getReachableCircles($user, $role, $center);
|
||||
|
||||
$qb
|
||||
->where(
|
||||
$qb->expr()->orX(
|
||||
$qb->expr()->in('a.scope', ':scopes'),
|
||||
$qb->expr()->isNull('a.scope')
|
||||
)
|
||||
)
|
||||
->setParameter('scopes', $scopes);
|
||||
|
||||
$qb
|
||||
->andWhere(
|
||||
$qb->expr()->eq('a.accompanyingPeriod', ':period')
|
||||
)
|
||||
->setParameter('period', $period);
|
||||
|
||||
//Add filter queries
|
||||
$this->repository->addQueryFilters($qb, $userJob, $activityTypes, $after, $before, $onlyMe);
|
||||
|
||||
foreach ($orderBy as $k => $dir) {
|
||||
$qb->addOrderBy('a.' . $k, $dir);
|
||||
}
|
||||
|
||||
$qb->setMaxResults($limit)->setFirstResult($offset);
|
||||
|
||||
return $qb->getQuery()->getResult();
|
||||
}
|
||||
|
||||
private function getFromClauseCenter(array $args): string
|
||||
{
|
||||
$metadataActivity = $this->em->getClassMetadata(Activity::class);
|
||||
|
@@ -11,15 +11,29 @@ declare(strict_types=1);
|
||||
|
||||
namespace Chill\ActivityBundle\Repository;
|
||||
|
||||
use Chill\ActivityBundle\Entity\Activity;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod;
|
||||
use Chill\PersonBundle\Entity\Person;
|
||||
use DateTime;
|
||||
|
||||
interface ActivityACLAwareRepositoryInterface
|
||||
{
|
||||
/**
|
||||
* @return Activity[]|array
|
||||
*/
|
||||
public function findByAccompanyingPeriod(AccompanyingPeriod $period, string $role, ?int $start = 0, ?int $limit = 1000, ?array $orderBy = []): array;
|
||||
public function findByAccompanyingPeriod(
|
||||
AccompanyingPeriod $period,
|
||||
string $role,
|
||||
?int $start = 0,
|
||||
?DateTime $before = null,
|
||||
?DateTime $after = null,
|
||||
?array $userJob = [],
|
||||
?array $activityTypes = [],
|
||||
bool $onlyMe = false,
|
||||
?int $limit = 1000,
|
||||
?int $offset = 0,
|
||||
?array $orderBy = []
|
||||
): array;
|
||||
|
||||
/**
|
||||
* Return a list of activities, simplified as array (not object).
|
||||
|
@@ -12,10 +12,16 @@ declare(strict_types=1);
|
||||
namespace Chill\ActivityBundle\Repository;
|
||||
|
||||
use Chill\ActivityBundle\Entity\Activity;
|
||||
use Chill\ActivityBundle\Entity\ActivityType;
|
||||
use Chill\MainBundle\Entity\UserJob;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod;
|
||||
use Chill\PersonBundle\Entity\Person;
|
||||
use DateTime;
|
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
use Symfony\Component\Security\Core\Security;
|
||||
use function count;
|
||||
|
||||
/**
|
||||
* @method Activity|null find($id, $lockMode = null, $lockVersion = null)
|
||||
@@ -25,9 +31,58 @@ use Doctrine\Persistence\ManagerRegistry;
|
||||
*/
|
||||
class ActivityRepository extends ServiceEntityRepository
|
||||
{
|
||||
public function __construct(ManagerRegistry $registry)
|
||||
private Security $security;
|
||||
|
||||
public function __construct(ManagerRegistry $registry, Security $security)
|
||||
{
|
||||
parent::__construct($registry, Activity::class);
|
||||
$this->security = $security;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array|UserJob $jobs
|
||||
* @param array|ActivityType $types
|
||||
* @param DateTime $dateFrom
|
||||
* @param DateTime $dateTo
|
||||
*/
|
||||
public function addQueryFilters(QueryBuilder $qb, array $jobs, array $types, ?DateTime $dateFrom, ?DateTime $dateTo, bool $onlyMe): QueryBuilder
|
||||
{
|
||||
if (0 < count($jobs)) {
|
||||
//TODO check for jobs of all users involved
|
||||
$qb->innerJoin('a.user', 'u');
|
||||
$qb->andWhere($qb->expr()->in('u.userJob', ':jobs'))
|
||||
->setParameter('jobs', $jobs);
|
||||
}
|
||||
|
||||
if (0 < count($types)) {
|
||||
$qb->andWhere($qb->expr()->in('a.activityType', ':types'))
|
||||
->setParameter('types', $types);
|
||||
}
|
||||
|
||||
if (null !== $dateFrom && null !== $dateTo) {
|
||||
$qb->andWhere($qb->expr()->between(
|
||||
'a.date',
|
||||
':date_from',
|
||||
':date_to'
|
||||
))
|
||||
->setParameter('date_from', $dateFrom)
|
||||
->setParameter('date_to', $dateTo);
|
||||
} elseif (null !== $dateFrom && null === $dateTo) {
|
||||
$qb->andWhere($qb->expr()->gt('a.date', ':date_from'))
|
||||
->setParameter('date_from', $dateFrom);
|
||||
} elseif (null === $dateFrom && null !== $dateTo) {
|
||||
$qb->andWhere($qb->expr()->lt('a.date', ':date_to'))
|
||||
->setParameter('date_to', $dateTo);
|
||||
}
|
||||
|
||||
if (true === $onlyMe) {
|
||||
$currentUser = $this->security->getUser();
|
||||
|
||||
$qb->andWhere($qb->expr()->eq('a.user', ':currentUser'))
|
||||
->setParameter('currentUser', $currentUser);
|
||||
}
|
||||
|
||||
return $qb;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -35,8 +90,19 @@ class ActivityRepository extends ServiceEntityRepository
|
||||
*
|
||||
* @return Activity[]
|
||||
*/
|
||||
public function findByAccompanyingPeriod(AccompanyingPeriod $period, array $scopes, ?bool $allowNullScope = false, ?int $limit = 100, ?int $offset = 0, array $orderBy = ['date' => 'desc']): array
|
||||
{
|
||||
public function findByAccompanyingPeriod(
|
||||
AccompanyingPeriod $period,
|
||||
array $scopes,
|
||||
?bool $allowNullScope = false,
|
||||
?DateTime $before = null,
|
||||
?DateTime $after = null,
|
||||
?array $userJob = [],
|
||||
array $activityTypes = [],
|
||||
bool $onlyMe = false,
|
||||
?int $limit = 100,
|
||||
?int $offset = 0,
|
||||
array $orderBy = ['date' => 'desc']
|
||||
): array {
|
||||
$qb = $this->createQueryBuilder('a');
|
||||
$qb->select('a');
|
||||
|
||||
@@ -61,6 +127,9 @@ class ActivityRepository extends ServiceEntityRepository
|
||||
)
|
||||
->setParameter('period', $period);
|
||||
|
||||
//Add filter queries
|
||||
$this->addQueryFilters($qb, $userJob, $activityTypes, $after, $before, $onlyMe);
|
||||
|
||||
foreach ($orderBy as $k => $dir) {
|
||||
$qb->addOrderBy('a.' . $k, $dir);
|
||||
}
|
||||
|
@@ -27,7 +27,49 @@
|
||||
{% set accompanying_course_id = accompanyingCourse.id %}
|
||||
{% endif %}
|
||||
|
||||
<h1>{{ 'Activity list' |trans }}</h1>
|
||||
<h1>{{ 'Activity list'|trans }}</h1>
|
||||
|
||||
{# TODO: form error messages not displaying #}
|
||||
<p>{{ form_errors(form) }}</p>
|
||||
|
||||
{{ form_start(form) }}
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
{{ form_label(form.types ) }}
|
||||
{{ form_widget(form.types, {'attr': {'class': 'select2'}}) }}
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
{{ form_label(form.jobs) }}
|
||||
{{ form_widget(form.jobs, {'attr': {'class': 'select2'}}) }}
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
{{ form_label(form.dateFrom) }}
|
||||
{{ form_widget(form.dateFrom) }}
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
{{ form_label(form.dateTo) }}
|
||||
{{ form_widget(form.dateTo) }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
{{ form_label(form.onlyMe) }}
|
||||
{{ form_widget(form.onlyMe) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ul class="record_actions">
|
||||
<li>
|
||||
<button type="submit" class="btn btn-save change-icon">
|
||||
<i class="fa fa-filter"></i> Filtrer
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
{{ form_end(form) }}
|
||||
{# </div>#}
|
||||
|
||||
{% include 'ChillActivityBundle:Activity:list.html.twig' with {'context': 'accompanyingCourse'} %}
|
||||
|
||||
|
@@ -1,5 +1,8 @@
|
||||
---
|
||||
services:
|
||||
Chill\ActivityBundle\Form\ActivityFilterType:
|
||||
autowire: true
|
||||
autoconfigure: true
|
||||
Chill\ActivityBundle\Form\Type\TranslatableActivityReasonCategoryType:
|
||||
autowire: true
|
||||
autoconfigure: true
|
||||
|
@@ -284,6 +284,8 @@ Filter acp which has no activity: Filtrer les parcours qui n’ont pas d’activ
|
||||
Filtered acp which has no activities: Filtrer les parcours sans activité associée
|
||||
Group acp by activity number: Grouper les parcours par nombre d’activité
|
||||
|
||||
My activities only: Mes échanges uniquement
|
||||
|
||||
#aggregators
|
||||
Activity type: Type d'activité
|
||||
Activity user: Utilisateur lié à l'activité
|
||||
|
Reference in New Issue
Block a user