1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-12-28 16:30:59 +01:00

AphrontFormCountedToggleButtonsControl

Summary: Like AphrontFormToggleButtonsControl, but with mouseover counters.  These counters let you know how many of each thing there are in each category, which is useful when using this control for filtering a list of things in multiple dimensions.

Test Plan: `/uiexample/view/PhabricatorCountedToggleButtonsExample/`

Reviewers: epriestley

CC: aran, Korvin

Maniphest Tasks: T2094

Differential Revision: https://secure.phabricator.com/D5118
This commit is contained in:
Edward Speyer 2013-02-26 16:20:14 +00:00
parent 6ab2db6d4d
commit a1b98c5cb7
5 changed files with 311 additions and 40 deletions

View file

@ -683,7 +683,7 @@ celerity_register_resource_map(array(
),
'aphront-form-view-css' =>
array(
'uri' => '/res/c1cf5cce/rsrc/css/aphront/form-view.css',
'uri' => '/res/efaecc2d/rsrc/css/aphront/form-view.css',
'type' => 'css',
'requires' =>
array(
@ -3562,7 +3562,7 @@ celerity_register_resource_map(array(
), array(
'packages' =>
array(
'0f595159' =>
'b481b309' =>
array(
'name' => 'core.pkg.css',
'symbols' =>
@ -3605,7 +3605,7 @@ celerity_register_resource_map(array(
35 => 'phabricator-object-item-list-view-css',
36 => 'global-drag-and-drop-css',
),
'uri' => '/res/pkg/0f595159/core.pkg.css',
'uri' => '/res/pkg/b481b309/core.pkg.css',
'type' => 'css',
),
'95ceba95' =>
@ -3796,17 +3796,17 @@ celerity_register_resource_map(array(
'reverse' =>
array(
'aphront-attached-file-view-css' => 'eb35a026',
'aphront-crumbs-view-css' => '0f595159',
'aphront-dialog-view-css' => '0f595159',
'aphront-error-view-css' => '0f595159',
'aphront-form-view-css' => '0f595159',
'aphront-list-filter-view-css' => '0f595159',
'aphront-pager-view-css' => '0f595159',
'aphront-panel-view-css' => '0f595159',
'aphront-table-view-css' => '0f595159',
'aphront-tokenizer-control-css' => '0f595159',
'aphront-tooltip-css' => '0f595159',
'aphront-typeahead-control-css' => '0f595159',
'aphront-crumbs-view-css' => 'b481b309',
'aphront-dialog-view-css' => 'b481b309',
'aphront-error-view-css' => 'b481b309',
'aphront-form-view-css' => 'b481b309',
'aphront-list-filter-view-css' => 'b481b309',
'aphront-pager-view-css' => 'b481b309',
'aphront-panel-view-css' => 'b481b309',
'aphront-table-view-css' => 'b481b309',
'aphront-tokenizer-control-css' => 'b481b309',
'aphront-tooltip-css' => 'b481b309',
'aphront-typeahead-control-css' => 'b481b309',
'differential-changeset-view-css' => '8aaacd1b',
'differential-core-view-css' => '8aaacd1b',
'differential-inline-comment-editor' => '322728f3',
@ -3820,7 +3820,7 @@ celerity_register_resource_map(array(
'differential-table-of-contents-css' => '8aaacd1b',
'diffusion-commit-view-css' => 'c8ce2d88',
'diffusion-icons-css' => 'c8ce2d88',
'global-drag-and-drop-css' => '0f595159',
'global-drag-and-drop-css' => 'b481b309',
'inline-comment-summary-css' => '8aaacd1b',
'javelin-aphlict' => '95ceba95',
'javelin-behavior' => 'cd1d650a',
@ -3892,48 +3892,48 @@ celerity_register_resource_map(array(
'javelin-util' => 'cd1d650a',
'javelin-vector' => 'cd1d650a',
'javelin-workflow' => 'cd1d650a',
'lightbox-attachment-css' => '0f595159',
'lightbox-attachment-css' => 'b481b309',
'maniphest-task-summary-css' => 'eb35a026',
'maniphest-transaction-detail-css' => 'eb35a026',
'phabricator-busy' => '95ceba95',
'phabricator-content-source-view-css' => '8aaacd1b',
'phabricator-core-buttons-css' => '0f595159',
'phabricator-core-css' => '0f595159',
'phabricator-crumbs-view-css' => '0f595159',
'phabricator-directory-css' => '0f595159',
'phabricator-core-buttons-css' => 'b481b309',
'phabricator-core-css' => 'b481b309',
'phabricator-crumbs-view-css' => 'b481b309',
'phabricator-directory-css' => 'b481b309',
'phabricator-drag-and-drop-file-upload' => '322728f3',
'phabricator-dropdown-menu' => '95ceba95',
'phabricator-file-upload' => '95ceba95',
'phabricator-filetree-view-css' => '0f595159',
'phabricator-flag-css' => '0f595159',
'phabricator-form-view-css' => '0f595159',
'phabricator-header-view-css' => '0f595159',
'phabricator-jump-nav' => '0f595159',
'phabricator-filetree-view-css' => 'b481b309',
'phabricator-flag-css' => 'b481b309',
'phabricator-form-view-css' => 'b481b309',
'phabricator-header-view-css' => 'b481b309',
'phabricator-jump-nav' => 'b481b309',
'phabricator-keyboard-shortcut' => '95ceba95',
'phabricator-keyboard-shortcut-manager' => '95ceba95',
'phabricator-main-menu-view' => '0f595159',
'phabricator-main-menu-view' => 'b481b309',
'phabricator-menu-item' => '95ceba95',
'phabricator-nav-view-css' => '0f595159',
'phabricator-nav-view-css' => 'b481b309',
'phabricator-notification' => '95ceba95',
'phabricator-notification-css' => '0f595159',
'phabricator-notification-menu-css' => '0f595159',
'phabricator-object-item-list-view-css' => '0f595159',
'phabricator-notification-css' => 'b481b309',
'phabricator-notification-menu-css' => 'b481b309',
'phabricator-object-item-list-view-css' => 'b481b309',
'phabricator-object-selector-css' => '8aaacd1b',
'phabricator-paste-file-upload' => '95ceba95',
'phabricator-prefab' => '95ceba95',
'phabricator-project-tag-css' => 'eb35a026',
'phabricator-remarkup-css' => '0f595159',
'phabricator-remarkup-css' => 'b481b309',
'phabricator-shaped-request' => '322728f3',
'phabricator-side-menu-view-css' => '0f595159',
'phabricator-standard-page-view' => '0f595159',
'phabricator-side-menu-view-css' => 'b481b309',
'phabricator-standard-page-view' => 'b481b309',
'phabricator-textareautils' => '95ceba95',
'phabricator-tooltip' => '95ceba95',
'phabricator-transaction-view-css' => '0f595159',
'phabricator-zindex-css' => '0f595159',
'sprite-apps-large-css' => '0f595159',
'sprite-gradient-css' => '0f595159',
'sprite-icon-css' => '0f595159',
'sprite-menu-css' => '0f595159',
'syntax-highlighting-css' => '0f595159',
'phabricator-transaction-view-css' => 'b481b309',
'phabricator-zindex-css' => 'b481b309',
'sprite-apps-large-css' => 'b481b309',
'sprite-gradient-css' => 'b481b309',
'sprite-icon-css' => 'b481b309',
'sprite-menu-css' => 'b481b309',
'syntax-highlighting-css' => 'b481b309',
),
));

View file

@ -33,6 +33,7 @@ phutil_register_library_map(array(
'AphrontFileResponse' => 'aphront/response/AphrontFileResponse.php',
'AphrontFormCheckboxControl' => 'view/form/control/AphrontFormCheckboxControl.php',
'AphrontFormControl' => 'view/form/control/AphrontFormControl.php',
'AphrontFormCountedToggleButtonsControl' => 'view/form/control/AphrontFormCountedToggleButtonsControl.php',
'AphrontFormCropControl' => 'view/form/control/AphrontFormCropControl.php',
'AphrontFormDateControl' => 'view/form/control/AphrontFormDateControl.php',
'AphrontFormDividerControl' => 'view/form/control/AphrontFormDividerControl.php',
@ -824,6 +825,7 @@ phutil_register_library_map(array(
'PhabricatorCountdownListController' => 'applications/countdown/controller/PhabricatorCountdownListController.php',
'PhabricatorCountdownRemarkupRule' => 'applications/countdown/remarkup/PhabricatorCountdownRemarkupRule.php',
'PhabricatorCountdownViewController' => 'applications/countdown/controller/PhabricatorCountdownViewController.php',
'PhabricatorCountedToggleButtonsExample' => 'applications/uiexample/examples/PhabricatorCountedToggleButtonsExample.php',
'PhabricatorCrumbView' => 'view/layout/PhabricatorCrumbView.php',
'PhabricatorCrumbsView' => 'view/layout/PhabricatorCrumbsView.php',
'PhabricatorCursorPagedPolicyAwareQuery' => 'infrastructure/query/policy/PhabricatorCursorPagedPolicyAwareQuery.php',
@ -1604,6 +1606,7 @@ phutil_register_library_map(array(
'AphrontFileResponse' => 'AphrontResponse',
'AphrontFormCheckboxControl' => 'AphrontFormControl',
'AphrontFormControl' => 'AphrontView',
'AphrontFormCountedToggleButtonsControl' => 'AphrontFormControl',
'AphrontFormCropControl' => 'AphrontFormControl',
'AphrontFormDateControl' => 'AphrontFormControl',
'AphrontFormDividerControl' => 'AphrontFormControl',
@ -2356,6 +2359,7 @@ phutil_register_library_map(array(
'PhabricatorCountdownListController' => 'PhabricatorCountdownController',
'PhabricatorCountdownRemarkupRule' => 'PhutilRemarkupRule',
'PhabricatorCountdownViewController' => 'PhabricatorCountdownController',
'PhabricatorCountedToggleButtonsExample' => 'PhabricatorUIExample',
'PhabricatorCrumbView' => 'AphrontView',
'PhabricatorCrumbsView' => 'AphrontView',
'PhabricatorCursorPagedPolicyAwareQuery' => 'PhabricatorPolicyAwareQuery',

View file

@ -0,0 +1,148 @@
<?php
final class PhabricatorCountedToggleButtonsExample
extends PhabricatorUIExample {
public function getName() {
return 'Counted Toggle Buttons';
}
public function getDescription() {
return 'Like AphrontFormToggleButtonsControl, but with counters.';
}
private static function buildTreesList() {
$all_trees = array(
array(
'name' => 'Oak',
'leaves' => 'deciduous',
'wood' => 'hard',
'branches' => 'climbable',
),
array(
'name' => 'Pine',
'leaves' => 'coniferous',
'wood' => 'soft',
'branches' => 'spindly',
),
array(
'name' => 'Spruce',
'leaves' => 'coniferous',
'wood' => 'soft',
'branches' => 'sticky',
),
array(
'name' => 'Ash',
'leaves' => 'deciduous',
'wood' => 'hard',
'branches' => 'climbable',
),
array(
'name' => 'Holly',
'leaves' => 'waxy',
'wood' => 'hard',
'branches' => 'prickly',
),
);
for ($ii = 0; $ii < 345; $ii++) {
$name = sprintf("Soylent UltraTree \xE2\x84\xA2 Mutation 0xPD%03x", $ii);
$all_trees[] = array(
'name' => $name,
'leaves' => 'carcinogenic',
'wood' => 'metallic',
'branches' => 'sentient',
);
}
return $all_trees;
}
public function renderExample() {
$request = $this->getRequest();
$form = id(new AphrontFormView())
->setUser($request->getUser());
$attributes = array('leaves', 'wood', 'branches');
$all_trees = self::buildTreesList();
$trees = $all_trees;
foreach ($attributes as $attribute) {
$form_value = $request->getStr($attribute);
$buttons = array(null => 'all');
foreach ($all_trees as $dict) {
$value = $dict[$attribute];
$buttons[$value] = $value;
}
// The trees filtered by other attributes, before we filter by this
// attribute
$trees_before = $all_trees;
foreach ($attributes as $other_attribute) {
if ($other_attribute != $attribute) {
$trees_before = $this->filterTrees($trees_before, $other_attribute);
}
}
$counters = array(null => count($trees_before));
foreach ($trees_before as $dict) {
$value = $dict[$attribute];
if (!isset($counters[$value])) {
$counters[$value] = 0;
}
$counters[$value]++;
}
$trees = $this->filterTrees($trees, $attribute);
$control = id(new AphrontFormCountedToggleButtonsControl())
->setLabel(ucfirst($attribute))
->setName($attribute)
->setValue($form_value)
->setBaseURI($request->getRequestURI(), $attribute)
->setButtons($buttons)
->setCounters($counters);
$form->appendChild($control);
}
$rows = array();
foreach ($trees as $dict) {
$row = array_select_keys($dict, $attributes);
array_unshift($row, $dict['name']);
$rows[] = $row;
}
$headers = $attributes;
array_unshift($headers, 'name');
$table = id(new AphrontTableView($rows))
->setHeaders($headers);
$panel = id(new AphrontPanelView())
->setHeader('Counters!')
->setWidth(AphrontPanelView::WIDTH_FULL)
->appendChild($form)
->appendChild($table);
return $panel;
}
private function filterTrees($trees, $attribute) {
$form_value = $this->getRequest()->getStr($attribute);
if (!$form_value) {
return $trees;
}
$new = array();
foreach ($trees as $dict) {
if ($dict[$attribute] == $form_value) {
$new[] = $dict;
}
}
return $new;
}
}

View file

@ -0,0 +1,80 @@
<?php
final class AphrontFormCountedToggleButtonsControl extends AphrontFormControl {
private $baseURI;
private $param;
private $buttons;
private $counters = array();
public function setBaseURI(PhutilURI $uri, $param) {
$this->baseURI = $uri;
$this->param = $param;
return $this;
}
public function setButtons(array $buttons) {
$this->buttons = $buttons;
return $this;
}
public function setCounters(array $counters) {
$this->counters = $counters;
return $this;
}
protected function getCustomControlClass() {
return 'aphront-form-control-counted-togglebuttons';
}
protected function renderInput() {
if (!$this->baseURI) {
throw new Exception('Call setBaseURI() before render()!');
}
$selected = $this->getValue();
$out = array();
foreach ($this->buttons as $value => $label) {
if ($value == $selected) {
$more = ' toggle-selected toggle-fixed';
} else {
$more = null;
}
$counter = idx($this->counters, $value);
if ($counter > 0) {
$href = $this->baseURI->alter($this->param, $value);
$counter_markup = phutil_tag(
'div',
array(
'class' => 'counter',
),
$counter);
} else {
$href = null;
$counter_markup = '';
$more .= ' disabled';
}
$attributes = array(
'class' => 'toggle'.$more,
);
if ($href) {
$attributes['href'] = $href;
}
$out[] = phutil_tag(
'a',
$attributes,
array(
$counter_markup,
$label));
}
return $out;
}
}

View file

@ -368,3 +368,42 @@ table.aphront-form-control-checkbox-layout th {
padding: 12px;
float: right;
}
.aphront-form-control-counted-togglebuttons {
padding-top: 7px;
}
.aphront-form-control-counted-togglebuttons .toggle {
position: relative;
}
.aphront-form-control-counted-togglebuttons .toggle-fixed {
cursor: pointer;
}
.aphront-form-control-counted-togglebuttons .toggle .counter {
font-size: smaller;
display: none;
position: absolute;
top: -9px;
right: -8px;
padding: 0px 3px;
border-radius: 3px;
}
.aphront-form-control-counted-togglebuttons:hover .toggle .counter {
display: block;
}
.aphront-form-control-counted-togglebuttons .toggle .counter {
background: gray;
color: #ddd;
}
.aphront-form-control-counted-togglebuttons .toggle-selected .counter {
color: white;
}
.aphront-form-control-counted-togglebuttons .toggle.disabled:hover {
background-color: #a7a7a7;
}