diff --git a/src/applications/drydock/controller/DrydockBlueprintViewController.php b/src/applications/drydock/controller/DrydockBlueprintViewController.php index 33a27264b8..5da92539cf 100644 --- a/src/applications/drydock/controller/DrydockBlueprintViewController.php +++ b/src/applications/drydock/controller/DrydockBlueprintViewController.php @@ -1,123 +1,127 @@ getViewer(); $id = $request->getURIData('id'); $blueprint = id(new DrydockBlueprintQuery()) ->setViewer($viewer) ->withIDs(array($id)) ->executeOne(); if (!$blueprint) { return new Aphront404Response(); } $title = $blueprint->getBlueprintName(); $header = id(new PHUIHeaderView()) ->setHeader($title) ->setUser($viewer) ->setPolicyObject($blueprint); $actions = $this->buildActionListView($blueprint); $properties = $this->buildPropertyListView($blueprint, $actions); $blueprint_uri = 'blueprint/'.$blueprint->getID().'/'; $blueprint_uri = $this->getApplicationURI($blueprint_uri); $resources = id(new DrydockResourceQuery()) ->withBlueprintPHIDs(array($blueprint->getPHID())) ->setViewer($viewer) ->execute(); $resource_list = id(new DrydockResourceListView()) ->setUser($viewer) ->setResources($resources) ->render(); $resource_list->setNoDataString(pht('This blueprint has no resources.')); $pager = new PHUIPagerView(); $pager->setURI(new PhutilURI($blueprint_uri), 'offset'); $pager->setOffset($request->getInt('offset')); $crumbs = $this->buildApplicationCrumbs(); $crumbs->addTextCrumb(pht('Blueprint %d', $blueprint->getID())); $object_box = id(new PHUIObjectBoxView()) ->setHeader($header) ->addPropertyList($properties); $field_list = PhabricatorCustomField::getObjectFields( $blueprint, PhabricatorCustomField::ROLE_VIEW); $field_list ->setViewer($viewer) ->readFieldsFromStorage($blueprint); $field_list->appendFieldsToPropertyList( $blueprint, $viewer, $properties); + $resource_box = id(new PHUIObjectBoxView()) + ->setHeaderText(pht('Resources')) + ->setObjectList($resource_list); + $timeline = $this->buildTransactionTimeline( $blueprint, new DrydockBlueprintTransactionQuery()); $timeline->setShouldTerminate(true); return $this->buildApplicationPage( array( $crumbs, $object_box, - $resource_list, + $resource_box, $timeline, ), array( 'title' => $title, )); } private function buildActionListView(DrydockBlueprint $blueprint) { $viewer = $this->getRequest()->getUser(); $view = id(new PhabricatorActionListView()) ->setUser($viewer) ->setObjectURI($this->getRequest()->getRequestURI()) ->setObject($blueprint); $uri = '/blueprint/edit/'.$blueprint->getID().'/'; $uri = $this->getApplicationURI($uri); $can_edit = PhabricatorPolicyFilter::hasCapability( $viewer, $blueprint, PhabricatorPolicyCapability::CAN_EDIT); $view->addAction( id(new PhabricatorActionView()) ->setHref($uri) ->setName(pht('Edit Blueprint')) ->setIcon('fa-pencil') ->setWorkflow(!$can_edit) ->setDisabled(!$can_edit)); return $view; } private function buildPropertyListView( DrydockBlueprint $blueprint, PhabricatorActionListView $actions) { $view = new PHUIPropertyListView(); $view->setActionList($actions); $view->addProperty( pht('Type'), $blueprint->getImplementation()->getBlueprintName()); return $view; } } diff --git a/src/applications/drydock/controller/DrydockController.php b/src/applications/drydock/controller/DrydockController.php index c2fa3dae72..3e3d83cc1d 100644 --- a/src/applications/drydock/controller/DrydockController.php +++ b/src/applications/drydock/controller/DrydockController.php @@ -1,11 +1,39 @@ buildSideNavView()->getMenu(); } + protected function buildLocksTab($owner_phid) { + $locks = DrydockSlotLock::loadLocks($owner_phid); + + $rows = array(); + foreach ($locks as $lock) { + $rows[] = array( + $lock->getID(), + $lock->getLockKey(), + ); + } + + $table = id(new AphrontTableView($rows)) + ->setNoDataString(pht('No slot locks held.')) + ->setHeaders( + array( + pht('ID'), + pht('Lock Key'), + )) + ->setColumnClasses( + array( + null, + 'wide', + )); + + return id(new PHUIPropertyListView()) + ->addRawContent($table); + } + } diff --git a/src/applications/drydock/controller/DrydockLeaseViewController.php b/src/applications/drydock/controller/DrydockLeaseViewController.php index 562e466311..aed1f6416f 100644 --- a/src/applications/drydock/controller/DrydockLeaseViewController.php +++ b/src/applications/drydock/controller/DrydockLeaseViewController.php @@ -1,134 +1,141 @@ getViewer(); $id = $request->getURIData('id'); $lease = id(new DrydockLeaseQuery()) ->setViewer($viewer) ->withIDs(array($id)) ->executeOne(); if (!$lease) { return new Aphront404Response(); } $lease_uri = $this->getApplicationURI('lease/'.$lease->getID().'/'); $title = pht('Lease %d', $lease->getID()); $header = id(new PHUIHeaderView()) ->setHeader($title); $actions = $this->buildActionListView($lease); $properties = $this->buildPropertyListView($lease, $actions); $pager = new PHUIPagerView(); $pager->setURI(new PhutilURI($lease_uri), 'offset'); $pager->setOffset($request->getInt('offset')); $logs = id(new DrydockLogQuery()) ->setViewer($viewer) ->withLeaseIDs(array($lease->getID())) ->executeWithOffsetPager($pager); $log_table = id(new DrydockLogListView()) ->setUser($viewer) ->setLogs($logs) ->render(); $log_table->appendChild($pager); $crumbs = $this->buildApplicationCrumbs(); $crumbs->addTextCrumb($title, $lease_uri); + $locks = $this->buildLocksTab($lease->getPHID()); + $object_box = id(new PHUIObjectBoxView()) ->setHeader($header) - ->addPropertyList($properties); + ->addPropertyList($properties, pht('Properties')) + ->addPropertyList($locks, pht('Slot Locks')); + + $log_box = id(new PHUIObjectBoxView()) + ->setHeaderText(pht('Lease Logs')) + ->setTable($log_table); return $this->buildApplicationPage( array( $crumbs, $object_box, - $log_table, + $log_box, ), array( - 'title' => $title, + 'title' => $title, )); } private function buildActionListView(DrydockLease $lease) { $view = id(new PhabricatorActionListView()) ->setUser($this->getRequest()->getUser()) ->setObjectURI($this->getRequest()->getRequestURI()) ->setObject($lease); $id = $lease->getID(); $can_release = ($lease->getStatus() == DrydockLeaseStatus::STATUS_ACTIVE); $view->addAction( id(new PhabricatorActionView()) ->setName(pht('Release Lease')) ->setIcon('fa-times') ->setHref($this->getApplicationURI("/lease/{$id}/release/")) ->setWorkflow(true) ->setDisabled(!$can_release)); return $view; } private function buildPropertyListView( DrydockLease $lease, PhabricatorActionListView $actions) { $view = new PHUIPropertyListView(); $view->setActionList($actions); switch ($lease->getStatus()) { case DrydockLeaseStatus::STATUS_ACTIVE: $status = pht('Active'); break; case DrydockLeaseStatus::STATUS_RELEASED: $status = pht('Released'); break; case DrydockLeaseStatus::STATUS_EXPIRED: $status = pht('Expired'); break; case DrydockLeaseStatus::STATUS_PENDING: $status = pht('Pending'); break; case DrydockLeaseStatus::STATUS_BROKEN: $status = pht('Broken'); break; default: $status = pht('Unknown'); break; } $view->addProperty( pht('Status'), $status); $view->addProperty( pht('Resource Type'), $lease->getResourceType()); $view->addProperty( pht('Resource'), $lease->getResourceID()); $attributes = $lease->getAttributes(); if ($attributes) { $view->addSectionHeader( pht('Attributes'), 'fa-list-ul'); foreach ($attributes as $key => $value) { $view->addProperty($key, $value); } } return $view; } } diff --git a/src/applications/drydock/controller/DrydockResourceViewController.php b/src/applications/drydock/controller/DrydockResourceViewController.php index afa0fb49fd..d4a37af33c 100644 --- a/src/applications/drydock/controller/DrydockResourceViewController.php +++ b/src/applications/drydock/controller/DrydockResourceViewController.php @@ -1,130 +1,141 @@ getViewer(); $id = $request->getURIData('id'); $resource = id(new DrydockResourceQuery()) ->setViewer($viewer) ->withIDs(array($id)) ->executeOne(); if (!$resource) { return new Aphront404Response(); } $title = pht('Resource %s %s', $resource->getID(), $resource->getName()); $header = id(new PHUIHeaderView()) ->setHeader($title); $actions = $this->buildActionListView($resource); $properties = $this->buildPropertyListView($resource, $actions); $resource_uri = 'resource/'.$resource->getID().'/'; $resource_uri = $this->getApplicationURI($resource_uri); $leases = id(new DrydockLeaseQuery()) ->setViewer($viewer) ->withResourceIDs(array($resource->getID())) ->execute(); $lease_list = id(new DrydockLeaseListView()) ->setUser($viewer) ->setLeases($leases) ->render(); $lease_list->setNoDataString(pht('This resource has no leases.')); $pager = new PHUIPagerView(); $pager->setURI(new PhutilURI($resource_uri), 'offset'); $pager->setOffset($request->getInt('offset')); $logs = id(new DrydockLogQuery()) ->setViewer($viewer) ->withResourceIDs(array($resource->getID())) ->executeWithOffsetPager($pager); $log_table = id(new DrydockLogListView()) ->setUser($viewer) ->setLogs($logs) ->render(); $log_table->appendChild($pager); $crumbs = $this->buildApplicationCrumbs(); $crumbs->addTextCrumb(pht('Resource %d', $resource->getID())); + $locks = $this->buildLocksTab($resource->getPHID()); + $object_box = id(new PHUIObjectBoxView()) ->setHeader($header) - ->addPropertyList($properties); + ->addPropertyList($properties, pht('Properties')) + ->addPropertyList($locks, pht('Slot Locks')); + + $lease_box = id(new PHUIObjectBoxView()) + ->setHeaderText(pht('Leases')) + ->setObjectList($lease_list); + + $log_box = id(new PHUIObjectBoxView()) + ->setHeaderText(pht('Resource Logs')) + ->setTable($log_table); return $this->buildApplicationPage( array( $crumbs, $object_box, - $lease_list, - $log_table, + $lease_box, + $log_box, ), array( 'title' => $title, )); } private function buildActionListView(DrydockResource $resource) { $view = id(new PhabricatorActionListView()) ->setUser($this->getRequest()->getUser()) ->setObjectURI($this->getRequest()->getRequestURI()) ->setObject($resource); $can_close = ($resource->getStatus() == DrydockResourceStatus::STATUS_OPEN); $uri = '/resource/'.$resource->getID().'/close/'; $uri = $this->getApplicationURI($uri); $view->addAction( id(new PhabricatorActionView()) ->setHref($uri) ->setName(pht('Close Resource')) ->setIcon('fa-times') ->setWorkflow(true) ->setDisabled(!$can_close)); return $view; } private function buildPropertyListView( DrydockResource $resource, PhabricatorActionListView $actions) { + $viewer = $this->getViewer(); $view = new PHUIPropertyListView(); $view->setActionList($actions); $status = $resource->getStatus(); $status = DrydockResourceStatus::getNameForStatus($status); $view->addProperty( pht('Status'), $status); $view->addProperty( pht('Resource Type'), $resource->getType()); - // TODO: Load handle. $view->addProperty( pht('Blueprint'), - $resource->getBlueprintPHID()); + $viewer->renderHandle($resource->getBlueprintPHID())); $attributes = $resource->getAttributes(); if ($attributes) { $view->addSectionHeader( pht('Attributes'), 'fa-list-ul'); foreach ($attributes as $key => $value) { $view->addProperty($key, $value); } } return $view; } } diff --git a/src/applications/drydock/phid/DrydockBlueprintPHIDType.php b/src/applications/drydock/phid/DrydockBlueprintPHIDType.php index b61eb396b9..86eeb7f3c5 100644 --- a/src/applications/drydock/phid/DrydockBlueprintPHIDType.php +++ b/src/applications/drydock/phid/DrydockBlueprintPHIDType.php @@ -1,36 +1,37 @@ withPHIDs($phids); } public function loadHandles( PhabricatorHandleQuery $query, array $handles, array $objects) { foreach ($handles as $phid => $handle) { $blueprint = $objects[$phid]; $id = $blueprint->getID(); + $handle->setName($blueprint->getBlueprintName()); $handle->setURI("/drydock/blueprint/{$id}/"); } } }