diff --git a/resources/celerity/map.php b/resources/celerity/map.php --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -7,7 +7,7 @@ return array( 'names' => array( - 'core.pkg.css' => 'afe6e16d', + 'core.pkg.css' => '818e5093', 'core.pkg.js' => 'c415c382', 'darkconsole.pkg.js' => 'ca8671ce', 'differential.pkg.css' => '4b8686e3', @@ -115,7 +115,7 @@ 'rsrc/css/font/font-source-sans-pro.css' => '91d53463', 'rsrc/css/font/phui-font-icon-base.css' => 'cd92ff25', 'rsrc/css/layout/phabricator-action-header-view.css' => 'c14dfc57', - 'rsrc/css/layout/phabricator-action-list-view.css' => '81383e25', + 'rsrc/css/layout/phabricator-action-list-view.css' => 'ee7c25c2', 'rsrc/css/layout/phabricator-crumbs-view.css' => '0222cbe0', 'rsrc/css/layout/phabricator-filetree-view.css' => 'a8c86ace', 'rsrc/css/layout/phabricator-hovercard-view.css' => '46a13cf0', @@ -681,7 +681,7 @@ 'path-typeahead' => 'f7fc67ec', 'people-profile-css' => 'ba7b2762', 'phabricator-action-header-view-css' => 'c14dfc57', - 'phabricator-action-list-view-css' => '81383e25', + 'phabricator-action-list-view-css' => 'ee7c25c2', 'phabricator-application-launch-view-css' => 'd290ba21', 'phabricator-busy' => '6453c869', 'phabricator-chatlog-css' => '852140ff', diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -3842,7 +3842,7 @@ 'PhabricatorActionHeaderView' => 'AphrontView', 'PhabricatorActionListExample' => 'PhabricatorUIExample', 'PhabricatorActionListView' => 'AphrontView', - 'PhabricatorActionView' => 'AphrontView', + 'PhabricatorActionView' => 'AphrontTagView', 'PhabricatorAllCapsTranslation' => 'PhabricatorTranslation', 'PhabricatorAnchorView' => 'AphrontView', 'PhabricatorAphrontBarExample' => 'PhabricatorUIExample', diff --git a/src/applications/people/controller/PhabricatorPeopleProfileController.php b/src/applications/people/controller/PhabricatorPeopleProfileController.php --- a/src/applications/people/controller/PhabricatorPeopleProfileController.php +++ b/src/applications/people/controller/PhabricatorPeopleProfileController.php @@ -66,22 +66,31 @@ if ($viewer->getIsAdmin()) { $actions->addAction( id(new PhabricatorActionView()) - ->setIcon('wrench') + ->setIsContainer(true) + ->setIcon('user') + ->setGroupKey('user.admin') + ->setName(pht('Administrate User'))); + + $actions->addAction( + id(new PhabricatorActionView()) + ->setGroupKey('user.admin') + ->setIcon('none') ->setName(pht('Edit Settings')) ->setDisabled(!$can_edit) ->setWorkflow(!$can_edit) ->setHref('/settings/'.$user->getID().'/')); if ($user->getIsAdmin()) { - $empower_icon = 'lower-priority'; + $empower_icon = 'none'; $empower_name = pht('Remove Administrator'); } else { - $empower_icon = 'raise-priority'; + $empower_icon = 'none'; $empower_name = pht('Make Administrator'); } $actions->addAction( id(new PhabricatorActionView()) + ->setGroupKey('user.admin') ->setIcon($empower_icon) ->setName($empower_name) ->setDisabled(($user->getPHID() == $viewer->getPHID())) @@ -90,21 +99,23 @@ $actions->addAction( id(new PhabricatorActionView()) - ->setIcon('tag') + ->setGroupKey('user.admin') + ->setIcon('none') ->setName(pht('Change Username')) ->setWorkflow(true) ->setHref($this->getApplicationURI('rename/'.$user->getID().'/'))); if ($user->getIsDisabled()) { - $disable_icon = 'enable'; + $disable_icon = 'none'; $disable_name = pht('Enable User'); } else { - $disable_icon = 'disable'; + $disable_icon = 'none'; $disable_name = pht('Disable User'); } $actions->addAction( id(new PhabricatorActionView()) + ->setGroupKey('user.admin') ->setIcon($disable_icon) ->setName($disable_name) ->setDisabled(($user->getPHID() == $viewer->getPHID())) @@ -113,7 +124,8 @@ $actions->addAction( id(new PhabricatorActionView()) - ->setIcon('delete') + ->setGroupKey('user.admin') + ->setIcon('none') ->setName(pht('Delete User')) ->setDisabled(($user->getPHID() == $viewer->getPHID())) ->setWorkflow(true) @@ -121,7 +133,8 @@ $actions->addAction( id(new PhabricatorActionView()) - ->setIcon('message') + ->setGroupKey('user.admin') + ->setIcon('none') ->setName(pht('Send Welcome Email')) ->setWorkflow(true) ->setHref($this->getApplicationURI('welcome/'.$user->getID().'/'))); diff --git a/src/view/layout/PhabricatorActionListView.php b/src/view/layout/PhabricatorActionListView.php --- a/src/view/layout/PhabricatorActionListView.php +++ b/src/view/layout/PhabricatorActionListView.php @@ -51,6 +51,69 @@ $action->setUser($this->user); } + $groups = array(); + foreach ($actions as $key => $action) { + if (!$action->getIsContainer()) { + if ($action->getGroupKey()) { + $groups[$action->getGroupKey()][] = $action; + unset($actions[$key]); + } + } + } + + $output = array(); + foreach ($actions as $key => $action) { + if (!$action->getIsContainer()) { + $output[] = $action; + continue; + } + + $group = idx($groups, $action->getGroupKey(), array()); + if (!$group) { + continue; + } + + Javelin::initBehavior('phabricator-reveal-content'); + + $closed_id = celerity_generate_unique_node_id(); + + $open_id = celerity_generate_unique_node_id(); + $item_ids = array($open_id); + + foreach ($group as $item) { + if (!$item->getID()) { + $item->setID(celerity_generate_unique_node_id()); + } + $item_ids[] = $item->getID(); + $item->setStyle('display: none'); + $item->addClass('phabricator-action-list-subitem'); + } + + $output[] = id(clone $action) + ->setHref('#') + ->setID($closed_id) + ->addSigil('reveal-content') + ->setMetadata( + array( + 'hideIDs' => array($closed_id), + 'showIDs' => $item_ids, + )); + + $output[] = id(clone $action) + ->setHref('#') + ->setID($open_id) + ->addSigil('reveal-content') + ->setStyle('display: none') + ->addClass('phabricator-action-list-group-header') + ->setMetadata( + array( + 'hideIDs' => $item_ids, + 'showIDs' => array($closed_id), + )); + + $output[] = $group; + } + require_celerity_resource('phabricator-action-list-view-css'); return phutil_tag( @@ -59,7 +122,7 @@ 'class' => 'phabricator-action-list-view', 'id' => $this->id ), - $actions); + $output); } diff --git a/src/view/layout/PhabricatorActionView.php b/src/view/layout/PhabricatorActionView.php --- a/src/view/layout/PhabricatorActionView.php +++ b/src/view/layout/PhabricatorActionView.php @@ -1,6 +1,6 @@ groupKey = $group_key; + return $this; + } + + public function getGroupKey() { + return $this->groupKey; + } + + public function setIsContainer($is_container) { + $this->isContainer = $is_container; + return $this; + } + + public function getIsContainer() { + return $this->isContainer; + } public function setObjectURI($object_uri) { $this->objectURI = $object_uri; @@ -35,11 +55,6 @@ return $this; } - public function addSigil($sigil) { - $this->sigils[] = $sigil; - return $this; - } - /** * If the user is not logged in and the action is relatively complicated, * give them a generic login link that will re-direct to the page they're @@ -86,7 +101,23 @@ return $this; } - public function render() { + public function getTagName() { + return 'li'; + } + + public function getTagAttributes() { + $classes = array(); + $classes[] = 'phabricator-action-view'; + if ($this->disabled) { + $classes[] = 'phabricator-action-view-disabled'; + } + + return array( + 'class' => $classes, + ); + } + + public function getTagContent() { $icon = null; if ($this->icon) { @@ -113,10 +144,6 @@ $sigils[] = 'download'; } - if ($this->sigils) { - $sigils = array_merge($sigils, $this->sigils); - } - $sigils = $sigils ? implode(' ', $sigils) : null; if ($this->renderAsForm) { @@ -159,18 +186,7 @@ $this->name); } - $classes = array(); - $classes[] = 'phabricator-action-view'; - if ($this->disabled) { - $classes[] = 'phabricator-action-view-disabled'; - } - - return phutil_tag( - 'li', - array( - 'class' => implode(' ', $classes), - ), - array($icon, $item)); + return array($icon, $item); } public static function getAvailableIcons() { diff --git a/webroot/rsrc/css/layout/phabricator-action-list-view.css b/webroot/rsrc/css/layout/phabricator-action-list-view.css --- a/webroot/rsrc/css/layout/phabricator-action-list-view.css +++ b/webroot/rsrc/css/layout/phabricator-action-list-view.css @@ -64,6 +64,14 @@ left: 9px; } +.phabricator-action-list-group-header { + background-color: #f7f7f7; +} + +.phabricator-action-list-subitem .phabricator-action-view-icon { + left: 17px; +} + .device-desktop .phabricator-action-view:hover .phabricator-action-view-item { text-decoration: none; background-color: {$blue};