diff --git a/src/Form/Ticket/QuickSearchForm.php b/src/Form/Ticket/QuickSearchForm.php index 8cb1ce61..e6cf592e 100644 --- a/src/Form/Ticket/QuickSearchForm.php +++ b/src/Form/Ticket/QuickSearchForm.php @@ -199,6 +199,20 @@ function (?string $value): string { 'block_prefix' => 'multiselect', ]); + $form->add('teams', AppType\TeamType::class, [ + 'multiple' => true, + 'required' => false, + 'label' => new TranslatableMessage('tickets.team'), + 'organization' => $organization, + 'label_attr' => [ + 'class' => 'text--bold', + ], + 'attr' => [ + 'data-placeholder' => $this->translator->trans('forms.multiselect.select_team'), + ], + 'block_prefix' => 'multiselect', + ]); + $form->add('assignees', AppType\ActorType::class, [ 'multiple' => true, 'required' => false, diff --git a/src/SearchEngine/Ticket/QuickSearchFilter.php b/src/SearchEngine/Ticket/QuickSearchFilter.php index 0b35380a..d12cfcc7 100644 --- a/src/SearchEngine/Ticket/QuickSearchFilter.php +++ b/src/SearchEngine/Ticket/QuickSearchFilter.php @@ -30,6 +30,9 @@ class QuickSearchFilter /** @var Collections\Collection */ private Collections\Collection $requesters; + /** @var Collections\Collection */ + private Collections\Collection $teams; + /** @var Collections\Collection */ private Collections\Collection $labels; @@ -49,6 +52,7 @@ public function __construct() $this->involves = new Collections\ArrayCollection(); $this->assignees = new Collections\ArrayCollection(); $this->requesters = new Collections\ArrayCollection(); + $this->teams = new Collections\ArrayCollection(); $this->labels = new Collections\ArrayCollection(); } @@ -192,6 +196,22 @@ public function setRequesters(Collections\Collection $values): void $this->requesters = $values; } + /** + * @return Collections\Collection + */ + public function getTeams(): Collections\Collection + { + return $this->teams; + } + + /** + * @param Collections\Collection $values + */ + public function setTeams(Collections\Collection $values): void + { + $this->teams = $values; + } + /** * @return Collections\Collection */ @@ -303,6 +323,11 @@ public function toTextualQuery(): string $textualQueryParts[] = "requester:{$values}"; } + if (!$this->teams->isEmpty()) { + $values = $this->processTeamValues($this->teams); + $textualQueryParts[] = "team:{$values}"; + } + foreach ($this->labels as $label) { $value = $label->getName(); @@ -349,4 +374,16 @@ private function processActorValues(Collections\Collection $actors): string return implode(',', $actorIds); } + + /** + * @param Collections\Collection $teams + */ + private function processTeamValues(Collections\Collection $teams): string + { + $teamIds = array_map(function (Entity\Team $team): string { + return "#{$team->getId()}"; + }, $teams->toArray()); + + return implode(',', $teamIds); + } } diff --git a/src/SearchEngine/Ticket/QuickSearchFilterBuilder.php b/src/SearchEngine/Ticket/QuickSearchFilterBuilder.php index f2a57b9d..33b83aaf 100644 --- a/src/SearchEngine/Ticket/QuickSearchFilterBuilder.php +++ b/src/SearchEngine/Ticket/QuickSearchFilterBuilder.php @@ -16,6 +16,7 @@ class QuickSearchFilterBuilder { public function __construct( private Repository\LabelRepository $labelRepository, + private Repository\TeamRepository $teamRepository, private Repository\UserRepository $userRepository, private Security $security, ) { @@ -85,6 +86,9 @@ public function getFilter(?SearchEngine\Query $query = null): ?QuickSearchFilter } elseif ($qualifier === 'requester') { $users = $this->processUsers($values); $quickSearchFilter->setRequesters($users); + } elseif ($qualifier === 'team') { + $teams = $this->processTeams($values); + $quickSearchFilter->setTeams($teams); } elseif ($qualifier === 'label') { foreach ($values as $value) { $labels = $this->labelRepository->findByName($value); @@ -135,4 +139,27 @@ private function processUsers(array $values): Collections\ArrayCollection return new Collections\ArrayCollection($users); } + + /** + * @param string[] $values + * + * @return Collections\ArrayCollection + */ + private function processTeams(array $values): Collections\ArrayCollection + { + $ids = []; + + foreach ($values as $value) { + if (preg_match('/^#[\d]+$/', $value)) { + $value = substr($value, 1); + $ids[] = intval($value); + } + } + + $teams = $this->teamRepository->findBy([ + 'id' => $ids, + ]); + + return new Collections\ArrayCollection($teams); + } } diff --git a/templates/tickets/_search_form.html.twig b/templates/tickets/_search_form.html.twig index 8d10b53e..be620295 100644 --- a/templates/tickets/_search_form.html.twig +++ b/templates/tickets/_search_form.html.twig @@ -55,11 +55,12 @@ {% if quickSearchForm.involves is defined %} {% set involvesIsSet = field_value(quickSearchForm.involves) is not empty %} + {% set teamsIsSet = field_value(quickSearchForm.teams) is not empty %} {% set assigneesIsSet = field_value(quickSearchForm.assignees) is not empty %} {% set unassignedOnlyIsSet = quickSearchForm.unassignedOnly.vars.checked %} {% set requestersIsSet = field_value(quickSearchForm.requesters) is not empty %} -
+
{{ 'tickets.filters.actors.title' | trans }} @@ -67,6 +68,12 @@
{{ form_row(quickSearchForm.involves) }} + {% if quickSearchForm.teams.vars.choices is not empty %} + {{ form_row(quickSearchForm.teams) }} + {% else %} + {% do quickSearchForm.teams.setRendered %} + {% endif %} +
{{ form_row(quickSearchForm.assignees) }} diff --git a/translations/messages+intl-icu.en_GB.yaml b/translations/messages+intl-icu.en_GB.yaml index d87f1642..f8f3f120 100644 --- a/translations/messages+intl-icu.en_GB.yaml +++ b/translations/messages+intl-icu.en_GB.yaml @@ -177,6 +177,7 @@ forms.error: Error forms.input_texts.remove: Remove forms.max_chars: '(max. {number} characters)' forms.multiselect.select_actor: 'Select an actor' +forms.multiselect.select_team: 'Select a team' forms.multiselect.unselect: Unselect forms.optional: (optional) forms.optional_max_chars: '(optional, max. {number} characters)' diff --git a/translations/messages+intl-icu.fr_FR.yaml b/translations/messages+intl-icu.fr_FR.yaml index c265f2d3..53756f78 100644 --- a/translations/messages+intl-icu.fr_FR.yaml +++ b/translations/messages+intl-icu.fr_FR.yaml @@ -177,6 +177,7 @@ forms.error: Erreur forms.input_texts.remove: Retirer forms.max_chars: '(max. {number} caractères)' forms.multiselect.select_actor: 'Sélectionner un acteur' +forms.multiselect.select_team: 'Sélectionner une équipe' forms.multiselect.unselect: Désélectionner forms.optional: (optionnel) forms.optional_max_chars: '(optionnel, max. {number} caractères)'