1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-12-04 20:52:43 +01:00

(stable) Allow menu items to render their own content; make Dashboard items render on-page

Summary:
Ref T11957. When you click a dashboard item, it now sends you to `/<app>/item/view/123/`, which renders the proper crumbs, navigation, etc., with the dashboard as page content.

This works as you'd expect in Projects:

{F2508568}

It's sliiiightly odd in Favorites since we nuke the nav menu, but seems basically fine?

{F2508571}

Test Plan:
  - Created a dashboard panel on a project.
  - Clicked it, saw it render.
  - Made it the default panel, viewed project default screen, saw dashboard.
  - Disabled every panel I could, still saw reasonable behavior (this is silly anyway).

Reviewers: chad

Reviewed By: chad

Maniphest Tasks: T11957

Differential Revision: https://secure.phabricator.com/D17255
This commit is contained in:
epriestley 2017-01-26 12:14:02 -08:00
parent 23c54262ca
commit 2dc4692021
10 changed files with 113 additions and 27 deletions

View file

@ -7,7 +7,7 @@ final class PhabricatorFavoritesProfileMenuEngine
return true; return true;
} }
protected function getItemURI($path) { public function getItemURI($path) {
$object = $this->getProfileObject(); $object = $this->getProfileObject();
$custom = $this->getCustomPHID(); $custom = $this->getCustomPHID();

View file

@ -7,7 +7,7 @@ final class PhabricatorHomeProfileMenuEngine
return true; return true;
} }
protected function getItemURI($path) { public function getItemURI($path) {
$object = $this->getProfileObject(); $object = $this->getProfileObject();
$custom = $this->getCustomPHID(); $custom = $this->getCustomPHID();

View file

@ -10,7 +10,7 @@ final class PhabricatorPeopleProfileMenuEngine
return false; return false;
} }
protected function getItemURI($path) { public function getItemURI($path) {
$user = $this->getProfileObject(); $user = $this->getProfileObject();
$username = $user->getUsername(); $username = $user->getUsername();
$username = phutil_escape_uri($username); $username = phutil_escape_uri($username);

View file

@ -25,9 +25,10 @@ final class PhabricatorProjectViewController
$controller_object = new PhabricatorProjectBoardViewController(); $controller_object = new PhabricatorProjectBoardViewController();
break; break;
case PhabricatorProject::ITEM_PROFILE: case PhabricatorProject::ITEM_PROFILE:
default:
$controller_object = new PhabricatorProjectProfileController(); $controller_object = new PhabricatorProjectProfileController();
break; break;
default:
return $engine->buildResponse();
} }
return $this->delegateToController($controller_object); return $this->delegateToController($controller_object);

View file

@ -7,7 +7,7 @@ final class PhabricatorProjectProfileMenuEngine
return true; return true;
} }
protected function getItemURI($path) { public function getItemURI($path) {
$project = $this->getProfileObject(); $project = $this->getProfileObject();
$id = $project->getID(); $id = $project->getID();
return "/project/{$id}/item/{$path}"; return "/project/{$id}/item/{$path}";

View file

@ -18,11 +18,6 @@ final class PhabricatorProjectManageProfileMenuItem
return false; return false;
} }
public function canMakeDefault(
PhabricatorProfileMenuItemConfiguration $config) {
return true;
}
public function getDisplayName( public function getDisplayName(
PhabricatorProfileMenuItemConfiguration $config) { PhabricatorProfileMenuItemConfiguration $config) {
$name = $config->getMenuItemProperty('name'); $name = $config->getMenuItemProperty('name');

View file

@ -82,7 +82,7 @@ abstract class PhabricatorProfileMenuEngine extends Phobject {
return $this->showNavigation; return $this->showNavigation;
} }
abstract protected function getItemURI($path); abstract public function getItemURI($path);
abstract protected function isMenuEngineConfigurable(); abstract protected function isMenuEngineConfigurable();
abstract protected function getBuiltinProfileItems($object); abstract protected function getBuiltinProfileItems($object);
@ -102,6 +102,9 @@ abstract class PhabricatorProfileMenuEngine extends Phobject {
$request = $controller->getRequest(); $request = $controller->getRequest();
$item_action = $request->getURIData('itemAction'); $item_action = $request->getURIData('itemAction');
if (!$item_action) {
$item_action = 'view';
}
// If the engine is not configurable, don't respond to any of the editing // If the engine is not configurable, don't respond to any of the editing
// or configuration routes. // or configuration routes.
@ -136,6 +139,12 @@ abstract class PhabricatorProfileMenuEngine extends Phobject {
} }
} }
if (!$selected_item) {
if ($item_action == 'view') {
$selected_item = $this->getDefaultItem();
}
}
switch ($item_action) { switch ($item_action) {
case 'view': case 'view':
case 'info': case 'info':
@ -159,21 +168,33 @@ abstract class PhabricatorProfileMenuEngine extends Phobject {
} }
$navigation = $this->buildNavigation(); $navigation = $this->buildNavigation();
$navigation->selectFilter('item.configure');
$crumbs = $controller->buildApplicationCrumbsForEditEngine(); $crumbs = $controller->buildApplicationCrumbsForEditEngine();
switch ($this->getMenuType()) {
case 'personal': // TODO: This stuff might need a little tweaking at some point, since it
$crumbs->addTextCrumb(pht('Personal')); // causes "Global" and "Personal" to show up in contexts where they don't
break; // make sense, notably Projects.
case 'global': if ($item_action != 'view') {
$crumbs->addTextCrumb(pht('Global')); $navigation->selectFilter('item.configure');
break; switch ($this->getMenuType()) {
case 'personal':
$crumbs->addTextCrumb(pht('Personal'));
break;
case 'global':
$crumbs->addTextCrumb(pht('Global'));
break;
}
} }
switch ($item_action) { switch ($item_action) {
case 'view': case 'view':
$navigation->selectFilter($selected_item->getItemIdentifier());
$content = $this->buildItemViewContent($selected_item); $content = $this->buildItemViewContent($selected_item);
$crumbs->addTextCrumb($selected_item->getDisplayName());
if (!$content) {
return new Aphront404Response();
}
break; break;
case 'configure': case 'configure':
$content = $this->buildItemConfigureContent($item_list); $content = $this->buildItemConfigureContent($item_list);
@ -225,6 +246,7 @@ abstract class PhabricatorProfileMenuEngine extends Phobject {
if ($this->getShowNavigation()) { if ($this->getShowNavigation()) {
$page->setNavigation($navigation); $page->setNavigation($navigation);
} }
return $page; return $page;
} }
@ -269,13 +291,8 @@ abstract class PhabricatorProfileMenuEngine extends Phobject {
if (count($items) == 1) { if (count($items) == 1) {
$item = head($items); $item = head($items);
if ($item->getKey() === null) { if ($item->getKey() === null) {
$builtin_key = $menu_item->getBuiltinKey(); $item_identifier = $menu_item->getItemIdentifier();
$item_phid = $menu_item->getPHID(); $item->setKey($item_identifier);
if ($builtin_key !== null) {
$item->setKey($builtin_key);
} else if ($item_phid !== null) {
$item->setKey($item_phid);
}
} }
} }
@ -326,6 +343,7 @@ abstract class PhabricatorProfileMenuEngine extends Phobject {
foreach ($stored_items as $stored_item) { foreach ($stored_items as $stored_item) {
$impl = $stored_item->getMenuItem(); $impl = $stored_item->getMenuItem();
$impl->setViewer($viewer); $impl->setViewer($viewer);
$impl->setEngine($this);
} }
// Merge the stored items into the builtin items. If a builtin item has // Merge the stored items into the builtin items. If a builtin item has
@ -442,6 +460,7 @@ abstract class PhabricatorProfileMenuEngine extends Phobject {
$item = clone $item; $item = clone $item;
$item->setViewer($viewer); $item->setViewer($viewer);
$item->setEngine($this);
$builtin $builtin
->setProfilePHID($object->getPHID()) ->setProfilePHID($object->getPHID())
@ -546,6 +565,10 @@ abstract class PhabricatorProfileMenuEngine extends Phobject {
->setURI($this->getConfigureURI()); ->setURI($this->getConfigureURI());
} }
private function buildItemViewContent(
PhabricatorProfileMenuItemConfiguration $item) {
return $item->newPageContent();
}
private function buildItemConfigureContent(array $items) { private function buildItemConfigureContent(array $items) {
$viewer = $this->getViewer(); $viewer = $this->getViewer();

View file

@ -21,6 +21,11 @@ final class PhabricatorDashboardProfileMenuItem
return true; return true;
} }
public function canMakeDefault(
PhabricatorProfileMenuItemConfiguration $config) {
return true;
}
public function attachDashboard($dashboard) { public function attachDashboard($dashboard) {
$this->dashboard = $dashboard; $this->dashboard = $dashboard;
return $this; return $this;
@ -28,14 +33,39 @@ final class PhabricatorDashboardProfileMenuItem
public function getDashboard() { public function getDashboard() {
$dashboard = $this->dashboard; $dashboard = $this->dashboard;
if (!$dashboard) { if (!$dashboard) {
return null; return null;
} else if ($dashboard->isArchived()) { } else if ($dashboard->isArchived()) {
return null; return null;
} }
return $dashboard; return $dashboard;
} }
public function newPageContent(
PhabricatorProfileMenuItemConfiguration $config) {
$viewer = $this->getViewer();
$dashboard_phid = $config->getMenuItemProperty('dashboardPHID');
// Reload the dashboard to attach panels, which we need for rendering.
$dashboard = id(new PhabricatorDashboardQuery())
->setViewer($viewer)
->withPHIDs(array($dashboard_phid))
->needPanels(true)
->executeOne();
if (!$dashboard) {
return null;
}
$engine = id(new PhabricatorDashboardRenderingEngine())
->setViewer($viewer)
->setDashboard($dashboard);
return $engine->renderDashboard();
}
public function willBuildNavigationItems(array $items) { public function willBuildNavigationItems(array $items) {
$viewer = $this->getViewer(); $viewer = $this->getViewer();
$dashboard_phids = array(); $dashboard_phids = array();
@ -100,7 +130,7 @@ final class PhabricatorDashboardProfileMenuItem
$icon = $dashboard->getIcon(); $icon = $dashboard->getIcon();
$name = $this->getDisplayName($config); $name = $this->getDisplayName($config);
$href = $dashboard->getViewURI(); $href = $this->getItemViewURI($config);
$item = $this->newItem() $item = $this->newItem()
->setHref($href) ->setHref($href)

View file

@ -3,6 +3,7 @@
abstract class PhabricatorProfileMenuItem extends Phobject { abstract class PhabricatorProfileMenuItem extends Phobject {
private $viewer; private $viewer;
private $engine;
final public function buildNavigationMenuItems( final public function buildNavigationMenuItems(
PhabricatorProfileMenuItemConfiguration $config) { PhabricatorProfileMenuItemConfiguration $config) {
@ -55,6 +56,15 @@ abstract class PhabricatorProfileMenuItem extends Phobject {
return $this->viewer; return $this->viewer;
} }
public function setEngine(PhabricatorProfileMenuEngine $engine) {
$this->engine = $engine;
return $this;
}
public function getEngine() {
return $this->engine;
}
final public function getMenuItemKey() { final public function getMenuItemKey() {
return $this->getPhobjectClassConstant('MENUITEMKEY'); return $this->getPhobjectClassConstant('MENUITEMKEY');
} }
@ -70,6 +80,20 @@ abstract class PhabricatorProfileMenuItem extends Phobject {
return new PHUIListItemView(); return new PHUIListItemView();
} }
public function newPageContent(
PhabricatorProfileMenuItemConfiguration $config) {
return null;
}
public function getItemViewURI(
PhabricatorProfileMenuItemConfiguration $config) {
$engine = $this->getEngine();
$key = $config->getItemIdentifier();
return $engine->getItemURI("view/{$key}/");
}
public function validateTransactions( public function validateTransactions(
PhabricatorProfileMenuItemConfiguration $config, PhabricatorProfileMenuItemConfiguration $config,
$field_key, $field_key,

View file

@ -185,6 +185,19 @@ final class PhabricatorProfileMenuItemConfiguration
return ($this->getVisibility() === self::VISIBILITY_DEFAULT); return ($this->getVisibility() === self::VISIBILITY_DEFAULT);
} }
public function getItemIdentifier() {
$id = $this->getID();
if ($id) {
return (int)$id;
}
return $this->getBuiltinKey();
}
public function newPageContent() {
return $this->getMenuItem()->newPageContent($this);
}
/* -( PhabricatorPolicyInterface )----------------------------------------- */ /* -( PhabricatorPolicyInterface )----------------------------------------- */