mirror of
				https://gitlab.com/Chill-Projet/chill-bundles.git
				synced 2025-11-04 03:08:25 +00:00 
			
		
		
		
	Merge branch 'user_filter_tasks' into 'master'
Filter on user within task list See merge request Chill-Projet/chill-bundles!569
This commit is contained in:
		
							
								
								
									
										5
									
								
								.changes/unreleased/Feature-20230705-140336.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								.changes/unreleased/Feature-20230705-140336.yaml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
			
		||||
kind: Feature
 | 
			
		||||
body: Allow filtering on the basis of a user within general tasks list
 | 
			
		||||
time: 2023-07-05T14:03:36.664880092+02:00
 | 
			
		||||
custom:
 | 
			
		||||
  Issue: ""
 | 
			
		||||
@@ -12,6 +12,7 @@ declare(strict_types=1);
 | 
			
		||||
namespace Chill\MainBundle\Form\Type\Listing;
 | 
			
		||||
 | 
			
		||||
use Chill\MainBundle\Form\Type\ChillDateType;
 | 
			
		||||
use Chill\MainBundle\Form\Type\PickUserDynamicType;
 | 
			
		||||
use Chill\MainBundle\Templating\Listing\FilterOrderHelper;
 | 
			
		||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
 | 
			
		||||
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
 | 
			
		||||
@@ -114,6 +115,28 @@ final class FilterOrderType extends \Symfony\Component\Form\AbstractType
 | 
			
		||||
 | 
			
		||||
            $builder->add($singleCheckBoxBuilder);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if ([] !== $helper->getUserPickers()) {
 | 
			
		||||
            $userPickersBuilder = $builder->create('user_pickers', null, ['compound' => true]);
 | 
			
		||||
 | 
			
		||||
            foreach ($helper->getUserPickers() as $name => [
 | 
			
		||||
                'label' => $label, 'options' => $opts
 | 
			
		||||
            ]) {
 | 
			
		||||
 | 
			
		||||
                $userPickersBuilder->add(
 | 
			
		||||
                    $name,
 | 
			
		||||
                    PickUserDynamicType::class,
 | 
			
		||||
                    [
 | 
			
		||||
                        'multiple' => true,
 | 
			
		||||
                        'label' => $label,
 | 
			
		||||
                        ...$opts,
 | 
			
		||||
                    ]
 | 
			
		||||
                );
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            $builder->add($userPickersBuilder);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static function buildCheckboxChoices(array $choices, array $trans = []): array
 | 
			
		||||
 
 | 
			
		||||
@@ -18,6 +18,7 @@
 | 
			
		||||
                    </div>
 | 
			
		||||
                {% endif %}
 | 
			
		||||
            </div>
 | 
			
		||||
 | 
			
		||||
            {% if form.dateRanges is defined %}
 | 
			
		||||
                {% set btnSubmit = 1 %}
 | 
			
		||||
                {% if form.dateRanges|length > 0 %}
 | 
			
		||||
@@ -40,6 +41,7 @@
 | 
			
		||||
                    {% endfor %}
 | 
			
		||||
                {% endif %}
 | 
			
		||||
            {% endif %}
 | 
			
		||||
 | 
			
		||||
            {% if form.checkboxes is defined %}
 | 
			
		||||
                {% set btnSubmit = 1 %}
 | 
			
		||||
                {% if form.checkboxes|length > 0 %}
 | 
			
		||||
@@ -56,6 +58,7 @@
 | 
			
		||||
                    {% endfor %}
 | 
			
		||||
                {% endif %}
 | 
			
		||||
            {% endif %}
 | 
			
		||||
 | 
			
		||||
            {% if form.entity_choices is defined %}
 | 
			
		||||
                {% set btnSubmit = 1 %}
 | 
			
		||||
                {% if form.entity_choices |length > 0 %}
 | 
			
		||||
@@ -74,6 +77,25 @@
 | 
			
		||||
                    {% endfor %}
 | 
			
		||||
                {% endif %}
 | 
			
		||||
            {% endif %}
 | 
			
		||||
 | 
			
		||||
            {% if form.user_pickers is defined %}
 | 
			
		||||
                {% set btnSubmit = 1 %}
 | 
			
		||||
                {% if form.user_pickers.children|length > 0 %}
 | 
			
		||||
                    {% for name, options in form.user_pickers %}
 | 
			
		||||
                        <div class="row my-2">
 | 
			
		||||
                            {% if form.user_pickers[name].vars.label is not same as(false) %}
 | 
			
		||||
                                {{ form_label(form.user_pickers[name]) }}
 | 
			
		||||
                            {% else %}
 | 
			
		||||
                                {{ form_label(form.user_pickers[name].vars.label) }}
 | 
			
		||||
                            {% endif %}
 | 
			
		||||
                            <div class="col-sm-8 pt-2">
 | 
			
		||||
                                {{ form_widget(form.user_pickers[name]) }}
 | 
			
		||||
                            </div>
 | 
			
		||||
                        </div>
 | 
			
		||||
                    {% endfor %}
 | 
			
		||||
                {% endif %}
 | 
			
		||||
            {% endif %}
 | 
			
		||||
 | 
			
		||||
            {% if form.single_checkboxes is defined %}
 | 
			
		||||
                {% set btnSubmit = 1 %}
 | 
			
		||||
                {% for name, _o in form.single_checkboxes %}
 | 
			
		||||
@@ -91,8 +113,10 @@
 | 
			
		||||
                    <button type="submit" class="btn btn-sm btn-misc"><i class="fa fa-fw fa-filter"></i>{{ 'Filter'|trans }}</button>
 | 
			
		||||
                </div>
 | 
			
		||||
            {% endif %}
 | 
			
		||||
 | 
			
		||||
        </div>
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    {% if active|length > 0 %}
 | 
			
		||||
        <div class="activeFilters mt-3">
 | 
			
		||||
            {% for f in active %}
 | 
			
		||||
 
 | 
			
		||||
@@ -11,6 +11,7 @@ declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Chill\MainBundle\Templating\Listing;
 | 
			
		||||
 | 
			
		||||
use Chill\MainBundle\Templating\Entity\UserRender;
 | 
			
		||||
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
 | 
			
		||||
use Symfony\Component\PropertyAccess\PropertyPathInterface;
 | 
			
		||||
use Symfony\Contracts\Translation\TranslatorInterface;
 | 
			
		||||
@@ -20,6 +21,7 @@ final readonly class FilterOrderGetActiveFilterHelper
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        private TranslatorInterface $translator,
 | 
			
		||||
        private PropertyAccessorInterface $propertyAccessor,
 | 
			
		||||
        private UserRender $userRender,
 | 
			
		||||
    ) {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -73,6 +75,12 @@ final readonly class FilterOrderGetActiveFilterHelper
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        foreach ($filterOrderHelper->getUserPickers() as $name => ['label' => $label, 'options' => $options]) {
 | 
			
		||||
            foreach ($filterOrderHelper->getUserPickerData($name) as $user) {
 | 
			
		||||
                $result[] = ['value' => $this->userRender->renderString($user, []), 'label' => (string) $label, 'position' => FilterOrderPositionEnum::UserPicker->value, 'name' => $name];
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        foreach ($filterOrderHelper->getSingleCheckbox() as $name => ['label' => $label]) {
 | 
			
		||||
            if (true === $filterOrderHelper->getSingleCheckboxData($name)) {
 | 
			
		||||
                $result[] = ['label' => '', 'value' => $this->translator->trans($label), 'position' => FilterOrderPositionEnum::SingleCheckbox->value, 'name' => $name];
 | 
			
		||||
 
 | 
			
		||||
@@ -11,8 +11,11 @@ declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Chill\MainBundle\Templating\Listing;
 | 
			
		||||
 | 
			
		||||
use Chill\MainBundle\Entity\User;
 | 
			
		||||
use Chill\MainBundle\Form\Type\Listing\FilterOrderType;
 | 
			
		||||
use DateTimeImmutable;
 | 
			
		||||
use Symfony\Component\Form\Extension\Core\Type\FormType;
 | 
			
		||||
use Symfony\Component\Form\Extension\Core\Type\HiddenType;
 | 
			
		||||
use Symfony\Component\Form\FormFactoryInterface;
 | 
			
		||||
use Symfony\Component\Form\FormInterface;
 | 
			
		||||
use Symfony\Component\HttpFoundation\RequestStack;
 | 
			
		||||
@@ -52,6 +55,11 @@ final class FilterOrderHelper
 | 
			
		||||
    private array $entityChoices = [];
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @var array<string, array{label: string, options: array}>
 | 
			
		||||
     */
 | 
			
		||||
    private array $userPickers = [];
 | 
			
		||||
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        private readonly FormFactoryInterface $formFactory,
 | 
			
		||||
        private readonly RequestStack $requestStack,
 | 
			
		||||
@@ -80,6 +88,14 @@ final class FilterOrderHelper
 | 
			
		||||
        return $this->entityChoices;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function addUserPicker(string $name, ?string $label = null, array $options = []): self
 | 
			
		||||
    {
 | 
			
		||||
        $this->userPickers[$name] = ['label' => $label, 'options' => $options];
 | 
			
		||||
 | 
			
		||||
        return $this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    public function addCheckbox(string $name, array $choices, ?array $default = [], ?array $trans = [], array $options = []): self
 | 
			
		||||
    {
 | 
			
		||||
        if ([] === $trans) {
 | 
			
		||||
@@ -114,6 +130,19 @@ final class FilterOrderHelper
 | 
			
		||||
            ->handleRequest($this->requestStack->getCurrentRequest());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getUserPickers(): array
 | 
			
		||||
    {
 | 
			
		||||
        return $this->userPickers;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @return list<User>
 | 
			
		||||
     */
 | 
			
		||||
    public function getUserPickerData(string $name): array
 | 
			
		||||
    {
 | 
			
		||||
        return $this->getFormData()['user_pickers'][$name];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function hasCheckboxData(string $name): bool
 | 
			
		||||
    {
 | 
			
		||||
        return array_key_exists($name, $this->checkboxes);
 | 
			
		||||
@@ -203,7 +232,8 @@ final class FilterOrderHelper
 | 
			
		||||
            'checkboxes' => [],
 | 
			
		||||
            'dateRanges' => [],
 | 
			
		||||
            'single_checkboxes' => [],
 | 
			
		||||
            'entity_choices' => []
 | 
			
		||||
            'entity_choices' => [],
 | 
			
		||||
            'user_pickers' => []
 | 
			
		||||
        ];
 | 
			
		||||
 | 
			
		||||
        if ($this->hasSearchBox()) {
 | 
			
		||||
@@ -227,6 +257,10 @@ final class FilterOrderHelper
 | 
			
		||||
            $r['entity_choices'][$name] = ($c['options']['multiple'] ?? true) ? [] : null;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        foreach ($this->userPickers as $name => $u) {
 | 
			
		||||
            $r['user_pickers'][$name] = ($u['options']['multiple'] ?? true) ? [] : null;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $r;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -39,6 +39,11 @@ class FilterOrderHelperBuilder
 | 
			
		||||
     */
 | 
			
		||||
    private array $entityChoices = [];
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @var array<string, array{label: string, options: array}>
 | 
			
		||||
     */
 | 
			
		||||
    private array $userPickers = [];
 | 
			
		||||
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        FormFactoryInterface $formFactory,
 | 
			
		||||
        RequestStack $requestStack,
 | 
			
		||||
@@ -85,6 +90,13 @@ class FilterOrderHelperBuilder
 | 
			
		||||
        return $this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function addUserPicker(string $name, ?string $label = null, ?array $options = []): self
 | 
			
		||||
    {
 | 
			
		||||
        $this->userPickers[$name] = ['label' => $label, 'options' => $options];
 | 
			
		||||
 | 
			
		||||
        return $this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function build(): FilterOrderHelper
 | 
			
		||||
    {
 | 
			
		||||
        $helper = new FilterOrderHelper(
 | 
			
		||||
@@ -126,6 +138,17 @@ class FilterOrderHelperBuilder
 | 
			
		||||
            $helper->addDateRange($name, $label, $from, $to);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        foreach (
 | 
			
		||||
            $this->userPickers as $name => [
 | 
			
		||||
                'label' => $label,
 | 
			
		||||
                'options' => $options
 | 
			
		||||
            ]
 | 
			
		||||
        ) {
 | 
			
		||||
            $helper->addUserPicker($name, $label, $options);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        return $helper;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -18,4 +18,5 @@ enum FilterOrderPositionEnum: string
 | 
			
		||||
    case DateRange = 'date_range';
 | 
			
		||||
    case EntityChoice = 'entity_choice';
 | 
			
		||||
    case SingleCheckbox = 'single_checkbox';
 | 
			
		||||
    case UserPicker = 'user_picker';
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -26,6 +26,7 @@ use Chill\TaskBundle\Event\TaskEvent;
 | 
			
		||||
use Chill\TaskBundle\Event\UI\UIEvent;
 | 
			
		||||
use Chill\TaskBundle\Form\SingleTaskType;
 | 
			
		||||
use Chill\TaskBundle\Repository\SingleTaskAclAwareRepositoryInterface;
 | 
			
		||||
use Chill\TaskBundle\Repository\SingleTaskStateRepository;
 | 
			
		||||
use Chill\TaskBundle\Security\Authorization\TaskVoter;
 | 
			
		||||
use LogicException;
 | 
			
		||||
use Psr\Log\LoggerInterface;
 | 
			
		||||
@@ -71,7 +72,8 @@ final class SingleTaskController extends AbstractController
 | 
			
		||||
        EventDispatcherInterface $eventDispatcher,
 | 
			
		||||
        TimelineBuilder $timelineBuilder,
 | 
			
		||||
        LoggerInterface $logger,
 | 
			
		||||
        FilterOrderHelperFactoryInterface $filterOrderHelperFactory
 | 
			
		||||
        FilterOrderHelperFactoryInterface $filterOrderHelperFactory,
 | 
			
		||||
        private SingleTaskStateRepository $singleTaskStateRepository
 | 
			
		||||
    ) {
 | 
			
		||||
        $this->eventDispatcher = $eventDispatcher;
 | 
			
		||||
        $this->timelineBuilder = $timelineBuilder;
 | 
			
		||||
@@ -299,13 +301,17 @@ final class SingleTaskController extends AbstractController
 | 
			
		||||
        $this->denyAccessUnlessGranted(TaskVoter::SHOW, null);
 | 
			
		||||
 | 
			
		||||
        $filterOrder = $this->buildFilterOrder();
 | 
			
		||||
 | 
			
		||||
        $filteredUsers = $filterOrder->getUserPickerData('userPicker');
 | 
			
		||||
 | 
			
		||||
        $flags = array_merge(
 | 
			
		||||
            $filterOrder->getCheckboxData('status'),
 | 
			
		||||
            array_map(static fn ($i) => 'state_' . $i, $filterOrder->getCheckboxData('states'))
 | 
			
		||||
        );
 | 
			
		||||
        $nb = $this->singleTaskAclAwareRepository->countByAllViewable(
 | 
			
		||||
            $filterOrder->getQueryString(),
 | 
			
		||||
            $flags
 | 
			
		||||
            $flags,
 | 
			
		||||
            $filteredUsers
 | 
			
		||||
        );
 | 
			
		||||
        $paginator = $this->paginatorFactory->create($nb);
 | 
			
		||||
 | 
			
		||||
@@ -313,6 +319,7 @@ final class SingleTaskController extends AbstractController
 | 
			
		||||
            $tasks = $this->singleTaskAclAwareRepository->findByAllViewable(
 | 
			
		||||
                $filterOrder->getQueryString(),
 | 
			
		||||
                $flags,
 | 
			
		||||
                $filteredUsers,
 | 
			
		||||
                $paginator->getCurrentPageFirstItemNumber(),
 | 
			
		||||
                $paginator->getItemsPerPage(),
 | 
			
		||||
                [
 | 
			
		||||
@@ -447,7 +454,7 @@ final class SingleTaskController extends AbstractController
 | 
			
		||||
    {
 | 
			
		||||
        $this->denyAccessUnlessGranted('ROLE_USER');
 | 
			
		||||
 | 
			
		||||
        $filterOrder = $this->buildFilterOrder();
 | 
			
		||||
        $filterOrder = $this->buildFilterOrder(false);
 | 
			
		||||
        $flags = array_merge(
 | 
			
		||||
            $filterOrder->getCheckboxData('status'),
 | 
			
		||||
            array_map(static fn ($i) => 'state_' . $i, $filterOrder->getCheckboxData('states'))
 | 
			
		||||
@@ -662,7 +669,7 @@ final class SingleTaskController extends AbstractController
 | 
			
		||||
        return $form;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function buildFilterOrder(): FilterOrderHelper
 | 
			
		||||
    private function buildFilterOrder($includeFilterByUser = true): FilterOrderHelper
 | 
			
		||||
    {
 | 
			
		||||
        $statuses = ['no-alert', 'warning', 'alert'];
 | 
			
		||||
        $statusTrans = [
 | 
			
		||||
@@ -670,17 +677,22 @@ final class SingleTaskController extends AbstractController
 | 
			
		||||
            'Tasks near deadline',
 | 
			
		||||
            'Tasks over deadline',
 | 
			
		||||
        ];
 | 
			
		||||
        $states = [
 | 
			
		||||
            // todo: get a list of possible states dynamically
 | 
			
		||||
            'new', 'in_progress', 'closed', 'canceled',
 | 
			
		||||
        ];
 | 
			
		||||
        $states = $this->singleTaskStateRepository->findAllExistingStates();
 | 
			
		||||
        $checked = array_values(array_filter($states, fn (string $state) => !in_array($state, ['closed', 'canceled', 'validated'], true)));
 | 
			
		||||
 | 
			
		||||
        return $this->filterOrderHelperFactory
 | 
			
		||||
        $filterBuilder = $this->filterOrderHelperFactory
 | 
			
		||||
            ->create(self::class)
 | 
			
		||||
            ->addSearchBox()
 | 
			
		||||
            ->addCheckbox('status', $statuses, $statuses, $statusTrans)
 | 
			
		||||
            ->addCheckbox('states', $states, ['new', 'in_progress'])
 | 
			
		||||
            ->build();
 | 
			
		||||
            ->addCheckbox('states', $states, $checked)
 | 
			
		||||
        ;
 | 
			
		||||
 | 
			
		||||
        if ($includeFilterByUser) {
 | 
			
		||||
            $filterBuilder
 | 
			
		||||
                ->addUserPicker('userPicker', 'Filter by user', ['multiple' => true, 'required' => false]);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $filterBuilder->build();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
 
 | 
			
		||||
@@ -51,7 +51,8 @@ final class SingleTaskAclAwareRepository implements SingleTaskAclAwareRepository
 | 
			
		||||
 | 
			
		||||
    public function buildBaseQuery(
 | 
			
		||||
        ?string $pattern = null,
 | 
			
		||||
        ?array $flags = []
 | 
			
		||||
        ?array $flags = [],
 | 
			
		||||
        ?array $users = []
 | 
			
		||||
    ): QueryBuilder {
 | 
			
		||||
        $qb = $this->em->createQueryBuilder();
 | 
			
		||||
        $qb
 | 
			
		||||
@@ -62,6 +63,24 @@ final class SingleTaskAclAwareRepository implements SingleTaskAclAwareRepository
 | 
			
		||||
                ->setParameter('pattern', '%' . $pattern . '%');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (count($users) > 0) {
 | 
			
		||||
            $orXUser = $qb->expr()->orX();
 | 
			
		||||
 | 
			
		||||
            foreach ($users as $key => $user) {
 | 
			
		||||
                $orXUser->add(
 | 
			
		||||
                    $qb->expr()->eq('t.assignee', ':user_' . $key)
 | 
			
		||||
                );
 | 
			
		||||
 | 
			
		||||
                $qb->setParameter('user_' . $key, $user);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if ($orXUser->count() > 0) {
 | 
			
		||||
                $qb->andWhere($orXUser);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return $qb;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (count($flags) > 0) {
 | 
			
		||||
            $orXDate = $qb->expr()->orX();
 | 
			
		||||
            $orXState = $qb->expr()->orX();
 | 
			
		||||
@@ -183,9 +202,10 @@ final class SingleTaskAclAwareRepository implements SingleTaskAclAwareRepository
 | 
			
		||||
 | 
			
		||||
    public function countByAllViewable(
 | 
			
		||||
        ?string $pattern = null,
 | 
			
		||||
        ?array $flags = []
 | 
			
		||||
        ?array $flags = [],
 | 
			
		||||
        ?array $users = []
 | 
			
		||||
    ): int {
 | 
			
		||||
        $qb = $this->buildBaseQuery($pattern, $flags);
 | 
			
		||||
        $qb = $this->buildBaseQuery($pattern, $flags, $users);
 | 
			
		||||
 | 
			
		||||
        return $this
 | 
			
		||||
            ->addACLGlobal($qb)
 | 
			
		||||
@@ -231,11 +251,12 @@ final class SingleTaskAclAwareRepository implements SingleTaskAclAwareRepository
 | 
			
		||||
    public function findByAllViewable(
 | 
			
		||||
        ?string $pattern = null,
 | 
			
		||||
        ?array $flags = [],
 | 
			
		||||
        ?array $users = [],
 | 
			
		||||
        ?int $start = 0,
 | 
			
		||||
        ?int $limit = 50,
 | 
			
		||||
        ?array $orderBy = []
 | 
			
		||||
    ): array {
 | 
			
		||||
        $qb = $this->buildBaseQuery($pattern, $flags);
 | 
			
		||||
        $qb = $this->buildBaseQuery($pattern, $flags, $users);
 | 
			
		||||
        $qb = $this->addACLGlobal($qb);
 | 
			
		||||
 | 
			
		||||
        return $this->getResult($qb, $start, $limit, $orderBy);
 | 
			
		||||
 
 | 
			
		||||
@@ -18,7 +18,8 @@ interface SingleTaskAclAwareRepositoryInterface
 | 
			
		||||
{
 | 
			
		||||
    public function countByAllViewable(
 | 
			
		||||
        ?string $pattern = null,
 | 
			
		||||
        ?array $flags = []
 | 
			
		||||
        ?array $flags = [],
 | 
			
		||||
        ?array $users = []
 | 
			
		||||
    ): int;
 | 
			
		||||
 | 
			
		||||
    public function countByCourse(
 | 
			
		||||
@@ -38,6 +39,7 @@ interface SingleTaskAclAwareRepositoryInterface
 | 
			
		||||
    public function findByAllViewable(
 | 
			
		||||
        ?string $pattern = null,
 | 
			
		||||
        ?array $flags = [],
 | 
			
		||||
        ?array $users = [],
 | 
			
		||||
        ?int $start = 0,
 | 
			
		||||
        ?int $limit = 50,
 | 
			
		||||
        ?array $orderBy = []
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,47 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Chill is a software for social workers
 | 
			
		||||
 *
 | 
			
		||||
 * For the full copyright and license information, please view
 | 
			
		||||
 * the LICENSE file that was distributed with this source code.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
namespace Chill\TaskBundle\Repository;
 | 
			
		||||
 | 
			
		||||
use Doctrine\DBAL\Connection;
 | 
			
		||||
use Doctrine\DBAL\Exception;
 | 
			
		||||
 | 
			
		||||
class SingleTaskStateRepository
 | 
			
		||||
{
 | 
			
		||||
    private const FIND_ALL_STATES = <<<'SQL'
 | 
			
		||||
    SELECT DISTINCT jsonb_array_elements_text(current_states) FROM chill_task.single_task
 | 
			
		||||
    SQL;
 | 
			
		||||
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        private Connection $connection
 | 
			
		||||
    ) {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Return a list of all states associated to at least one single task in the database
 | 
			
		||||
     *
 | 
			
		||||
     * @return list<string>
 | 
			
		||||
     * @throws Exception
 | 
			
		||||
     */
 | 
			
		||||
    public function findAllExistingStates(): array
 | 
			
		||||
    {
 | 
			
		||||
        $states = [];
 | 
			
		||||
 | 
			
		||||
        foreach ($this->connection->fetchAllNumeric(self::FIND_ALL_STATES) as $row) {
 | 
			
		||||
            if ('' !== $row[0] && null !== $row[0]) {
 | 
			
		||||
                $states[] = $row[0];
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $states;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -27,8 +27,10 @@
 | 
			
		||||
{% block css %}
 | 
			
		||||
    {{ parent() }}
 | 
			
		||||
    {{ encore_entry_link_tags('page_task_list') }}
 | 
			
		||||
    {{ encore_entry_link_tags('mod_pickentity_type') }}
 | 
			
		||||
{% endblock %}
 | 
			
		||||
{% block js %}
 | 
			
		||||
    {{ parent() }}
 | 
			
		||||
    {{ encore_entry_script_tags('page_task_list') }}
 | 
			
		||||
    {{ encore_entry_script_tags('mod_pickentity_type') }}
 | 
			
		||||
{% endblock %}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,8 @@
 | 
			
		||||
services:
 | 
			
		||||
    _defaults:
 | 
			
		||||
        autowire: true
 | 
			
		||||
        autoconfigure: true
 | 
			
		||||
 | 
			
		||||
    chill_task.single_task_repository:
 | 
			
		||||
        class: Chill\TaskBundle\Repository\SingleTaskRepository
 | 
			
		||||
        factory: ['@doctrine.orm.entity_manager', getRepository]
 | 
			
		||||
@@ -10,8 +14,8 @@ services:
 | 
			
		||||
                  - "@chill.main.security.authorization.helper"
 | 
			
		||||
    Chill\TaskBundle\Repository\SingleTaskRepository: '@chill_task.single_task_repository'
 | 
			
		||||
 | 
			
		||||
    Chill\TaskBundle\Repository\SingleTaskAclAwareRepository:
 | 
			
		||||
        autowire: true
 | 
			
		||||
        autoconfigure: true
 | 
			
		||||
    Chill\TaskBundle\Repository\SingleTaskAclAwareRepository: ~
 | 
			
		||||
 | 
			
		||||
    Chill\TaskBundle\Repository\SingleTaskAclAwareRepositoryInterface: '@Chill\TaskBundle\Repository\SingleTaskAclAwareRepository'
 | 
			
		||||
 | 
			
		||||
    Chill\TaskBundle\Repository\SingleTaskStateRepository: ~
 | 
			
		||||
 
 | 
			
		||||
@@ -65,6 +65,7 @@ Not assigned: Aucun utilisateur assigné
 | 
			
		||||
For person: Pour
 | 
			
		||||
By: Par
 | 
			
		||||
Any tasks: Aucune tâche
 | 
			
		||||
Filter by user: Filtrer par utilisateur(s)
 | 
			
		||||
 | 
			
		||||
# transitions - default task definition
 | 
			
		||||
"new": "nouvelle"
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user