@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 "Move Left" and "Move Right" to dashboard tab panels

Summary: Depends on D20474. Ref T13272. Provide an easy way to rearrange tabs on a tab panel, by moving them left or right from the context menu.

Test Plan: Moved tabs left and right. Tried to move them off the end of the tab list, no luck.

Reviewers: amckinley

Reviewed By: amckinley

Maniphest Tasks: T13272

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

+142 -10
+9
src/aphront/AphrontRequest.php
··· 383 383 return $this->validateCSRF(); 384 384 } 385 385 386 + public function hasCSRF() { 387 + try { 388 + $this->validateCSRF(); 389 + return true; 390 + } catch (AphrontMalformedRequestException $ex) { 391 + return false; 392 + } 393 + } 394 + 386 395 public function isFormOrHisecPost() { 387 396 $post = $this->getExists(self::TYPE_FORM) && 388 397 $this->isHTTPPost();
+84 -1
src/applications/dashboard/controller/panel/PhabricatorDashboardPanelTabsController.php
··· 140 140 case 'remove': 141 141 return $this->handleRemoveOperation($panel, $target, $cancel_uri); 142 142 case 'move': 143 - break; 143 + return $this->handleMoveOperation($panel, $target, $after, $cancel_uri); 144 144 case 'rename': 145 145 return $this->handleRenameOperation($panel, $target, $cancel_uri); 146 146 } ··· 298 298 ->addSubmitButton(pht('Rename Tab')); 299 299 } 300 300 301 + private function handleMoveOperation( 302 + PhabricatorDashboardPanel $panel, 303 + $target, 304 + $after, 305 + $cancel_uri) { 306 + $request = $this->getRequest(); 307 + $viewer = $this->getViewer(); 308 + 309 + $move = $request->getStr('move'); 310 + 311 + $impl = $panel->getImplementation(); 312 + $old_config = $impl->getPanelConfiguration($panel); 313 + 314 + $is_next = ($move === 'next'); 315 + if ($target === $after) { 316 + return $this->newDialog() 317 + ->setTitle(pht('Impossible!')) 318 + ->appendParagraph( 319 + pht( 320 + 'You can not move a tab relative to itself.')) 321 + ->addCancelButton($cancel_uri); 322 + } else if ($is_next && ((string)last_key($old_config) === $target)) { 323 + return $this->newDialog() 324 + ->setTitle(pht('Impossible!')) 325 + ->appendParagraph( 326 + pht( 327 + 'This is already the last tab. It can not move any farther to '. 328 + 'the right.')) 329 + ->addCancelButton($cancel_uri); 330 + } else if ((string)head_key($old_config) === $target) { 331 + return $this->newDialog() 332 + ->setTitle(pht('Impossible!')) 333 + ->appendParagraph( 334 + pht( 335 + 'This is already the first tab. It can not move any farther to '. 336 + 'the left.')) 337 + ->addCancelButton($cancel_uri); 338 + } 339 + 340 + if ($request->hasCSRF()) { 341 + $new_config = array(); 342 + foreach ($old_config as $old_key => $old_spec) { 343 + $old_key = (string)$old_key; 344 + 345 + $is_after = ($old_key === $after); 346 + 347 + if (!$is_after) { 348 + if ($old_key === $target) { 349 + continue; 350 + } 351 + } 352 + 353 + if ($is_after && !$is_next) { 354 + $new_config[$target] = $old_config[$target]; 355 + } 356 + 357 + $new_config[$old_key] = $old_spec; 358 + 359 + if ($is_after && $is_next) { 360 + $new_config[$target] = $old_config[$target]; 361 + } 362 + } 363 + 364 + $this->writePanelConfig($panel, $new_config); 365 + 366 + return id(new AphrontRedirectResponse())->setURI($cancel_uri); 367 + } 368 + 369 + if ($is_next) { 370 + $prompt = pht('Move this tab to the right?'); 371 + } else { 372 + $prompt = pht('Move this tab to the left?'); 373 + } 374 + 375 + return $this->newEditDialog() 376 + ->setTitle(pht('Move Tab')) 377 + ->addHiddenInput('target', $target) 378 + ->addHiddenInput('after', $after) 379 + ->addHiddenInput('move', $move) 380 + ->appendParagraph($prompt) 381 + ->addCancelButton($cancel_uri) 382 + ->addSubmitButton(pht('Move Tab')); 383 + } 301 384 302 385 private function writePanelConfig( 303 386 PhabricatorDashboardPanel $panel,
+48 -3
src/applications/dashboard/paneltype/PhabricatorDashboardTabsPanelType.php
··· 87 87 88 88 $selected = 0; 89 89 90 - $last_idx = null; 90 + $key_list = array_keys($config); 91 + 92 + $next_keys = array(); 93 + $prev_keys = array(); 94 + for ($ii = 0; $ii < count($key_list); $ii++) { 95 + $next_keys[$key_list[$ii]] = idx($key_list, $ii + 1); 96 + $prev_keys[$key_list[$ii]] = idx($key_list, $ii - 1); 97 + } 98 + 91 99 foreach ($config as $idx => $tab_spec) { 92 100 $panel_id = idx($tab_spec, 'panelID'); 93 101 $subpanel = idx($panels, $panel_id); ··· 145 153 ->setHref($rename_tab_uri) 146 154 ->setWorkflow(true)); 147 155 156 + $move_uri = urisprintf('/dashboard/panel/tabs/%d/move/', $id); 157 + 158 + $prev_key = $prev_keys[$idx]; 159 + $prev_params = array( 160 + 'target' => $idx, 161 + 'after' => $prev_key, 162 + 'move' => 'prev', 163 + 'contextPHID' => $context_phid, 164 + ); 165 + $prev_uri = new PhutilURI($move_uri, $prev_params); 166 + 167 + $next_key = $next_keys[$idx]; 168 + $next_params = array( 169 + 'target' => $idx, 170 + 'after' => $next_key, 171 + 'move' => 'next', 172 + 'contextPHID' => $context_phid, 173 + ); 174 + $next_uri = new PhutilURI($move_uri, $next_params); 175 + 176 + $dropdown_menu->addAction( 177 + id(new PhabricatorActionView()) 178 + ->setName(pht('Move Tab Left')) 179 + ->setIcon('fa-chevron-left') 180 + ->setHref($prev_uri) 181 + ->setWorkflow(true) 182 + ->setDisabled(($prev_key === null) || !$can_edit)); 183 + 184 + $dropdown_menu->addAction( 185 + id(new PhabricatorActionView()) 186 + ->setName(pht('Move Tab Right')) 187 + ->setIcon('fa-chevron-right') 188 + ->setHref($next_uri) 189 + ->setWorkflow(true) 190 + ->setDisabled(($next_key === null) || !$can_edit)); 191 + 148 192 $dropdown_menu->addAction( 149 193 id(new PhabricatorActionView()) 150 194 ->setName(pht('Remove Tab')) ··· 177 221 } 178 222 179 223 $list->addMenuItem($tab_view); 224 + } 180 225 181 - $last_idx = $idx; 182 - } 183 226 184 227 if ($is_edit) { 185 228 $actions = id(new PhabricatorActionListView()) 186 229 ->setViewer($viewer); 187 230 188 231 $add_last_uri = clone $add_uri; 232 + 233 + $last_idx = last_key($config); 189 234 if ($last_idx) { 190 235 $add_last_uri->replaceQueryParam('after', $last_idx); 191 236 }
+1 -6
src/applications/notification/controller/PhabricatorNotificationClearController.php
··· 10 10 if ($request->isDialogFormPost()) { 11 11 $should_clear = true; 12 12 } else { 13 - try { 14 - $request->validateCSRF(); 15 - $should_clear = true; 16 - } catch (AphrontMalformedRequestException $ex) { 17 - $should_clear = false; 18 - } 13 + $should_clear = $request->hasCSRF(); 19 14 } 20 15 21 16 if ($should_clear) {