@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Give Harbormaster build steps a "View" page

Summary:
Fixes T9519. Right now, build steps go straight from the build to the edit screen.

This means that there's no way to see their edit history or review details without edit permission. In particular, this makes it a bit harder to catch the Drydock Blueprint authorization warnings from T9519.

- Add a standard view screen.
- Add a little warning callout to blueprint authorizations.

This also does a bit of a touchup on the weird dropshadow element from T9586. Maybe not totally design-approved now but it's less ugly, at least.

Test Plan:
{F906695}

{F906696}

Reviewers: chad

Reviewed By: chad

Maniphest Tasks: T9519

Differential Revision: https://secure.phabricator.com/D14330

+175 -45
+2 -2
resources/celerity/map.php
··· 71 71 'rsrc/css/application/feed/feed.css' => 'ecd4ec57', 72 72 'rsrc/css/application/files/global-drag-and-drop.css' => '697324ad', 73 73 'rsrc/css/application/flag/flag.css' => '5337623f', 74 - 'rsrc/css/application/harbormaster/harbormaster.css' => '49d64eb4', 74 + 'rsrc/css/application/harbormaster/harbormaster.css' => 'b0758ca5', 75 75 'rsrc/css/application/herald/herald-test.css' => 'a52e323e', 76 76 'rsrc/css/application/herald/herald.css' => '826075fa', 77 77 'rsrc/css/application/maniphest/batch-editor.css' => 'b0f0b6d5', ··· 528 528 'font-lato' => '5ab1a46a', 529 529 'font-roboto-slab' => 'f24a53cb', 530 530 'global-drag-and-drop-css' => '697324ad', 531 - 'harbormaster-css' => '49d64eb4', 531 + 'harbormaster-css' => 'b0758ca5', 532 532 'herald-css' => '826075fa', 533 533 'herald-rule-editor' => '91a6031b', 534 534 'herald-test-css' => 'a52e323e',
+2
src/__phutil_library_map__.php
··· 1078 1078 'HarbormasterStepAddController' => 'applications/harbormaster/controller/HarbormasterStepAddController.php', 1079 1079 'HarbormasterStepDeleteController' => 'applications/harbormaster/controller/HarbormasterStepDeleteController.php', 1080 1080 'HarbormasterStepEditController' => 'applications/harbormaster/controller/HarbormasterStepEditController.php', 1081 + 'HarbormasterStepViewController' => 'applications/harbormaster/controller/HarbormasterStepViewController.php', 1081 1082 'HarbormasterTargetEngine' => 'applications/harbormaster/engine/HarbormasterTargetEngine.php', 1082 1083 'HarbormasterTargetWorker' => 'applications/harbormaster/worker/HarbormasterTargetWorker.php', 1083 1084 'HarbormasterTestBuildStepGroup' => 'applications/harbormaster/stepgroup/HarbormasterTestBuildStepGroup.php', ··· 4919 4920 'HarbormasterStepAddController' => 'HarbormasterController', 4920 4921 'HarbormasterStepDeleteController' => 'HarbormasterController', 4921 4922 'HarbormasterStepEditController' => 'HarbormasterController', 4923 + 'HarbormasterStepViewController' => 'HarbormasterController', 4922 4924 'HarbormasterTargetEngine' => 'Phobject', 4923 4925 'HarbormasterTargetWorker' => 'HarbormasterWorker', 4924 4926 'HarbormasterTestBuildStepGroup' => 'HarbormasterBuildStepGroup',
+1 -1
src/applications/drydock/storage/DrydockAuthorization.php
··· 66 66 67 67 public static function getBlueprintStateIcon($state) { 68 68 $map = array( 69 - self::BLUEPRINTAUTH_REQUESTED => 'fa-exclamation-circle indigo', 69 + self::BLUEPRINTAUTH_REQUESTED => 'fa-exclamation-circle pink', 70 70 self::BLUEPRINTAUTH_AUTHORIZED => 'fa-check-circle green', 71 71 self::BLUEPRINTAUTH_DECLINED => 'fa-times red', 72 72 );
+19
src/applications/drydock/view/DrydockObjectAuthorizationView.php
··· 47 47 $authorizations = array(); 48 48 } 49 49 50 + $warnings = array(); 50 51 $items = array(); 51 52 foreach ($blueprint_phids as $phid) { 52 53 $authorization = idx($authorizations, $phid); ··· 65 66 null, 66 67 DrydockAuthorization::getBlueprintStateName($state)); 67 68 69 + switch ($state) { 70 + case DrydockAuthorization::BLUEPRINTAUTH_REQUESTED: 71 + case DrydockAuthorization::BLUEPRINTAUTH_DECLINED: 72 + $warnings[] = $authorization; 73 + break; 74 + } 75 + 68 76 $items[] = $item; 69 77 } 70 78 71 79 $status = new PHUIStatusListView(); 80 + 81 + if ($warnings) { 82 + $status->addItem( 83 + id(new PHUIStatusItemView()) 84 + ->setIcon('fa-exclamation-triangle', 'pink') 85 + ->setTarget( 86 + pht( 87 + 'WARNING: There are %s unapproved authorization(s)!', 88 + new PhutilNumber(count($warnings))))); 89 + } 90 + 72 91 foreach ($items as $item) { 73 92 $status->addItem($item); 74 93 }
+1
src/applications/harbormaster/application/PhabricatorHarbormasterApplication.php
··· 61 61 'add/(?:(?P<id>\d+)/)?' => 'HarbormasterStepAddController', 62 62 'new/(?P<plan>\d+)/(?P<class>[^/]+)/' 63 63 => 'HarbormasterStepEditController', 64 + 'view/(?P<id>\d+)/' => 'HarbormasterStepViewController', 64 65 'edit/(?:(?P<id>\d+)/)?' => 'HarbormasterStepEditController', 65 66 'delete/(?:(?P<id>\d+)/)?' => 'HarbormasterStepDeleteController', 66 67 ),
+3 -26
src/applications/harbormaster/controller/HarbormasterPlanViewController.php
··· 117 117 ->setStatusIcon('fa-warning red') 118 118 ->addAttribute(pht( 119 119 'This step has an invalid implementation (%s).', 120 - $step->getClassName())) 121 - ->addAction( 122 - id(new PHUIListItemView()) 123 - ->setIcon('fa-times') 124 - ->addSigil('harbormaster-build-step-delete') 125 - ->setWorkflow(true) 126 - ->setRenderNameAsTooltip(true) 127 - ->setName(pht('Delete')) 128 - ->setHref( 129 - $this->getApplicationURI('step/delete/'.$step->getID().'/'))); 120 + $step->getClassName())); 130 121 $step_list->addItem($item); 131 122 continue; 132 123 } ··· 137 128 $item->addAttribute($implementation->getDescription()); 138 129 139 130 $step_id = $step->getID(); 140 - $edit_uri = $this->getApplicationURI("step/edit/{$step_id}/"); 141 - $delete_uri = $this->getApplicationURI("step/delete/{$step_id}/"); 142 131 143 - if ($can_edit) { 144 - $item->setHref($edit_uri); 145 - } 146 - 147 - $item 148 - ->setHref($edit_uri) 149 - ->addAction( 150 - id(new PHUIListItemView()) 151 - ->setIcon('fa-times') 152 - ->addSigil('harbormaster-build-step-delete') 153 - ->setWorkflow(true) 154 - ->setDisabled(!$can_edit) 155 - ->setHref( 156 - $this->getApplicationURI('step/delete/'.$step->getID().'/'))); 132 + $view_uri = $this->getApplicationURI("step/view/{$step_id}/"); 133 + $item->setHref($view_uri); 157 134 158 135 $depends = $step->getStepImplementation()->getDependencies($step); 159 136 $inputs = $step->getStepImplementation()->getArtifactInputs();
+18 -9
src/applications/harbormaster/controller/HarbormasterStepEditController.php
··· 58 58 59 59 $plan_uri = $this->getApplicationURI('plan/'.$plan->getID().'/'); 60 60 61 + if ($is_new) { 62 + $cancel_uri = $plan_uri; 63 + } else { 64 + $cancel_uri = $this->getApplicationURI('step/view/'.$step->getID().'/'); 65 + } 66 + 61 67 $implementation = $step->getStepImplementation(); 62 68 63 69 $field_list = PhabricatorCustomField::getObjectFields( ··· 119 125 120 126 try { 121 127 $editor->applyTransactions($step, $xactions); 122 - return id(new AphrontRedirectResponse())->setURI($plan_uri); 128 + 129 + $step_uri = $this->getApplicationURI('step/view/'.$step->getID().'/'); 130 + 131 + return id(new AphrontRedirectResponse())->setURI($step_uri); 123 132 } catch (PhabricatorApplicationTransactionValidationException $ex) { 124 133 $validation_exception = $ex; 125 134 } ··· 162 171 ->setError($e_description) 163 172 ->setValue($v_description)); 164 173 174 + $crumbs = $this->buildApplicationCrumbs(); 175 + $id = $plan->getID(); 176 + $crumbs->addTextCrumb(pht('Plan %d', $id), $plan_uri); 177 + 165 178 if ($is_new) { 166 179 $submit = pht('Create Build Step'); 167 180 $header = pht('New Step: %s', $implementation->getName()); 168 - $crumb = pht('Add Step'); 181 + $crumbs->addTextCrumb(pht('Add Step')); 169 182 } else { 170 183 $submit = pht('Save Build Step'); 171 184 $header = pht('Edit Step: %s', $implementation->getName()); 172 - $crumb = pht('Edit Step'); 185 + $crumbs->addTextCrumb(pht('Step %d', $step->getID()), $cancel_uri); 186 + $crumbs->addTextCrumb(pht('Edit Step')); 173 187 } 174 188 175 189 $form->appendChild( 176 190 id(new AphrontFormSubmitControl()) 177 191 ->setValue($submit) 178 - ->addCancelButton($plan_uri)); 192 + ->addCancelButton($cancel_uri)); 179 193 180 194 $box = id(new PHUIObjectBoxView()) 181 195 ->setHeaderText($header) 182 196 ->setValidationException($validation_exception) 183 197 ->setForm($form); 184 - 185 - $crumbs = $this->buildApplicationCrumbs(); 186 - $id = $plan->getID(); 187 - $crumbs->addTextCrumb(pht('Plan %d', $id), $plan_uri); 188 - $crumbs->addTextCrumb($crumb); 189 198 190 199 $variables = $this->renderBuildVariablesTable(); 191 200
+122
src/applications/harbormaster/controller/HarbormasterStepViewController.php
··· 1 + <?php 2 + 3 + final class HarbormasterStepViewController extends HarbormasterController { 4 + 5 + public function handleRequest(AphrontRequest $request) { 6 + $viewer = $this->getViewer(); 7 + $id = $request->getURIData('id'); 8 + 9 + $step = id(new HarbormasterBuildStepQuery()) 10 + ->setViewer($viewer) 11 + ->withIDs(array($id)) 12 + ->executeOne(); 13 + if (!$step) { 14 + return new Aphront404Response(); 15 + } 16 + $plan = $step->getBuildPlan(); 17 + 18 + $plan_id = $plan->getID(); 19 + $plan_uri = $this->getApplicationURI("plan/{$plan_id}/"); 20 + 21 + $implementation = $step->getStepImplementation(); 22 + 23 + $field_list = PhabricatorCustomField::getObjectFields( 24 + $step, 25 + PhabricatorCustomField::ROLE_VIEW); 26 + $field_list 27 + ->setViewer($viewer) 28 + ->readFieldsFromStorage($step); 29 + 30 + $crumbs = $this->buildApplicationCrumbs(); 31 + $crumbs->addTextCrumb(pht('Plan %d', $plan_id), $plan_uri); 32 + $crumbs->addTextCrumb(pht('Step %d', $id)); 33 + 34 + $box = id(new PHUIObjectBoxView()) 35 + ->setHeaderText(pht('Build Step %d: %s', $id, $step->getName())); 36 + 37 + $properties = $this->buildPropertyList($step, $field_list); 38 + $actions = $this->buildActionList($step); 39 + $properties->setActionList($actions); 40 + 41 + $box->addPropertyList($properties); 42 + 43 + $timeline = $this->buildTransactionTimeline( 44 + $step, 45 + new HarbormasterBuildStepTransactionQuery()); 46 + $timeline->setShouldTerminate(true); 47 + 48 + return $this->buildApplicationPage( 49 + array( 50 + $crumbs, 51 + $box, 52 + $timeline, 53 + ), 54 + array( 55 + 'title' => pht('Step %d', $id), 56 + )); 57 + } 58 + 59 + private function buildPropertyList( 60 + HarbormasterBuildStep $step, 61 + PhabricatorCustomFieldList $field_list) { 62 + $viewer = $this->getViewer(); 63 + 64 + $view = id(new PHUIPropertyListView()) 65 + ->setUser($viewer) 66 + ->setObject($step); 67 + 68 + $view->addProperty( 69 + pht('Created'), 70 + phabricator_datetime($step->getDateCreated(), $viewer)); 71 + 72 + $field_list->appendFieldsToPropertyList( 73 + $step, 74 + $viewer, 75 + $view); 76 + 77 + $view->invokeWillRenderEvent(); 78 + 79 + $description = $step->getDescription(); 80 + if (strlen($description)) { 81 + $view->addSectionHeader( 82 + pht('Description'), 83 + PHUIPropertyListView::ICON_SUMMARY); 84 + $view->addTextContent( 85 + new PHUIRemarkupView($viewer, $description)); 86 + } 87 + 88 + return $view; 89 + } 90 + 91 + 92 + private function buildActionList(HarbormasterBuildStep $step) { 93 + $viewer = $this->getViewer(); 94 + $id = $step->getID(); 95 + 96 + $list = id(new PhabricatorActionListView()) 97 + ->setUser($viewer) 98 + ->setObject($step); 99 + 100 + $can_edit = true; 101 + 102 + $list->addAction( 103 + id(new PhabricatorActionView()) 104 + ->setName(pht('Edit Step')) 105 + ->setHref($this->getApplicationURI("step/edit/{$id}/")) 106 + ->setWorkflow(!$can_edit) 107 + ->setDisabled(!$can_edit) 108 + ->setIcon('fa-pencil')); 109 + 110 + $list->addAction( 111 + id(new PhabricatorActionView()) 112 + ->setName(pht('Delete Step')) 113 + ->setHref($this->getApplicationURI("step/delete/{$id}/")) 114 + ->setWorkflow(true) 115 + ->setDisabled(!$can_edit) 116 + ->setIcon('fa-times')); 117 + 118 + return $list; 119 + } 120 + 121 + 122 + }
+5
src/infrastructure/internationalization/translation/PhabricatorUSEnglishTranslation.php
··· 1420 1420 ), 1421 1421 ), 1422 1422 1423 + 'WARNING: There are %s unapproved authorization(s)!' => array( 1424 + 'WARNING: There is an unapproved authorization!', 1425 + 'WARNING: There are unapproved authorizations!', 1426 + ), 1427 + 1423 1428 ); 1424 1429 } 1425 1430
+2 -7
webroot/rsrc/css/application/harbormaster/harbormaster.css
··· 3 3 */ 4 4 5 5 .harbormaster-artifact-io { 6 - margin: 0 0 0 8px; 7 - padding: 4px 8px; 8 - border-width: 1px 0 0 1px; 9 - border-style: solid; 10 - box-shadow: inset 2px 2px 1px rgba(0, 0, 0, 0.075); 11 - background: {$lightbluebackground}; 12 - border-color: {$lightblueborder}; 6 + margin: 4px 0 4px 8px; 7 + padding: 8px; 13 8 } 14 9 15 10 .harbormaster-artifact-summary-header {