1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-26 00:32:42 +01:00

Allow profile menu items to be locked to the top or bottom of the menu

Summary:
Depends on D20353. Ref T13275. This is just some small quality-of-life fixes:

  - When you add items to menus, they currently go below the "Edit Menu/Manage Menu" links by default. This isn't a very good place for them. Instead, lock "edit" items to the bottom of the menu.
  - Lock profile pictures to the top of the menu. This just simplifies things a little.
  - Show more iconography hints on the "edit menu items" UI.
  - Add a "drag stuff to do things" hint if some stuff can be dragged.

Test Plan:
  - Added new items to a Portal, they didn't go to the very bottom. Instead, they went above the "Edit/Manage" links; a sensible place for them.
  - Viewed the "edit menu items" screen, saw more hints and visual richness.
  - Viewed/edited Home, Projects, Portals, Favorites

Reviewers: amckinley

Reviewed By: amckinley

Maniphest Tasks: T13275

Differential Revision: https://secure.phabricator.com/D20355
This commit is contained in:
epriestley 2019-03-30 14:22:08 -07:00
parent 36a8b4ea17
commit 47bf382435
18 changed files with 129 additions and 22 deletions

View file

@ -9,7 +9,7 @@ return array(
'names' => array( 'names' => array(
'conpherence.pkg.css' => '3c8a0668', 'conpherence.pkg.css' => '3c8a0668',
'conpherence.pkg.js' => '020aebcf', 'conpherence.pkg.js' => '020aebcf',
'core.pkg.css' => '7e6e954b', 'core.pkg.css' => 'a1c2d49b',
'core.pkg.js' => 'a747b035', 'core.pkg.js' => 'a747b035',
'differential.pkg.css' => '8d8360fb', 'differential.pkg.css' => '8d8360fb',
'differential.pkg.js' => '67e02996', 'differential.pkg.js' => '67e02996',
@ -132,7 +132,7 @@ return array(
'rsrc/css/phui/object-item/phui-oi-color.css' => 'b517bfa0', 'rsrc/css/phui/object-item/phui-oi-color.css' => 'b517bfa0',
'rsrc/css/phui/object-item/phui-oi-drag-ui.css' => 'da15d3dc', 'rsrc/css/phui/object-item/phui-oi-drag-ui.css' => 'da15d3dc',
'rsrc/css/phui/object-item/phui-oi-flush-ui.css' => '490e2e2e', 'rsrc/css/phui/object-item/phui-oi-flush-ui.css' => '490e2e2e',
'rsrc/css/phui/object-item/phui-oi-list-view.css' => 'a65865a7', 'rsrc/css/phui/object-item/phui-oi-list-view.css' => 'f14f2422',
'rsrc/css/phui/object-item/phui-oi-simple-ui.css' => '6a30fa46', 'rsrc/css/phui/object-item/phui-oi-simple-ui.css' => '6a30fa46',
'rsrc/css/phui/phui-action-list.css' => 'c4972757', 'rsrc/css/phui/phui-action-list.css' => 'c4972757',
'rsrc/css/phui/phui-action-panel.css' => '6c386cbf', 'rsrc/css/phui/phui-action-panel.css' => '6c386cbf',
@ -853,7 +853,7 @@ return array(
'phui-oi-color-css' => 'b517bfa0', 'phui-oi-color-css' => 'b517bfa0',
'phui-oi-drag-ui-css' => 'da15d3dc', 'phui-oi-drag-ui-css' => 'da15d3dc',
'phui-oi-flush-ui-css' => '490e2e2e', 'phui-oi-flush-ui-css' => '490e2e2e',
'phui-oi-list-view-css' => 'a65865a7', 'phui-oi-list-view-css' => 'f14f2422',
'phui-oi-simple-ui-css' => '6a30fa46', 'phui-oi-simple-ui-css' => '6a30fa46',
'phui-pager-css' => 'd022c7ad', 'phui-pager-css' => 'd022c7ad',
'phui-pinboard-view-css' => '1f08f5d8', 'phui-pinboard-view-css' => '1f08f5d8',

View file

@ -24,7 +24,8 @@ final class PhabricatorDashboardPortalProfileMenuEngine
$items[] = $this->newItem() $items[] = $this->newItem()
->setMenuItemKey(PhabricatorDashboardPortalMenuItem::MENUITEMKEY) ->setMenuItemKey(PhabricatorDashboardPortalMenuItem::MENUITEMKEY)
->setBuiltinKey('manage'); ->setBuiltinKey('manage')
->setIsTailItem(true);
return $items; return $items;
} }

View file

@ -6,7 +6,7 @@ final class PhabricatorDashboardPortalMenuItem
const MENUITEMKEY = 'portal'; const MENUITEMKEY = 'portal';
public function getMenuItemTypeIcon() { public function getMenuItemTypeIcon() {
return 'fa-compass'; return 'fa-pencil';
} }
public function getDefaultName() { public function getDefaultName() {

View file

@ -13,6 +13,10 @@ final class PhabricatorHomeLauncherProfileMenuItem
return pht('More Applications'); return pht('More Applications');
} }
public function getMenuItemTypeIcon() {
return 'fa-ellipsis-h';
}
public function canHideMenuItem( public function canHideMenuItem(
PhabricatorProfileMenuItemConfiguration $config) { PhabricatorProfileMenuItemConfiguration $config) {
return false; return false;
@ -50,7 +54,7 @@ final class PhabricatorHomeLauncherProfileMenuItem
$viewer = $this->getViewer(); $viewer = $this->getViewer();
$name = $this->getDisplayName($config); $name = $this->getDisplayName($config);
$icon = 'fa-globe'; $icon = 'fa-ellipsis-h';
$href = '/applications/'; $href = '/applications/';
$item = $this->newItem() $item = $this->newItem()

View file

@ -13,6 +13,10 @@ final class PhabricatorHomeProfileMenuItem
return pht('Home'); return pht('Home');
} }
public function getMenuItemTypeIcon() {
return 'fa-home';
}
public function canMakeDefault( public function canMakeDefault(
PhabricatorProfileMenuItemConfiguration $config) { PhabricatorProfileMenuItemConfiguration $config) {
return true; return true;

View file

@ -22,7 +22,8 @@ final class PhabricatorProjectProfileMenuEngine
$items[] = $this->newItem() $items[] = $this->newItem()
->setBuiltinKey(PhabricatorProject::ITEM_PICTURE) ->setBuiltinKey(PhabricatorProject::ITEM_PICTURE)
->setMenuItemKey(PhabricatorProjectPictureProfileMenuItem::MENUITEMKEY); ->setMenuItemKey(PhabricatorProjectPictureProfileMenuItem::MENUITEMKEY)
->setIsHeadItem(true);
$items[] = $this->newItem() $items[] = $this->newItem()
->setBuiltinKey(PhabricatorProject::ITEM_PROFILE) ->setBuiltinKey(PhabricatorProject::ITEM_PROFILE)
@ -47,7 +48,8 @@ final class PhabricatorProjectProfileMenuEngine
$items[] = $this->newItem() $items[] = $this->newItem()
->setBuiltinKey(PhabricatorProject::ITEM_MANAGE) ->setBuiltinKey(PhabricatorProject::ITEM_MANAGE)
->setMenuItemKey(PhabricatorProjectManageProfileMenuItem::MENUITEMKEY); ->setMenuItemKey(PhabricatorProjectManageProfileMenuItem::MENUITEMKEY)
->setIsTailItem(true);
return $items; return $items;
} }

View file

@ -13,6 +13,10 @@ final class PhabricatorProjectDetailsProfileMenuItem
return pht('Project Details'); return pht('Project Details');
} }
public function getMenuItemTypeIcon() {
return 'fa-file-text-o';
}
public function canHideMenuItem( public function canHideMenuItem(
PhabricatorProfileMenuItemConfiguration $config) { PhabricatorProfileMenuItemConfiguration $config) {
return false; return false;

View file

@ -13,6 +13,10 @@ final class PhabricatorProjectManageProfileMenuItem
return pht('Manage'); return pht('Manage');
} }
public function getMenuItemTypeIcon() {
return 'fa-cog';
}
public function canHideMenuItem( public function canHideMenuItem(
PhabricatorProfileMenuItemConfiguration $config) { PhabricatorProfileMenuItemConfiguration $config) {
return false; return false;

View file

@ -13,6 +13,10 @@ final class PhabricatorProjectMembersProfileMenuItem
return pht('Members'); return pht('Members');
} }
public function getMenuItemTypeIcon() {
return 'fa-users';
}
public function getDisplayName( public function getDisplayName(
PhabricatorProfileMenuItemConfiguration $config) { PhabricatorProfileMenuItemConfiguration $config) {
$name = $config->getMenuItemProperty('name'); $name = $config->getMenuItemProperty('name');

View file

@ -13,6 +13,10 @@ final class PhabricatorProjectPictureProfileMenuItem
return pht('Project Picture'); return pht('Project Picture');
} }
public function getMenuItemTypeIcon() {
return 'fa-image';
}
public function canHideMenuItem( public function canHideMenuItem(
PhabricatorProfileMenuItemConfiguration $config) { PhabricatorProfileMenuItemConfiguration $config) {
return false; return false;

View file

@ -13,6 +13,10 @@ final class PhabricatorProjectSubprojectsProfileMenuItem
return pht('Subprojects'); return pht('Subprojects');
} }
public function getMenuItemTypeIcon() {
return 'fa-sitemap';
}
public function shouldEnableForObject($object) { public function shouldEnableForObject($object) {
if ($object->isMilestone()) { if ($object->isMilestone()) {
return false; return false;

View file

@ -13,6 +13,10 @@ final class PhabricatorProjectWorkboardProfileMenuItem
return pht('Workboard'); return pht('Workboard');
} }
public function getMenuItemTypeIcon() {
return 'fa-columns';
}
public function canMakeDefault( public function canMakeDefault(
PhabricatorProfileMenuItemConfiguration $config) { PhabricatorProfileMenuItemConfiguration $config) {
return true; return true;

View file

@ -460,6 +460,12 @@ abstract class PhabricatorProfileMenuEngine extends Phobject {
// stored config: it corresponds to an out-of-date or uninstalled // stored config: it corresponds to an out-of-date or uninstalled
// item. // item.
if (isset($items[$builtin_key])) { if (isset($items[$builtin_key])) {
$builtin_item = $items[$builtin_key];
// Copy runtime properties from the builtin item to the stored item.
$stored_item->setIsHeadItem($builtin_item->getIsHeadItem());
$stored_item->setIsTailItem($builtin_item->getIsTailItem());
$items[$builtin_key] = $stored_item; $items[$builtin_key] = $stored_item;
} else { } else {
continue; continue;
@ -802,6 +808,7 @@ abstract class PhabricatorProfileMenuEngine extends Phobject {
->setID($list_id) ->setID($list_id)
->setNoDataString(pht('This menu currently has no items.')); ->setNoDataString(pht('This menu currently has no items.'));
$any_draggable = false;
foreach ($items as $item) { foreach ($items as $item) {
$id = $item->getID(); $id = $item->getID();
$builtin_key = $item->getBuiltinKey(); $builtin_key = $item->getBuiltinKey();
@ -822,14 +829,25 @@ abstract class PhabricatorProfileMenuEngine extends Phobject {
$view->setHeader($name); $view->setHeader($name);
$view->addAttribute($type); $view->addAttribute($type);
$icon = $item->getMenuItem()->getMenuItemTypeIcon();
if ($icon !== null) {
$view->setStatusIcon($icon);
}
if ($can_edit) { if ($can_edit) {
$view $can_move = (!$item->getIsHeadItem() && !$item->getIsTailItem());
->setGrippable(true) if ($can_move) {
->addSigil('profile-menu-item') $view
->setMetadata( ->setGrippable(true)
array( ->addSigil('profile-menu-item')
'key' => nonempty($id, $builtin_key), ->setMetadata(
)); array(
'key' => nonempty($id, $builtin_key),
));
$any_draggable = true;
} else {
$view->setGrippable(false);
}
if ($id) { if ($id) {
$default_uri = $this->getItemURI("default/{$id}/"); $default_uri = $this->getItemURI("default/{$id}/");
@ -944,8 +962,16 @@ abstract class PhabricatorProfileMenuEngine extends Phobject {
->setHeader(pht('Menu Items')) ->setHeader(pht('Menu Items'))
->setHeaderIcon('fa-list'); ->setHeaderIcon('fa-list');
$list_header = id(new PHUIHeaderView())
->setHeader(pht('Current Menu Items'));
if ($any_draggable) {
$list_header->setSubheader(
pht('Drag items in this list to reorder them.'));
}
$box = id(new PHUIObjectBoxView()) $box = id(new PHUIObjectBoxView())
->setHeaderText(pht('Current Menu Items')) ->setHeader($list_header)
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
->setObjectList($list); ->setObjectList($list);
@ -1190,7 +1216,8 @@ abstract class PhabricatorProfileMenuEngine extends Phobject {
protected function newManageItem() { protected function newManageItem() {
return $this->newItem() return $this->newItem()
->setBuiltinKey(self::ITEM_MANAGE) ->setBuiltinKey(self::ITEM_MANAGE)
->setMenuItemKey(PhabricatorManageProfileMenuItem::MENUITEMKEY); ->setMenuItemKey(PhabricatorManageProfileMenuItem::MENUITEMKEY)
->setIsTailItem(true);
} }
public function adjustDefault($key) { public function adjustDefault($key) {

View file

@ -7,7 +7,7 @@ final class PhabricatorLabelProfileMenuItem
const FIELD_NAME = 'name'; const FIELD_NAME = 'name';
public function getMenuItemTypeIcon() { public function getMenuItemTypeIcon() {
return 'fa-map-signs'; return 'fa-tag';
} }
public function getMenuItemTypeName() { public function getMenuItemTypeName() {

View file

@ -13,6 +13,10 @@ final class PhabricatorManageProfileMenuItem
return pht('Edit Menu'); return pht('Edit Menu');
} }
public function getMenuItemTypeIcon() {
return 'fa-pencil';
}
public function canHideMenuItem( public function canHideMenuItem(
PhabricatorProfileMenuItemConfiguration $config) { PhabricatorProfileMenuItemConfiguration $config) {
return false; return false;

View file

@ -17,6 +17,8 @@ final class PhabricatorProfileMenuItemConfiguration
private $profileObject = self::ATTACHABLE; private $profileObject = self::ATTACHABLE;
private $menuItem = self::ATTACHABLE; private $menuItem = self::ATTACHABLE;
private $isHeadItem = false;
private $isTailItem = false;
const VISIBILITY_DEFAULT = 'default'; const VISIBILITY_DEFAULT = 'default';
const VISIBILITY_VISIBLE = 'visible'; const VISIBILITY_VISIBLE = 'visible';
@ -158,6 +160,15 @@ final class PhabricatorProfileMenuItemConfiguration
$is_global = 1; $is_global = 1;
} }
// Sort "head" items above other items and "tail" items after other items.
if ($this->getIsHeadItem()) {
$force_position = 0;
} else if ($this->getIsTailItem()) {
$force_position = 2;
} else {
$force_position = 1;
}
// Sort items with an explicit order above items without an explicit order, // Sort items with an explicit order above items without an explicit order,
// so any newly created builtins go to the bottom. // so any newly created builtins go to the bottom.
$order = $this->getMenuItemOrder(); $order = $this->getMenuItemOrder();
@ -169,6 +180,7 @@ final class PhabricatorProfileMenuItemConfiguration
return id(new PhutilSortVector()) return id(new PhutilSortVector())
->addInt($is_global) ->addInt($is_global)
->addInt($force_position)
->addInt($has_order) ->addInt($has_order)
->addInt((int)$order) ->addInt((int)$order)
->addInt((int)$this->getID()); ->addInt((int)$this->getID());
@ -207,6 +219,25 @@ final class PhabricatorProfileMenuItemConfiguration
return $this->getMenuItem()->newPageContent($this); return $this->getMenuItem()->newPageContent($this);
} }
public function setIsHeadItem($is_head_item) {
$this->isHeadItem = $is_head_item;
return $this;
}
public function getIsHeadItem() {
return $this->isHeadItem;
}
public function setIsTailItem($is_tail_item) {
$this->isTailItem = $is_tail_item;
return $this;
}
public function getIsTailItem() {
return $this->isTailItem;
}
/* -( PhabricatorPolicyInterface )----------------------------------------- */ /* -( PhabricatorPolicyInterface )----------------------------------------- */

View file

@ -330,8 +330,14 @@ final class PHUIObjectItemView extends AphrontTagView {
Javelin::initBehavior('phui-selectable-list'); Javelin::initBehavior('phui-selectable-list');
} }
if ($this->getGrippable()) { $is_grippable = $this->getGrippable();
$item_classes[] = 'phui-oi-grippable'; if ($is_grippable !== null) {
$item_classes[] = 'phui-oi-has-grip';
if ($is_grippable) {
$item_classes[] = 'phui-oi-grippable';
} else {
$item_classes[] = 'phui-oi-ungrippable';
}
} }
if ($this->getImageURI()) { if ($this->getImageURI()) {
@ -580,7 +586,7 @@ final class PHUIObjectItemView extends AphrontTagView {
} }
$grippable = null; $grippable = null;
if ($this->getGrippable()) { if ($this->getGrippable() !== null) {
$grippable = phutil_tag( $grippable = phutil_tag(
'div', 'div',
array( array(

View file

@ -132,11 +132,15 @@ ul.phui-oi-list-view {
background: url('/rsrc/image/texture/grip.png') center center no-repeat; background: url('/rsrc/image/texture/grip.png') center center no-repeat;
} }
.phui-oi-ungrippable .phui-oi-grip {
opacity: 0.25;
}
.device .phui-oi-grip { .device .phui-oi-grip {
display: none; display: none;
} }
.phui-oi-grippable .phui-oi-frame { .phui-oi-has-grip .phui-oi-frame {
padding-left: 16px; padding-left: 16px;
} }