Index: src/applications/diffusion/herald/HeraldPreCommitContentAdapter.php =================================================================== --- src/applications/diffusion/herald/HeraldPreCommitContentAdapter.php +++ src/applications/diffusion/herald/HeraldPreCommitContentAdapter.php @@ -31,6 +31,16 @@ return pht('Commit Hook: Commit Content'); } + public function getAdapterSortOrder() { + return 2500; + } + + public function getAdapterContentDescription() { + return pht( + "React to commits being pushed to hosted repositories.\n". + "Hook rules can block changes."); + } + public function getFieldNameMap() { return array( ) + parent::getFieldNameMap(); Index: src/applications/diffusion/herald/HeraldPreCommitRefAdapter.php =================================================================== --- src/applications/diffusion/herald/HeraldPreCommitRefAdapter.php +++ src/applications/diffusion/herald/HeraldPreCommitRefAdapter.php @@ -34,6 +34,16 @@ return pht('Commit Hook: Branches/Tags/Bookmarks'); } + public function getAdapterSortOrder() { + return 2000; + } + + public function getAdapterContentDescription() { + return pht( + "React to branches and tags being pushed to hosted repositories.\n". + "Hook rules can block changes."); + } + public function getFieldNameMap() { return array( self::FIELD_REF_TYPE => pht('Ref type'), Index: src/applications/herald/adapter/HeraldAdapter.php =================================================================== --- src/applications/herald/adapter/HeraldAdapter.php +++ src/applications/herald/adapter/HeraldAdapter.php @@ -134,9 +134,21 @@ } abstract public function getAdapterContentName(); + abstract public function getAdapterContentDescription(); abstract public function getAdapterApplicationClass(); abstract public function getObject(); + public function getAdapterSortKey() { + return sprintf( + '%08d%s', + $this->getAdapterSortOrder(), + $this->getAdapterContentName()); + } + + public function getAdapterSortOrder() { + return 1000; + } + /* -( Fields )------------------------------------------------------------- */ @@ -808,6 +820,7 @@ $adapters = id(new PhutilSymbolLoader()) ->setAncestorClass(__CLASS__) ->loadObjects(); + $adapters = msort($adapters, 'getAdapterSortKey'); } return $adapters; } @@ -840,7 +853,6 @@ $map[$type] = $name; } - asort($map); return $map; } Index: src/applications/herald/adapter/HeraldCommitAdapter.php =================================================================== --- src/applications/herald/adapter/HeraldCommitAdapter.php +++ src/applications/herald/adapter/HeraldCommitAdapter.php @@ -42,6 +42,13 @@ return pht('Commits'); } + public function getAdapterContentDescription() { + return pht( + "React to new commits appearing in tracked repositories.\n". + "Commit rules can send email, flag commits, trigger audits, ". + "and run build plans."); + } + public function getFieldNameMap() { return array( self::FIELD_NEED_AUDIT_FOR_PACKAGE => Index: src/applications/herald/adapter/HeraldDifferentialRevisionAdapter.php =================================================================== --- src/applications/herald/adapter/HeraldDifferentialRevisionAdapter.php +++ src/applications/herald/adapter/HeraldDifferentialRevisionAdapter.php @@ -36,6 +36,13 @@ return pht('Differential Revisions'); } + public function getAdapterContentDescription() { + return pht( + "React to revisions being created or updated.\n". + "Revision rules can send email, flag revisions, add reviewers, ". + "and run build plans."); + } + public function getFields() { return array_merge( array( Index: src/applications/herald/adapter/HeraldManiphestTaskAdapter.php =================================================================== --- src/applications/herald/adapter/HeraldManiphestTaskAdapter.php +++ src/applications/herald/adapter/HeraldManiphestTaskAdapter.php @@ -14,6 +14,11 @@ return 'PhabricatorApplicationManiphest'; } + public function getAdapterContentDescription() { + return pht( + 'React to tasks being created or updated.'); + } + public function setTask(ManiphestTask $task) { $this->task = $task; return $this; Index: src/applications/herald/adapter/HeraldPholioMockAdapter.php =================================================================== --- src/applications/herald/adapter/HeraldPholioMockAdapter.php +++ src/applications/herald/adapter/HeraldPholioMockAdapter.php @@ -12,6 +12,11 @@ return 'PhabricatorApplicationPholio'; } + public function getAdapterContentDescription() { + return pht( + 'React to mocks being created or updated.'); + } + public function getObject() { return $this->mock; } Index: src/applications/herald/controller/HeraldNewController.php =================================================================== --- src/applications/herald/controller/HeraldNewController.php +++ src/applications/herald/controller/HeraldNewController.php @@ -53,19 +53,21 @@ ->setUser($user) ->setAction($this->getApplicationURI('new/')); - $rule_types = $this->renderRuleTypeControl($rule_type_map, $e_rule); + $content_types = $this->renderContentTypeControl( + $content_type_map, + $e_type); + + $rule_types = $this->renderRuleTypeControl( + $rule_type_map, + $e_rule); switch ($step) { case 0: default: $form ->addHiddenInput('step', 1) - ->appendChild( - id(new AphrontFormSelectControl()) - ->setLabel(pht('New Rule for')) - ->setName('content_type') - ->setValue($request->getStr('content_type')) - ->setOptions($content_type_map)); + ->appendChild($content_types); + $cancel_text = null; $cancel_uri = $this->getApplicationURI(); break; @@ -73,7 +75,16 @@ $form ->addHiddenInput('content_type', $request->getStr('content_type')) ->addHiddenInput('step', 2) + ->appendChild( + id(new AphrontFormStaticControl()) + ->setLabel(pht('Rule for')) + ->setValue( + phutil_tag( + 'strong', + array(), + idx($content_type_map, $content_type)))) ->appendChild($rule_types); + $cancel_text = pht('Back'); $cancel_uri = id(new PhutilURI('new/')) ->setQueryParams( @@ -112,6 +123,27 @@ )); } + private function renderContentTypeControl(array $content_type_map, $e_type) { + $request = $this->getRequest(); + + $radio = id(new AphrontFormRadioButtonControl()) + ->setLabel(pht('New Rule for')) + ->setName('content_type') + ->setValue($request->getStr('content_type')) + ->setError($e_type); + + foreach ($content_type_map as $value => $name) { + $adapter = HeraldAdapter::getAdapterForContentType($value); + $radio->addButton( + $value, + $name, + phutil_escape_html_newlines($adapter->getAdapterContentDescription())); + } + + return $radio; + } + + private function renderRuleTypeControl(array $rule_type_map, $e_rule) { $request = $this->getRequest();