diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 749876acc9..89f65a8db0 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -881,8 +881,10 @@ phutil_register_library_map(array( 'DrydockObjectAuthorizationView' => 'applications/drydock/view/DrydockObjectAuthorizationView.php', 'DrydockQuery' => 'applications/drydock/query/DrydockQuery.php', 'DrydockRepositoryOperation' => 'applications/drydock/storage/DrydockRepositoryOperation.php', + 'DrydockRepositoryOperationListController' => 'applications/drydock/controller/DrydockRepositoryOperationListController.php', 'DrydockRepositoryOperationPHIDType' => 'applications/drydock/phid/DrydockRepositoryOperationPHIDType.php', 'DrydockRepositoryOperationQuery' => 'applications/drydock/query/DrydockRepositoryOperationQuery.php', + 'DrydockRepositoryOperationSearchEngine' => 'applications/drydock/query/DrydockRepositoryOperationSearchEngine.php', 'DrydockRepositoryOperationType' => 'applications/drydock/operation/DrydockRepositoryOperationType.php', 'DrydockRepositoryOperationUpdateWorker' => 'applications/drydock/worker/DrydockRepositoryOperationUpdateWorker.php', 'DrydockRepositoryOperationViewController' => 'applications/drydock/controller/DrydockRepositoryOperationViewController.php', @@ -4665,8 +4667,10 @@ phutil_register_library_map(array( 'DrydockDAO', 'PhabricatorPolicyInterface', ), + 'DrydockRepositoryOperationListController' => 'DrydockController', 'DrydockRepositoryOperationPHIDType' => 'PhabricatorPHIDType', 'DrydockRepositoryOperationQuery' => 'DrydockQuery', + 'DrydockRepositoryOperationSearchEngine' => 'PhabricatorApplicationSearchEngine', 'DrydockRepositoryOperationType' => 'Phobject', 'DrydockRepositoryOperationUpdateWorker' => 'DrydockWorker', 'DrydockRepositoryOperationViewController' => 'DrydockController', diff --git a/src/applications/drydock/application/PhabricatorDrydockApplication.php b/src/applications/drydock/application/PhabricatorDrydockApplication.php index cd8cfcad5b..237e4afd9a 100644 --- a/src/applications/drydock/application/PhabricatorDrydockApplication.php +++ b/src/applications/drydock/application/PhabricatorDrydockApplication.php @@ -91,6 +91,8 @@ final class PhabricatorDrydockApplication extends PhabricatorApplication { ), ), '(?Poperation)/' => array( + '(?:query/(?P[^/]+)/)?' + => 'DrydockRepositoryOperationListController', '(?P[1-9]\d*)/' => array( '' => 'DrydockRepositoryOperationViewController', ), diff --git a/src/applications/drydock/controller/DrydockAuthorizationAuthorizeController.php b/src/applications/drydock/controller/DrydockAuthorizationAuthorizeController.php index 41010ff882..6422512df5 100644 --- a/src/applications/drydock/controller/DrydockAuthorizationAuthorizeController.php +++ b/src/applications/drydock/controller/DrydockAuthorizationAuthorizeController.php @@ -82,14 +82,4 @@ final class DrydockAuthorizationAuthorizeController ->addCancelButton($authorization_uri); } - public function buildSideNavView() { - // TODO: Get rid of this, but it's currently required by DrydockController. - return null; - } - - public function buildApplicationMenu() { - // TODO: As above. - return null; - } - } diff --git a/src/applications/drydock/controller/DrydockAuthorizationViewController.php b/src/applications/drydock/controller/DrydockAuthorizationViewController.php index 95270c4b51..3609b95f9f 100644 --- a/src/applications/drydock/controller/DrydockAuthorizationViewController.php +++ b/src/applications/drydock/controller/DrydockAuthorizationViewController.php @@ -128,14 +128,4 @@ final class DrydockAuthorizationViewController return $view; } - public function buildSideNavView() { - // TODO: Get rid of this, but it's currently required by DrydockController. - return null; - } - - public function buildApplicationMenu() { - // TODO: As above. - return null; - } - } diff --git a/src/applications/drydock/controller/DrydockConsoleController.php b/src/applications/drydock/controller/DrydockConsoleController.php index 1964f508d0..77346cea94 100644 --- a/src/applications/drydock/controller/DrydockConsoleController.php +++ b/src/applications/drydock/controller/DrydockConsoleController.php @@ -15,6 +15,7 @@ final class DrydockConsoleController extends DrydockController { $nav->addFilter('blueprint', pht('Blueprints')); $nav->addFilter('resource', pht('Resources')); $nav->addFilter('lease', pht('Leases')); + $nav->addFilter('operation', pht('Repository Operations')); $nav->selectFilter(null); @@ -52,6 +53,13 @@ final class DrydockConsoleController extends DrydockController { ->setHref($this->getApplicationURI('lease/')) ->addAttribute(pht('Manage leases on resources.'))); + $menu->addItem( + id(new PHUIObjectItemView()) + ->setHeader(pht('Repository Operations')) + ->setFontIcon('fa-fighter-jet') + ->setHref($this->getApplicationURI('operation/')) + ->addAttribute(pht('Review the repository operation queue.'))); + $crumbs = $this->buildApplicationCrumbs(); $crumbs->addTextCrumb(pht('Console')); diff --git a/src/applications/drydock/controller/DrydockController.php b/src/applications/drydock/controller/DrydockController.php index 67e4278ae3..ddb6788fb6 100644 --- a/src/applications/drydock/controller/DrydockController.php +++ b/src/applications/drydock/controller/DrydockController.php @@ -2,12 +2,6 @@ abstract class DrydockController extends PhabricatorController { - abstract public function buildSideNavView(); - - public function buildApplicationMenu() { - return $this->buildSideNavView()->getMenu(); - } - protected function buildLocksTab($owner_phid) { $locks = DrydockSlotLock::loadLocks($owner_phid); diff --git a/src/applications/drydock/controller/DrydockRepositoryOperationListController.php b/src/applications/drydock/controller/DrydockRepositoryOperationListController.php new file mode 100644 index 0000000000..581302817b --- /dev/null +++ b/src/applications/drydock/controller/DrydockRepositoryOperationListController.php @@ -0,0 +1,37 @@ +getURIData('queryKey'); + + $engine = new DrydockRepositoryOperationSearchEngine(); + + $controller = id(new PhabricatorApplicationSearchController()) + ->setQueryKey($query_key) + ->setSearchEngine($engine) + ->setNavigation($this->buildSideNavView()); + + return $this->delegateToController($controller); + } + + public function buildSideNavView() { + $nav = new AphrontSideNavFilterView(); + $nav->setBaseURI(new PhutilURI($this->getApplicationURI())); + + $engine = id(new DrydockRepositoryOperationSearchEngine()) + ->setViewer($this->getViewer()); + + $engine->addNavigationItems($nav->getMenu()); + + $nav->selectFilter(null); + + return $nav; + } + +} diff --git a/src/applications/drydock/controller/DrydockRepositoryOperationViewController.php b/src/applications/drydock/controller/DrydockRepositoryOperationViewController.php index 882a9ab57f..e740073dd9 100644 --- a/src/applications/drydock/controller/DrydockRepositoryOperationViewController.php +++ b/src/applications/drydock/controller/DrydockRepositoryOperationViewController.php @@ -3,6 +3,10 @@ final class DrydockRepositoryOperationViewController extends DrydockController { + public function shouldAllowPublic() { + return true; + } + public function handleRequest(AphrontRequest $request) { $viewer = $request->getViewer(); $id = $request->getURIData('id'); @@ -33,6 +37,9 @@ final class DrydockRepositoryOperationViewController $properties->setActionList($actions); $crumbs = $this->buildApplicationCrumbs(); + $crumbs->addTextCrumb( + pht('Operations'), + $this->getApplicationURI('operation/')); $crumbs->addTextCrumb($title); $object_box = id(new PHUIObjectBoxView()) @@ -79,14 +86,4 @@ final class DrydockRepositoryOperationViewController return $view; } - public function buildSideNavView() { - // TODO: Get rid of this, but it's currently required by DrydockController. - return null; - } - - public function buildApplicationMenu() { - // TODO: As above. - return null; - } - } diff --git a/src/applications/drydock/operation/DrydockLandRepositoryOperation.php b/src/applications/drydock/operation/DrydockLandRepositoryOperation.php index a71de3fff9..050aaeeb36 100644 --- a/src/applications/drydock/operation/DrydockLandRepositoryOperation.php +++ b/src/applications/drydock/operation/DrydockLandRepositoryOperation.php @@ -5,6 +5,12 @@ final class DrydockLandRepositoryOperation const OPCONST = 'land'; + public function getOperationDescription( + DrydockRepositoryOperation $operation, + PhabricatorUser $viewer) { + return pht('Land Revision'); + } + public function applyOperation( DrydockRepositoryOperation $operation, DrydockInterface $interface) { diff --git a/src/applications/drydock/operation/DrydockRepositoryOperationType.php b/src/applications/drydock/operation/DrydockRepositoryOperationType.php index 3ec8f8ba9e..a78ed3173e 100644 --- a/src/applications/drydock/operation/DrydockRepositoryOperationType.php +++ b/src/applications/drydock/operation/DrydockRepositoryOperationType.php @@ -8,6 +8,10 @@ abstract class DrydockRepositoryOperationType extends Phobject { DrydockRepositoryOperation $operation, DrydockInterface $interface); + abstract public function getOperationDescription( + DrydockRepositoryOperation $operation, + PhabricatorUser $viewer); + final public function setViewer(PhabricatorUser $viewer) { $this->viewer = $viewer; return $this; diff --git a/src/applications/drydock/query/DrydockRepositoryOperationSearchEngine.php b/src/applications/drydock/query/DrydockRepositoryOperationSearchEngine.php new file mode 100644 index 0000000000..c4befe8201 --- /dev/null +++ b/src/applications/drydock/query/DrydockRepositoryOperationSearchEngine.php @@ -0,0 +1,99 @@ +newQuery(); + + return $query; + } + + protected function buildCustomSearchFields() { + return array( + ); + } + + protected function getURI($path) { + return '/drydock/operation/'.$path; + } + + protected function getBuiltinQueryNames() { + return array( + 'all' => pht('All Operations'), + ); + } + + public function buildSavedQueryFromBuiltin($query_key) { + $query = $this->newSavedQuery(); + $query->setQueryKey($query_key); + + switch ($query_key) { + case 'all': + return $query; + } + + return parent::buildSavedQueryFromBuiltin($query_key); + } + + protected function renderResultList( + array $operations, + PhabricatorSavedQuery $query, + array $handles) { + assert_instances_of($operations, 'DrydockRepositoryOperation'); + + $viewer = $this->requireViewer(); + + $view = new PHUIObjectItemListView(); + foreach ($operations as $operation) { + $id = $operation->getID(); + + $item = id(new PHUIObjectItemView()) + ->setHeader($operation->getOperationDescription($viewer)) + ->setHref($this->getApplicationURI("operation/{$id}/")) + ->setObjectName(pht('Repository Operation %d', $id)); + + $state = $operation->getOperationState(); + + $icon = DrydockRepositoryOperation::getOperationStateIcon($state); + $name = DrydockRepositoryOperation::getOperationStateName($state); + + $item->addIcon($icon, $name); + $item->addByline( + array( + pht('Via:'), + ' ', + $viewer->renderHandle($operation->getAuthorPHID()), + )); + + $item->addAttribute( + $viewer->renderHandle( + $operation->getObjectPHID())); + + $item->addAttribute( + $viewer->renderHandle( + $operation->getRepositoryPHID())); + + $view->addItem($item); + } + + $result = id(new PhabricatorApplicationSearchResultView()) + ->setObjectList($view) + ->setNoDataString(pht('No matching operations.')); + + return $result; + } + +} diff --git a/src/applications/drydock/storage/DrydockRepositoryOperation.php b/src/applications/drydock/storage/DrydockRepositoryOperation.php index aed6b147fa..7a8e35ea68 100644 --- a/src/applications/drydock/storage/DrydockRepositoryOperation.php +++ b/src/applications/drydock/storage/DrydockRepositoryOperation.php @@ -136,6 +136,12 @@ final class DrydockRepositoryOperation extends DrydockDAO $interface); } + public function getOperationDescription(PhabricatorUser $viewer) { + return $this->getImplementation()->getOperationDescription( + $this, + $viewer); + } + /* -( PhabricatorPolicyInterface )----------------------------------------- */