diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -1525,6 +1525,7 @@ 'ManiphestTaskStatusHeraldAction' => 'applications/maniphest/herald/ManiphestTaskStatusHeraldAction.php', 'ManiphestTaskStatusHeraldField' => 'applications/maniphest/herald/ManiphestTaskStatusHeraldField.php', 'ManiphestTaskStatusTestCase' => 'applications/maniphest/constants/__tests__/ManiphestTaskStatusTestCase.php', + 'ManiphestTaskSubtypeDatasource' => 'applications/maniphest/typeahead/ManiphestTaskSubtypeDatasource.php', 'ManiphestTaskTestCase' => 'applications/maniphest/__tests__/ManiphestTaskTestCase.php', 'ManiphestTaskTitleHeraldField' => 'applications/maniphest/herald/ManiphestTaskTitleHeraldField.php', 'ManiphestTransaction' => 'applications/maniphest/storage/ManiphestTransaction.php', @@ -6424,6 +6425,7 @@ 'ManiphestTaskStatusHeraldAction' => 'HeraldAction', 'ManiphestTaskStatusHeraldField' => 'ManiphestTaskHeraldField', 'ManiphestTaskStatusTestCase' => 'PhabricatorTestCase', + 'ManiphestTaskSubtypeDatasource' => 'PhabricatorTypeaheadDatasource', 'ManiphestTaskTestCase' => 'PhabricatorTestCase', 'ManiphestTaskTitleHeraldField' => 'ManiphestTaskHeraldField', 'ManiphestTransaction' => 'PhabricatorApplicationTransaction', diff --git a/src/applications/maniphest/query/ManiphestTaskSearchEngine.php b/src/applications/maniphest/query/ManiphestTaskSearchEngine.php --- a/src/applications/maniphest/query/ManiphestTaskSearchEngine.php +++ b/src/applications/maniphest/query/ManiphestTaskSearchEngine.php @@ -44,6 +44,11 @@ } protected function buildCustomSearchFields() { + // Hide the "Subtypes" constraint from the web UI if the install only + // defines one task subtype, since it isn't of any use in this case. + $subtype_map = id(new ManiphestTask())->newEditEngineSubtypeMap(); + $hide_subtypes = (count($subtype_map) == 1); + return array( id(new PhabricatorOwnersSearchField()) ->setLabel(pht('Assigned To')) @@ -73,6 +78,14 @@ pht('Search for tasks with given priorities.')) ->setConduitParameterType(new ConduitIntListParameterType()) ->setDatasource(new ManiphestTaskPriorityDatasource()), + id(new PhabricatorSearchDatasourceField()) + ->setLabel(pht('Subtypes')) + ->setKey('subtypes') + ->setAliases(array('subtype')) + ->setDescription( + pht('Search for tasks with given subtypes.')) + ->setDatasource(new ManiphestTaskSubtypeDatasource()) + ->setIsHidden($hide_subtypes), id(new PhabricatorSearchTextField()) ->setLabel(pht('Contains Words')) ->setKey('fulltext'), @@ -130,6 +143,7 @@ 'subscriberPHIDs', 'statuses', 'priorities', + 'subtypes', 'fulltext', 'hasParents', 'hasSubtasks', @@ -178,6 +192,10 @@ $query->withPriorities($map['priorities']); } + if ($map['subtypes']) { + $query->withSubtypes($map['subtypes']); + } + if ($map['createdStart']) { $query->withDateCreatedAfter($map['createdStart']); } diff --git a/src/applications/maniphest/typeahead/ManiphestTaskSubtypeDatasource.php b/src/applications/maniphest/typeahead/ManiphestTaskSubtypeDatasource.php new file mode 100644 --- /dev/null +++ b/src/applications/maniphest/typeahead/ManiphestTaskSubtypeDatasource.php @@ -0,0 +1,44 @@ +buildResults(); + return $this->filterResultsAgainstTokens($results); + } + + protected function renderSpecialTokens(array $values) { + return $this->renderTokensFromResults($this->buildResults(), $values); + } + + private function buildResults() { + $results = array(); + + $subtype_map = id(new ManiphestTask())->newEditEngineSubtypeMap(); + foreach ($subtype_map as $key => $subtype) { + + $result = id(new PhabricatorTypeaheadResult()) + ->setIcon($subtype->getIcon()) + ->setPHID($key) + ->setName($subtype->getName()); + + $results[$key] = $result; + } + + return $results; + } + +} diff --git a/src/applications/search/field/PhabricatorSearchField.php b/src/applications/search/field/PhabricatorSearchField.php --- a/src/applications/search/field/PhabricatorSearchField.php +++ b/src/applications/search/field/PhabricatorSearchField.php @@ -17,6 +17,7 @@ private $aliases = array(); private $errors = array(); private $description; + private $isHidden; /* -( Configuring Fields )------------------------------------------------- */ @@ -188,6 +189,30 @@ } + /** + * Hide this field from the web UI. + * + * @param bool True to hide the field from the web UI. + * @return this + * @task config + */ + public function setIsHidden($is_hidden) { + $this->isHidden = $is_hidden; + return $this; + } + + + /** + * Should this field be hidden from the web UI? + * + * @return bool True to hide the field in the web UI. + * @task config + */ + public function getIsHidden() { + return $this->isHidden; + } + + /* -( Handling Errors )---------------------------------------------------- */ @@ -273,6 +298,10 @@ protected function renderControl() { + if ($this->getIsHidden()) { + return null; + } + $control = $this->newControl(); if (!$control) { diff --git a/src/applications/transactions/editengine/PhabricatorEditEngineSubtype.php b/src/applications/transactions/editengine/PhabricatorEditEngineSubtype.php --- a/src/applications/transactions/editengine/PhabricatorEditEngineSubtype.php +++ b/src/applications/transactions/editengine/PhabricatorEditEngineSubtype.php @@ -27,6 +27,10 @@ return $this->name; } + public function getIcon() { + return 'fa-drivers-license-o'; + } + public static function validateSubtypeKey($subtype) { if (strlen($subtype) > 64) { throw new Exception(