@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.

Add a "Customize Query" action to query panels to make it easier to make minor query adjustments

Summary:
Depends on D20473. Ref T13272. Fixes T7216. If you want to tweak the query a panel uses, you currently have to complete 7 Great Labors.

Instead, add a "Customize Query" action which lets you update the query inline.

Test Plan: {F6402171}

Reviewers: amckinley

Reviewed By: amckinley

Maniphest Tasks: T13272, T7216

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

+169
+12
src/applications/dashboard/engine/PhabricatorDashboardPanelRenderingEngine.php
··· 329 329 $actions = array(); 330 330 331 331 if ($panel) { 332 + $panel_actions = $panel->newHeaderEditActions( 333 + $viewer, 334 + $context_phid); 335 + 336 + if ($panel_actions) { 337 + foreach ($panel_actions as $panel_action) { 338 + $actions[] = $panel_action; 339 + } 340 + $actions[] = id(new PhabricatorActionView()) 341 + ->setType(PhabricatorActionView::TYPE_DIVIDER); 342 + } 343 + 332 344 $panel_id = $panel->getID(); 333 345 334 346 $edit_uri = "/dashboard/panel/edit/{$panel_id}/";
+7
src/applications/dashboard/paneltype/PhabricatorDashboardPanelType.php
··· 63 63 return array(); 64 64 } 65 65 66 + public function newHeaderEditActions( 67 + PhabricatorDashboardPanel $panel, 68 + PhabricatorUser $viewer, 69 + $context_phid) { 70 + return array(); 71 + } 72 + 66 73 }
+22
src/applications/dashboard/paneltype/PhabricatorDashboardQueryPanelType.php
··· 236 236 return $engine; 237 237 } 238 238 239 + public function newHeaderEditActions( 240 + PhabricatorDashboardPanel $panel, 241 + PhabricatorUser $viewer, 242 + $context_phid) { 243 + $actions = array(); 244 + 245 + $engine = $this->getSearchEngine($panel); 246 + 247 + $customize_uri = $engine->getCustomizeURI( 248 + $panel->getProperty('key'), 249 + $panel->getPHID(), 250 + $context_phid); 251 + 252 + $actions[] = id(new PhabricatorActionView()) 253 + ->setIcon('fa-pencil-square-o') 254 + ->setName(pht('Customize Query')) 255 + ->setWorkflow(true) 256 + ->setHref($customize_uri); 257 + 258 + return $actions; 259 + } 260 + 239 261 }
+9
src/applications/dashboard/storage/PhabricatorDashboardPanel.php
··· 107 107 return $this->requireImplementation()->getEditEngineFields($this); 108 108 } 109 109 110 + public function newHeaderEditActions( 111 + PhabricatorUser $viewer, 112 + $context_phid) { 113 + return $this->requireImplementation()->newHeaderEditActions( 114 + $this, 115 + $viewer, 116 + $context_phid); 117 + } 118 + 110 119 111 120 /* -( PhabricatorApplicationTransactionInterface )------------------------- */ 112 121
+106
src/applications/search/controller/PhabricatorApplicationSearchController.php
··· 80 80 return $this->processExportRequest(); 81 81 } 82 82 83 + if ($query_action === 'customize') { 84 + return $this->processCustomizeRequest(); 85 + } 86 + 83 87 $key = $this->getQueryKey(); 84 88 if ($key == 'edit') { 85 89 return $this->processEditRequest(); ··· 985 989 $editor->applyTransactions($preferences, $xactions); 986 990 } 987 991 992 + private function processCustomizeRequest() { 993 + $viewer = $this->getViewer(); 994 + $engine = $this->getSearchEngine(); 995 + $request = $this->getRequest(); 996 + 997 + $object_phid = $request->getStr('search.objectPHID'); 998 + $context_phid = $request->getStr('search.contextPHID'); 999 + 1000 + // For now, the object can only be a dashboard panel, so just use a panel 1001 + // query explicitly. 1002 + $object = id(new PhabricatorDashboardPanelQuery()) 1003 + ->setViewer($viewer) 1004 + ->withPHIDs(array($object_phid)) 1005 + ->requireCapabilities( 1006 + array( 1007 + PhabricatorPolicyCapability::CAN_VIEW, 1008 + PhabricatorPolicyCapability::CAN_EDIT, 1009 + )) 1010 + ->executeOne(); 1011 + if (!$object) { 1012 + return new Aphront404Response(); 1013 + } 1014 + 1015 + $object_name = pht('%s %s', $object->getMonogram(), $object->getName()); 1016 + 1017 + // Likewise, the context object can only be a dashboard. 1018 + if (strlen($context_phid)) { 1019 + $context = id(new PhabricatorDashboardQuery()) 1020 + ->setViewer($viewer) 1021 + ->withPHIDs(array($context_phid)) 1022 + ->executeOne(); 1023 + if (!$context) { 1024 + return new Aphront404Response(); 1025 + } 1026 + } else { 1027 + $context = $object; 1028 + } 1029 + 1030 + $done_uri = $context->getURI(); 1031 + 1032 + if ($request->isFormPost()) { 1033 + $saved_query = $engine->buildSavedQueryFromRequest($request); 1034 + $engine->saveQuery($saved_query); 1035 + $query_key = $saved_query->getQueryKey(); 1036 + } else { 1037 + $query_key = $this->getQueryKey(); 1038 + if ($engine->isBuiltinQuery($query_key)) { 1039 + $saved_query = $engine->buildSavedQueryFromBuiltin($query_key); 1040 + } else if ($query_key) { 1041 + $saved_query = id(new PhabricatorSavedQueryQuery()) 1042 + ->setViewer($viewer) 1043 + ->withQueryKeys(array($query_key)) 1044 + ->executeOne(); 1045 + } else { 1046 + $saved_query = null; 1047 + } 1048 + } 1049 + 1050 + if (!$saved_query) { 1051 + return new Aphront404Response(); 1052 + } 1053 + 1054 + $form = id(new AphrontFormView()) 1055 + ->setViewer($viewer) 1056 + ->addHiddenInput('search.objectPHID', $object_phid) 1057 + ->addHiddenInput('search.contextPHID', $context_phid) 1058 + ->setAction($request->getPath()); 1059 + 1060 + $engine->buildSearchForm($form, $saved_query); 1061 + 1062 + $errors = $engine->getErrors(); 1063 + if ($request->isFormPost()) { 1064 + if (!$errors) { 1065 + $xactions = array(); 1066 + 1067 + // Since this workflow is currently used only by dashboard panels, 1068 + // we can hard-code how the edit works. 1069 + $xactions[] = $object->getApplicationTransactionTemplate() 1070 + ->setTransactionType( 1071 + PhabricatorDashboardQueryPanelQueryTransaction::TRANSACTIONTYPE) 1072 + ->setNewValue($query_key); 1073 + 1074 + $editor = $object->getApplicationTransactionEditor() 1075 + ->setActor($viewer) 1076 + ->setContentSourceFromRequest($request) 1077 + ->setContinueOnNoEffect(true) 1078 + ->setContinueOnMissingFields(true); 1079 + 1080 + $editor->applyTransactions($object, $xactions); 1081 + 1082 + return id(new AphrontRedirectResponse())->setURI($done_uri); 1083 + } 1084 + } 1085 + 1086 + return $this->newDialog() 1087 + ->setTitle(pht('Customize Query: %s', $object_name)) 1088 + ->setErrors($errors) 1089 + ->setWidth(AphrontDialogView::WIDTH_FULL) 1090 + ->appendForm($form) 1091 + ->addCancelButton($done_uri) 1092 + ->addSubmitButton(pht('Save Changes')); 1093 + } 988 1094 }
+13
src/applications/search/engine/PhabricatorApplicationSearchEngine.php
··· 425 425 return $this->getURI('query/'.$query_key.'/export/'); 426 426 } 427 427 428 + public function getCustomizeURI($query_key, $object_phid, $context_phid) { 429 + $params = array( 430 + 'search.objectPHID' => $object_phid, 431 + 'search.contextPHID' => $context_phid, 432 + ); 433 + 434 + $uri = $this->getURI('query/'.$query_key.'/customize/'); 435 + $uri = new PhutilURI($uri, $params); 436 + 437 + return phutil_string_cast($uri); 438 + } 439 + 440 + 428 441 429 442 /** 430 443 * Return the URI to a path within the application. Used to construct default