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

Implement ApplicationSearch in Flags

Summary:
Ref T1809. Provide ApplicationSearch to Flags and allow the user to select flags by color.

@chad might have some design feedback on my control.

Test Plan: {F54131}

Reviewers: btrahan, chad

Reviewed By: chad

CC: aran

Maniphest Tasks: T1809

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

+304 -195
+67 -67
src/__celerity_resource_map__.php
··· 1617 1617 ), 1618 1618 'javelin-behavior-differential-toggle-files' => 1619 1619 array( 1620 - 'uri' => '/res/2b266946/rsrc/js/application/differential/behavior-toggle-files.js', 1620 + 'uri' => '/res/beb89813/rsrc/js/application/differential/behavior-toggle-files.js', 1621 1621 'type' => 'js', 1622 1622 'requires' => 1623 1623 array( ··· 3174 3174 ), 3175 3175 'phabricator-flag-css' => 3176 3176 array( 3177 - 'uri' => '/res/237234d7/rsrc/css/application/flag/flag.css', 3177 + 'uri' => '/res/7c3dd9ea/rsrc/css/application/flag/flag.css', 3178 3178 'type' => 'css', 3179 3179 'requires' => 3180 3180 array( ··· 4172 4172 ), array( 4173 4173 'packages' => 4174 4174 array( 4175 - '638c9d42' => 4175 + '566968f8' => 4176 4176 array( 4177 4177 'name' => 'core.pkg.css', 4178 4178 'symbols' => ··· 4220 4220 40 => 'phabricator-property-list-view-css', 4221 4221 41 => 'phabricator-tag-view-css', 4222 4222 ), 4223 - 'uri' => '/res/pkg/638c9d42/core.pkg.css', 4223 + 'uri' => '/res/pkg/566968f8/core.pkg.css', 4224 4224 'type' => 'css', 4225 4225 ), 4226 4226 '4f81c788' => ··· 4302 4302 'uri' => '/res/pkg/09216861/differential.pkg.css', 4303 4303 'type' => 'css', 4304 4304 ), 4305 - '025bdd77' => 4305 + 'd07a3bc2' => 4306 4306 array( 4307 4307 'name' => 'differential.pkg.js', 4308 4308 'symbols' => ··· 4327 4327 17 => 'javelin-behavior-differential-toggle-files', 4328 4328 18 => 'javelin-behavior-differential-user-select', 4329 4329 ), 4330 - 'uri' => '/res/pkg/025bdd77/differential.pkg.js', 4330 + 'uri' => '/res/pkg/d07a3bc2/differential.pkg.js', 4331 4331 'type' => 'js', 4332 4332 ), 4333 4333 'c8ce2d88' => ··· 4411 4411 ), 4412 4412 'reverse' => 4413 4413 array( 4414 - 'aphront-dialog-view-css' => '638c9d42', 4415 - 'aphront-error-view-css' => '638c9d42', 4416 - 'aphront-form-view-css' => '638c9d42', 4417 - 'aphront-list-filter-view-css' => '638c9d42', 4418 - 'aphront-pager-view-css' => '638c9d42', 4419 - 'aphront-panel-view-css' => '638c9d42', 4420 - 'aphront-table-view-css' => '638c9d42', 4421 - 'aphront-tokenizer-control-css' => '638c9d42', 4422 - 'aphront-tooltip-css' => '638c9d42', 4423 - 'aphront-typeahead-control-css' => '638c9d42', 4414 + 'aphront-dialog-view-css' => '566968f8', 4415 + 'aphront-error-view-css' => '566968f8', 4416 + 'aphront-form-view-css' => '566968f8', 4417 + 'aphront-list-filter-view-css' => '566968f8', 4418 + 'aphront-pager-view-css' => '566968f8', 4419 + 'aphront-panel-view-css' => '566968f8', 4420 + 'aphront-table-view-css' => '566968f8', 4421 + 'aphront-tokenizer-control-css' => '566968f8', 4422 + 'aphront-tooltip-css' => '566968f8', 4423 + 'aphront-typeahead-control-css' => '566968f8', 4424 4424 'differential-changeset-view-css' => '09216861', 4425 4425 'differential-core-view-css' => '09216861', 4426 - 'differential-inline-comment-editor' => '025bdd77', 4426 + 'differential-inline-comment-editor' => 'd07a3bc2', 4427 4427 'differential-local-commits-view-css' => '09216861', 4428 4428 'differential-results-table-css' => '09216861', 4429 4429 'differential-revision-add-comment-css' => '09216861', ··· 4434 4434 'differential-table-of-contents-css' => '09216861', 4435 4435 'diffusion-commit-view-css' => 'c8ce2d88', 4436 4436 'diffusion-icons-css' => 'c8ce2d88', 4437 - 'global-drag-and-drop-css' => '638c9d42', 4437 + 'global-drag-and-drop-css' => '566968f8', 4438 4438 'inline-comment-summary-css' => '09216861', 4439 4439 'javelin-aphlict' => '4f81c788', 4440 4440 'javelin-behavior' => '2dbbb7d1', 4441 4441 'javelin-behavior-aphlict-dropdown' => '4f81c788', 4442 4442 'javelin-behavior-aphlict-listen' => '4f81c788', 4443 4443 'javelin-behavior-aphront-basic-tokenizer' => '4f81c788', 4444 - 'javelin-behavior-aphront-drag-and-drop-textarea' => '025bdd77', 4444 + 'javelin-behavior-aphront-drag-and-drop-textarea' => 'd07a3bc2', 4445 4445 'javelin-behavior-aphront-form-disable-on-submit' => '4f81c788', 4446 4446 'javelin-behavior-audit-preview' => '96909266', 4447 4447 'javelin-behavior-dark-console' => '4ccfeb47', 4448 4448 'javelin-behavior-device' => '4f81c788', 4449 - 'javelin-behavior-differential-accept-with-errors' => '025bdd77', 4450 - 'javelin-behavior-differential-add-reviewers-and-ccs' => '025bdd77', 4451 - 'javelin-behavior-differential-comment-jump' => '025bdd77', 4452 - 'javelin-behavior-differential-diff-radios' => '025bdd77', 4453 - 'javelin-behavior-differential-dropdown-menus' => '025bdd77', 4454 - 'javelin-behavior-differential-edit-inline-comments' => '025bdd77', 4455 - 'javelin-behavior-differential-feedback-preview' => '025bdd77', 4456 - 'javelin-behavior-differential-keyboard-navigation' => '025bdd77', 4457 - 'javelin-behavior-differential-populate' => '025bdd77', 4458 - 'javelin-behavior-differential-show-more' => '025bdd77', 4459 - 'javelin-behavior-differential-toggle-files' => '025bdd77', 4460 - 'javelin-behavior-differential-user-select' => '025bdd77', 4449 + 'javelin-behavior-differential-accept-with-errors' => 'd07a3bc2', 4450 + 'javelin-behavior-differential-add-reviewers-and-ccs' => 'd07a3bc2', 4451 + 'javelin-behavior-differential-comment-jump' => 'd07a3bc2', 4452 + 'javelin-behavior-differential-diff-radios' => 'd07a3bc2', 4453 + 'javelin-behavior-differential-dropdown-menus' => 'd07a3bc2', 4454 + 'javelin-behavior-differential-edit-inline-comments' => 'd07a3bc2', 4455 + 'javelin-behavior-differential-feedback-preview' => 'd07a3bc2', 4456 + 'javelin-behavior-differential-keyboard-navigation' => 'd07a3bc2', 4457 + 'javelin-behavior-differential-populate' => 'd07a3bc2', 4458 + 'javelin-behavior-differential-show-more' => 'd07a3bc2', 4459 + 'javelin-behavior-differential-toggle-files' => 'd07a3bc2', 4460 + 'javelin-behavior-differential-user-select' => 'd07a3bc2', 4461 4461 'javelin-behavior-diffusion-commit-graph' => '96909266', 4462 4462 'javelin-behavior-diffusion-pull-lastmodified' => '96909266', 4463 4463 'javelin-behavior-error-log' => '4ccfeb47', ··· 4465 4465 'javelin-behavior-history-install' => '4f81c788', 4466 4466 'javelin-behavior-konami' => '4f81c788', 4467 4467 'javelin-behavior-lightbox-attachments' => '4f81c788', 4468 - 'javelin-behavior-load-blame' => '025bdd77', 4468 + 'javelin-behavior-load-blame' => 'd07a3bc2', 4469 4469 'javelin-behavior-maniphest-batch-selector' => '98f64f07', 4470 4470 'javelin-behavior-maniphest-subpriority-editor' => '98f64f07', 4471 4471 'javelin-behavior-maniphest-transaction-controls' => '98f64f07', ··· 4477 4477 'javelin-behavior-phabricator-hovercards' => '4f81c788', 4478 4478 'javelin-behavior-phabricator-keyboard-shortcuts' => '4f81c788', 4479 4479 'javelin-behavior-phabricator-nav' => '4f81c788', 4480 - 'javelin-behavior-phabricator-object-selector' => '025bdd77', 4480 + 'javelin-behavior-phabricator-object-selector' => 'd07a3bc2', 4481 4481 'javelin-behavior-phabricator-oncopy' => '4f81c788', 4482 4482 'javelin-behavior-phabricator-remarkup-assist' => '4f81c788', 4483 4483 'javelin-behavior-phabricator-reveal-content' => '4f81c788', ··· 4485 4485 'javelin-behavior-phabricator-tooltips' => '4f81c788', 4486 4486 'javelin-behavior-phabricator-watch-anchor' => '4f81c788', 4487 4487 'javelin-behavior-refresh-csrf' => '4f81c788', 4488 - 'javelin-behavior-repository-crossreference' => '025bdd77', 4488 + 'javelin-behavior-repository-crossreference' => 'd07a3bc2', 4489 4489 'javelin-behavior-toggle-class' => '4f81c788', 4490 4490 'javelin-behavior-workflow' => '4f81c788', 4491 4491 'javelin-dom' => '2dbbb7d1', ··· 4507 4507 'javelin-util' => '2dbbb7d1', 4508 4508 'javelin-vector' => '2dbbb7d1', 4509 4509 'javelin-workflow' => '2dbbb7d1', 4510 - 'lightbox-attachment-css' => '638c9d42', 4510 + 'lightbox-attachment-css' => '566968f8', 4511 4511 'maniphest-task-summary-css' => '06bacb9a', 4512 4512 'maniphest-transaction-detail-css' => '06bacb9a', 4513 - 'phabricator-action-list-view-css' => '638c9d42', 4514 - 'phabricator-application-launch-view-css' => '638c9d42', 4513 + 'phabricator-action-list-view-css' => '566968f8', 4514 + 'phabricator-application-launch-view-css' => '566968f8', 4515 4515 'phabricator-busy' => '4f81c788', 4516 4516 'phabricator-content-source-view-css' => '09216861', 4517 - 'phabricator-core-css' => '638c9d42', 4518 - 'phabricator-crumbs-view-css' => '638c9d42', 4519 - 'phabricator-drag-and-drop-file-upload' => '025bdd77', 4517 + 'phabricator-core-css' => '566968f8', 4518 + 'phabricator-crumbs-view-css' => '566968f8', 4519 + 'phabricator-drag-and-drop-file-upload' => 'd07a3bc2', 4520 4520 'phabricator-dropdown-menu' => '4f81c788', 4521 4521 'phabricator-file-upload' => '4f81c788', 4522 - 'phabricator-filetree-view-css' => '638c9d42', 4523 - 'phabricator-flag-css' => '638c9d42', 4524 - 'phabricator-form-view-css' => '638c9d42', 4525 - 'phabricator-header-view-css' => '638c9d42', 4522 + 'phabricator-filetree-view-css' => '566968f8', 4523 + 'phabricator-flag-css' => '566968f8', 4524 + 'phabricator-form-view-css' => '566968f8', 4525 + 'phabricator-header-view-css' => '566968f8', 4526 4526 'phabricator-hovercard' => '4f81c788', 4527 - 'phabricator-jump-nav' => '638c9d42', 4527 + 'phabricator-jump-nav' => '566968f8', 4528 4528 'phabricator-keyboard-shortcut' => '4f81c788', 4529 4529 'phabricator-keyboard-shortcut-manager' => '4f81c788', 4530 - 'phabricator-main-menu-view' => '638c9d42', 4530 + 'phabricator-main-menu-view' => '566968f8', 4531 4531 'phabricator-menu-item' => '4f81c788', 4532 - 'phabricator-nav-view-css' => '638c9d42', 4532 + 'phabricator-nav-view-css' => '566968f8', 4533 4533 'phabricator-notification' => '4f81c788', 4534 - 'phabricator-notification-css' => '638c9d42', 4535 - 'phabricator-notification-menu-css' => '638c9d42', 4536 - 'phabricator-object-item-list-view-css' => '638c9d42', 4534 + 'phabricator-notification-css' => '566968f8', 4535 + 'phabricator-notification-menu-css' => '566968f8', 4536 + 'phabricator-object-item-list-view-css' => '566968f8', 4537 4537 'phabricator-object-selector-css' => '09216861', 4538 4538 'phabricator-phtize' => '4f81c788', 4539 4539 'phabricator-prefab' => '4f81c788', 4540 4540 'phabricator-project-tag-css' => '06bacb9a', 4541 - 'phabricator-property-list-view-css' => '638c9d42', 4542 - 'phabricator-remarkup-css' => '638c9d42', 4543 - 'phabricator-shaped-request' => '025bdd77', 4544 - 'phabricator-side-menu-view-css' => '638c9d42', 4545 - 'phabricator-standard-page-view' => '638c9d42', 4546 - 'phabricator-tag-view-css' => '638c9d42', 4541 + 'phabricator-property-list-view-css' => '566968f8', 4542 + 'phabricator-remarkup-css' => '566968f8', 4543 + 'phabricator-shaped-request' => 'd07a3bc2', 4544 + 'phabricator-side-menu-view-css' => '566968f8', 4545 + 'phabricator-standard-page-view' => '566968f8', 4546 + 'phabricator-tag-view-css' => '566968f8', 4547 4547 'phabricator-textareautils' => '4f81c788', 4548 4548 'phabricator-tooltip' => '4f81c788', 4549 - 'phabricator-transaction-view-css' => '638c9d42', 4550 - 'phabricator-zindex-css' => '638c9d42', 4551 - 'phui-button-css' => '638c9d42', 4552 - 'phui-form-css' => '638c9d42', 4553 - 'phui-icon-view-css' => '638c9d42', 4554 - 'phui-spacing-css' => '638c9d42', 4555 - 'sprite-apps-large-css' => '638c9d42', 4556 - 'sprite-gradient-css' => '638c9d42', 4557 - 'sprite-icons-css' => '638c9d42', 4558 - 'sprite-menu-css' => '638c9d42', 4559 - 'syntax-highlighting-css' => '638c9d42', 4549 + 'phabricator-transaction-view-css' => '566968f8', 4550 + 'phabricator-zindex-css' => '566968f8', 4551 + 'phui-button-css' => '566968f8', 4552 + 'phui-form-css' => '566968f8', 4553 + 'phui-icon-view-css' => '566968f8', 4554 + 'phui-spacing-css' => '566968f8', 4555 + 'sprite-apps-large-css' => '566968f8', 4556 + 'sprite-gradient-css' => '566968f8', 4557 + 'sprite-icons-css' => '566968f8', 4558 + 'sprite-menu-css' => '566968f8', 4559 + 'syntax-highlighting-css' => '566968f8', 4560 4560 ), 4561 4561 ));
+9 -3
src/__phutil_library_map__.php
··· 1184 1184 'PhabricatorFlagDeleteController' => 'applications/flag/controller/PhabricatorFlagDeleteController.php', 1185 1185 'PhabricatorFlagEditController' => 'applications/flag/controller/PhabricatorFlagEditController.php', 1186 1186 'PhabricatorFlagListController' => 'applications/flag/controller/PhabricatorFlagListController.php', 1187 - 'PhabricatorFlagListView' => 'applications/flag/view/PhabricatorFlagListView.php', 1188 1187 'PhabricatorFlagQuery' => 'applications/flag/query/PhabricatorFlagQuery.php', 1188 + 'PhabricatorFlagSearchEngine' => 'applications/flag/query/PhabricatorFlagSearchEngine.php', 1189 + 'PhabricatorFlagSelectControl' => 'applications/flag/view/PhabricatorFlagSelectControl.php', 1189 1190 'PhabricatorFlagsUIEventListener' => 'applications/flag/events/PhabricatorFlagsUIEventListener.php', 1190 1191 'PhabricatorFormExample' => 'applications/uiexample/examples/PhabricatorFormExample.php', 1191 1192 'PhabricatorGarbageCollectorConfigOptions' => 'applications/config/option/PhabricatorGarbageCollectorConfigOptions.php', ··· 3261 3262 'PhabricatorFlagDAO' => 'PhabricatorLiskDAO', 3262 3263 'PhabricatorFlagDeleteController' => 'PhabricatorFlagController', 3263 3264 'PhabricatorFlagEditController' => 'PhabricatorFlagController', 3264 - 'PhabricatorFlagListController' => 'PhabricatorFlagController', 3265 - 'PhabricatorFlagListView' => 'AphrontView', 3265 + 'PhabricatorFlagListController' => 3266 + array( 3267 + 0 => 'PhabricatorFlagController', 3268 + 1 => 'PhabricatorApplicationSearchResultsControllerInterface', 3269 + ), 3266 3270 'PhabricatorFlagQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 3271 + 'PhabricatorFlagSearchEngine' => 'PhabricatorApplicationSearchEngine', 3272 + 'PhabricatorFlagSelectControl' => 'AphrontFormControl', 3267 3273 'PhabricatorFlagsUIEventListener' => 'PhutilEventListener', 3268 3274 'PhabricatorFormExample' => 'PhabricatorUIExample', 3269 3275 'PhabricatorGarbageCollectorConfigOptions' => 'PhabricatorApplicationConfigOptions',
+5 -1
src/applications/flag/application/PhabricatorApplicationFlags.php
··· 20 20 ); 21 21 } 22 22 23 + public function getTitleGlyph() { 24 + return "\xE2\x9A\x90"; 25 + } 26 + 23 27 public function getApplicationGroup() { 24 28 return self::GROUP_ORGANIZATION; 25 29 } ··· 45 49 public function getRoutes() { 46 50 return array( 47 51 '/flag/' => array( 48 - '' => 'PhabricatorFlagListController', 52 + '(?:query/(?P<queryKey>[^/]+)/)?' => 'PhabricatorFlagListController', 49 53 'view/(?P<view>[^/]+)/' => 'PhabricatorFlagListController', 50 54 'edit/(?P<phid>[^/]+)/' => 'PhabricatorFlagEditController', 51 55 'delete/(?P<id>[1-9]\d*)/' => 'PhabricatorFlagDeleteController',
+10 -9
src/applications/flag/controller/PhabricatorFlagController.php
··· 2 2 3 3 abstract class PhabricatorFlagController extends PhabricatorController { 4 4 5 - public function buildStandardPageResponse($view, array $data) { 5 + public function buildSideNavView() { 6 + $user = $this->getRequest()->getUser(); 6 7 7 - $page = $this->buildStandardPageView(); 8 + $nav = new AphrontSideNavFilterView(); 9 + $nav->setBaseURI(new PhutilURI($this->getApplicationURI())); 8 10 9 - $page->setApplicationName(pht('Flag')); 10 - $page->setBaseURI('/flag/'); 11 - $page->setTitle(idx($data, 'title')); 12 - $page->setGlyph("\xE2\x9A\x90"); // Subtle! 13 - $page->appendChild($view); 11 + id(new PhabricatorFlagSearchEngine()) 12 + ->setViewer($user) 13 + ->addNavigationItems($nav->getMenu()); 14 14 15 - $response = new AphrontWebpageResponse(); 16 - return $response->setContent($page->render()); 15 + $nav->selectFilter(null); 17 16 17 + return $nav; 18 18 } 19 + 19 20 }
+60 -41
src/applications/flag/controller/PhabricatorFlagListController.php
··· 1 1 <?php 2 2 3 - final class PhabricatorFlagListController extends PhabricatorFlagController { 3 + final class PhabricatorFlagListController extends PhabricatorFlagController 4 + implements PhabricatorApplicationSearchResultsControllerInterface { 5 + 6 + private $queryKey; 7 + 8 + public function shouldAllowPublic() { 9 + return true; 10 + } 11 + 12 + public function willProcessRequest(array $data) { 13 + $this->queryKey = idx($data, 'queryKey'); 14 + } 4 15 5 16 public function processRequest() { 6 17 $request = $this->getRequest(); 7 - $user = $request->getUser(); 8 - $flag_order = $request->getStr('o', 'n'); 18 + $controller = id(new PhabricatorApplicationSearchController($request)) 19 + ->setQueryKey($this->queryKey) 20 + ->setSearchEngine(new PhabricatorFlagSearchEngine()) 21 + ->setNavigation($this->buildSideNavView()); 22 + 23 + return $this->delegateToController($controller); 24 + } 25 + 26 + public function renderResultsList( 27 + array $flags, 28 + PhabricatorSavedQuery $query) { 29 + assert_instances_of($flags, 'PhabricatorFlag'); 30 + 31 + $viewer = $this->getRequest()->getUser(); 9 32 10 - $nav = new AphrontSideNavFilterView(); 11 - $nav->setBaseURI(new PhutilURI('/flag/view/')); 12 - $nav->addLabel(pht('Flags')); 13 - $nav->addFilter('all', pht('Your Flags')); 14 - $nav->selectFilter('all', 'all'); 33 + $list = id(new PhabricatorObjectItemListView()) 34 + ->setUser($viewer); 35 + foreach ($flags as $flag) { 36 + $id = $flag->getID(); 37 + $phid = $flag->getObjectPHID(); 15 38 16 - $crumbs = $this->buildApplicationCrumbs(); 17 - $crumbs->addCrumb(id(new PhabricatorCrumbView) 18 - ->setName(pht('Flags')) 19 - ->setHref($request->getRequestURI())); 20 - $nav->setCrumbs($crumbs); 39 + $class = PhabricatorFlagColor::getCSSClass($flag->getColor()); 21 40 22 - $query = new PhabricatorFlagQuery(); 23 - $query->withOwnerPHIDs(array($user->getPHID())); 24 - $query->setViewer($user); 25 - $query->needHandles(true); 41 + $flag_icon = phutil_tag( 42 + 'div', 43 + array( 44 + 'class' => 'phabricator-flag-icon '.$class, 45 + ), 46 + ''); 26 47 27 - $flags = $query->execute(); 48 + $item = id(new PhabricatorObjectItemView()) 49 + ->addHeadIcon($flag_icon) 50 + ->setHeader($flag->getHandle()->renderLink()); 28 51 29 - $views = array(); 30 - $view = new PhabricatorFlagListView(); 31 - $view->setFlags($flags); 32 - $view->setUser($user); 33 - $view->setFlush(true); 34 - $views[] = array( 35 - 'view' => $view, 36 - ); 52 + $item->addAction( 53 + id(new PHUIListItemView()) 54 + ->setIcon('edit') 55 + ->setHref($this->getApplicationURI("edit/{$phid}/")) 56 + ->setWorkflow(true)); 37 57 38 - foreach ($views as $view) { 39 - $panel = new AphrontPanelView(); 40 - $panel->setNoBackground(); 58 + $item->addAction( 59 + id(new PHUIListItemView()) 60 + ->setIcon('delete') 61 + ->setHref($this->getApplicationURI("delete/{$id}/")) 62 + ->setWorkflow(true)); 41 63 42 - $title = idx($view, 'title'); 43 - if ($title) { 44 - $panel->setHeader($title); 64 + if ($flag->getNote()) { 65 + $item->addAttribute($flag->getNote()); 45 66 } 46 - $panel->appendChild($view['view']); 47 - $nav->appendChild($panel); 67 + 68 + $item->addIcon( 69 + 'none', 70 + phabricator_datetime($flag->getDateCreated(), $viewer)); 71 + 72 + $list->addItem($item); 48 73 } 49 74 50 - return $this->buildApplicationPage( 51 - $nav, 52 - array( 53 - 'title' => pht('Flags'), 54 - 'device' => true, 55 - 'dust' => true, 56 - )); 75 + return $list; 57 76 } 58 77 59 78 }
+62
src/applications/flag/query/PhabricatorFlagSearchEngine.php
··· 1 + <?php 2 + 3 + final class PhabricatorFlagSearchEngine 4 + extends PhabricatorApplicationSearchEngine { 5 + 6 + public function buildSavedQueryFromRequest(AphrontRequest $request) { 7 + $saved = new PhabricatorSavedQuery(); 8 + $saved->setParameter('colors', $request->getArr('colors')); 9 + return $saved; 10 + } 11 + 12 + public function buildQueryFromSavedQuery(PhabricatorSavedQuery $saved) { 13 + $query = id(new PhabricatorFlagQuery()) 14 + ->needHandles(true) 15 + ->withOwnerPHIDs(array($this->requireViewer()->getPHID())); 16 + 17 + $colors = $saved->getParameter('colors'); 18 + if ($colors) { 19 + $query->withColors($colors); 20 + } 21 + 22 + return $query; 23 + } 24 + 25 + public function buildSearchForm( 26 + AphrontFormView $form, 27 + PhabricatorSavedQuery $saved_query) { 28 + 29 + $form->appendChild( 30 + id(new PhabricatorFlagSelectControl()) 31 + ->setName('colors') 32 + ->setLabel(pht('Colors')) 33 + ->setValue($saved_query->getParameter('colors', array()))); 34 + 35 + } 36 + 37 + protected function getURI($path) { 38 + return '/flag/'.$path; 39 + } 40 + 41 + public function getBuiltinQueryNames() { 42 + $names = array( 43 + 'all' => pht('Flagged'), 44 + ); 45 + 46 + return $names; 47 + } 48 + 49 + public function buildSavedQueryFromBuiltin($query_key) { 50 + 51 + $query = $this->newSavedQuery(); 52 + $query->setQueryKey($query_key); 53 + 54 + switch ($query_key) { 55 + case 'all': 56 + return $query; 57 + } 58 + 59 + return parent::buildSavedQueryFromBuiltin($query_key); 60 + } 61 + 62 + }
-74
src/applications/flag/view/PhabricatorFlagListView.php
··· 1 - <?php 2 - 3 - final class PhabricatorFlagListView extends AphrontView { 4 - 5 - private $flags; 6 - private $flush = false; 7 - 8 - public function setFlags(array $flags) { 9 - assert_instances_of($flags, 'PhabricatorFlag'); 10 - $this->flags = $flags; 11 - return $this; 12 - } 13 - 14 - public function setFlush($flush) { 15 - $this->flush = $flush; 16 - return $this; 17 - } 18 - 19 - public function render() { 20 - $user = $this->user; 21 - 22 - require_celerity_resource('phabricator-flag-css'); 23 - 24 - $list = new PhabricatorObjectItemListView(); 25 - $list->setCards(true); 26 - $list->setNoDataString(pht('No flags.')); 27 - $list->setFlush($this->flush); 28 - 29 - $rows = array(); 30 - foreach ($this->flags as $flag) { 31 - $class = PhabricatorFlagColor::getCSSClass($flag->getColor()); 32 - 33 - $flag_icon = phutil_tag( 34 - 'div', 35 - array( 36 - 'class' => 'phabricator-flag-icon '.$class, 37 - ), 38 - ''); 39 - 40 - $edit_link = javelin_tag( 41 - 'a', 42 - array( 43 - 'href' => '/flag/edit/'.$flag->getObjectPHID().'/', 44 - 'sigil' => 'workflow', 45 - ), 46 - pht('Edit')); 47 - 48 - $remove_link = javelin_tag( 49 - 'a', 50 - array( 51 - 'href' => '/flag/delete/'.$flag->getID().'/', 52 - 'sigil' => 'workflow', 53 - ), 54 - pht('Remove')); 55 - 56 - $item = new PhabricatorObjectItemView(); 57 - $item->addIcon('edit', $edit_link); 58 - $item->addIcon('delete', $remove_link); 59 - 60 - $item->addHeadIcon($flag_icon); 61 - $item->setHeader($flag->getHandle()->renderLink()); 62 - 63 - $item->addAttribute(phabricator_datetime($flag->getDateCreated(), $user)); 64 - 65 - if ($flag->getNote()) { 66 - $item->addAttribute($flag->getNote()); 67 - } 68 - 69 - $list->addItem($item); 70 - } 71 - 72 - return $list; 73 - } 74 - }
+65
src/applications/flag/view/PhabricatorFlagSelectControl.php
··· 1 + <?php 2 + 3 + final class PhabricatorFlagSelectControl extends AphrontFormControl { 4 + 5 + public function getCustomControlClass() { 6 + return 'phabricator-flag-select-control'; 7 + } 8 + 9 + public function renderInput() { 10 + require_celerity_resource('phabricator-flag-css'); 11 + 12 + $colors = PhabricatorFlagColor::getColorNameMap(); 13 + 14 + $value_map = array_fuse($this->getValue()); 15 + 16 + $file_map = array( 17 + PhabricatorFlagColor::COLOR_RED => 'red', 18 + PhabricatorFlagColor::COLOR_ORANGE => 'orange', 19 + PhabricatorFlagColor::COLOR_YELLOW => 'yellow', 20 + PhabricatorFlagColor::COLOR_GREEN => 'green', 21 + PhabricatorFlagColor::COLOR_BLUE => 'blue', 22 + PhabricatorFlagColor::COLOR_PINK => 'pink', 23 + PhabricatorFlagColor::COLOR_PURPLE => 'purple', 24 + PhabricatorFlagColor::COLOR_CHECKERED => 'finish', 25 + ); 26 + 27 + $out = array(); 28 + foreach ($colors as $const => $name) { 29 + // TODO: This should probably be a sprite sheet. 30 + $partial = $file_map[$const]; 31 + $uri = '/rsrc/image/icon/fatcow/flag_'.$partial.'.png'; 32 + $uri = celerity_get_resource_uri($uri); 33 + 34 + $icon = id(new PHUIIconView()) 35 + ->setImage($uri); 36 + 37 + $input = phutil_tag( 38 + 'input', 39 + array( 40 + 'type' => 'checkbox', 41 + 'name' => $this->getName().'[]', 42 + 'value' => $const, 43 + 'checked' => isset($value_map[$const]) 44 + ? 'checked' 45 + : null, 46 + 'class' => 'phabricator-flag-select-checkbox', 47 + )); 48 + 49 + $label = phutil_tag( 50 + 'label', 51 + array( 52 + 'class' => 'phabricator-flag-select-label', 53 + ), 54 + array( 55 + $icon, 56 + $input, 57 + )); 58 + 59 + $out[] = $label; 60 + } 61 + 62 + return $out; 63 + } 64 + 65 + }
+26
webroot/rsrc/css/application/flag/flag.css
··· 55 55 .phabricator-flag-ghost { 56 56 background-image: url(/rsrc/image/icon/fatcow/flag_ghost.png); 57 57 } 58 + 59 + .phabricator-flag-select-control .phabricator-flag-select-label { 60 + border: 1px solid #aaaaaa; 61 + width: 48px; 62 + height: 24px; 63 + border-radius: 4px; 64 + position: relative; 65 + display: inline-block; 66 + cursor: pointer; 67 + margin: 0 4px 4px 0; 68 + } 69 + 70 + .phabricator-flag-select-control .phabricator-flag-select-checkbox { 71 + position: absolute; 72 + top: 2px; 73 + left: 4px; 74 + width: auto; 75 + } 76 + 77 + .phabricator-flag-select-control .phui-icon-view { 78 + position: absolute; 79 + width: 16px; 80 + height: 16px; 81 + top: 4px; 82 + left: 24px; 83 + }