mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-22 23:02:42 +01:00
Index and surface usage sites for Dashboards
Summary: Depends on D20397. Ref T13272. Similar to the recent "where are Herald rules used" stuff, show which menus Dashboards are installed in. This is mostly straightforward, except that I pulled some of the Herald logic into a parent class so it could be shared. Test Plan: {F6369164} Reviewers: amckinley Reviewed By: amckinley Maniphest Tasks: T13272 Differential Revision: https://secure.phabricator.com/D20398
This commit is contained in:
parent
cbe13b3065
commit
d62f4dbfc9
14 changed files with 306 additions and 61 deletions
|
@ -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' => '9d654dff',
|
'core.pkg.css' => '1db0892b',
|
||||||
'core.pkg.js' => '794952ae',
|
'core.pkg.js' => '794952ae',
|
||||||
'differential.pkg.css' => '8d8360fb',
|
'differential.pkg.css' => '8d8360fb',
|
||||||
'differential.pkg.js' => '67e02996',
|
'differential.pkg.js' => '67e02996',
|
||||||
|
@ -164,7 +164,7 @@ return array(
|
||||||
'rsrc/css/phui/phui-invisible-character-view.css' => 'c694c4a4',
|
'rsrc/css/phui/phui-invisible-character-view.css' => 'c694c4a4',
|
||||||
'rsrc/css/phui/phui-left-right.css' => '68513c34',
|
'rsrc/css/phui/phui-left-right.css' => '68513c34',
|
||||||
'rsrc/css/phui/phui-lightbox.css' => '4ebf22da',
|
'rsrc/css/phui/phui-lightbox.css' => '4ebf22da',
|
||||||
'rsrc/css/phui/phui-list.css' => '734a1039',
|
'rsrc/css/phui/phui-list.css' => 'b05144dd',
|
||||||
'rsrc/css/phui/phui-object-box.css' => 'f434b6be',
|
'rsrc/css/phui/phui-object-box.css' => 'f434b6be',
|
||||||
'rsrc/css/phui/phui-pager.css' => 'd022c7ad',
|
'rsrc/css/phui/phui-pager.css' => 'd022c7ad',
|
||||||
'rsrc/css/phui/phui-pinboard-view.css' => '1f08f5d8',
|
'rsrc/css/phui/phui-pinboard-view.css' => '1f08f5d8',
|
||||||
|
@ -847,7 +847,7 @@ return array(
|
||||||
'phui-invisible-character-view-css' => 'c694c4a4',
|
'phui-invisible-character-view-css' => 'c694c4a4',
|
||||||
'phui-left-right-css' => '68513c34',
|
'phui-left-right-css' => '68513c34',
|
||||||
'phui-lightbox-css' => '4ebf22da',
|
'phui-lightbox-css' => '4ebf22da',
|
||||||
'phui-list-view-css' => '734a1039',
|
'phui-list-view-css' => 'b05144dd',
|
||||||
'phui-object-box-css' => 'f434b6be',
|
'phui-object-box-css' => 'f434b6be',
|
||||||
'phui-oi-big-ui-css' => 'fa74cc35',
|
'phui-oi-big-ui-css' => 'fa74cc35',
|
||||||
'phui-oi-color-css' => 'b517bfa0',
|
'phui-oi-color-css' => 'b517bfa0',
|
||||||
|
|
|
@ -3064,6 +3064,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorEdgeEditType' => 'applications/transactions/edittype/PhabricatorEdgeEditType.php',
|
'PhabricatorEdgeEditType' => 'applications/transactions/edittype/PhabricatorEdgeEditType.php',
|
||||||
'PhabricatorEdgeEditor' => 'infrastructure/edges/editor/PhabricatorEdgeEditor.php',
|
'PhabricatorEdgeEditor' => 'infrastructure/edges/editor/PhabricatorEdgeEditor.php',
|
||||||
'PhabricatorEdgeGraph' => 'infrastructure/edges/util/PhabricatorEdgeGraph.php',
|
'PhabricatorEdgeGraph' => 'infrastructure/edges/util/PhabricatorEdgeGraph.php',
|
||||||
|
'PhabricatorEdgeIndexEngineExtension' => 'applications/search/engineextension/PhabricatorEdgeIndexEngineExtension.php',
|
||||||
'PhabricatorEdgeObject' => 'infrastructure/edges/conduit/PhabricatorEdgeObject.php',
|
'PhabricatorEdgeObject' => 'infrastructure/edges/conduit/PhabricatorEdgeObject.php',
|
||||||
'PhabricatorEdgeObjectQuery' => 'infrastructure/edges/query/PhabricatorEdgeObjectQuery.php',
|
'PhabricatorEdgeObjectQuery' => 'infrastructure/edges/query/PhabricatorEdgeObjectQuery.php',
|
||||||
'PhabricatorEdgeQuery' => 'infrastructure/edges/query/PhabricatorEdgeQuery.php',
|
'PhabricatorEdgeQuery' => 'infrastructure/edges/query/PhabricatorEdgeQuery.php',
|
||||||
|
@ -4067,11 +4068,13 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorProfileMenuEditor' => 'applications/search/editor/PhabricatorProfileMenuEditor.php',
|
'PhabricatorProfileMenuEditor' => 'applications/search/editor/PhabricatorProfileMenuEditor.php',
|
||||||
'PhabricatorProfileMenuEngine' => 'applications/search/engine/PhabricatorProfileMenuEngine.php',
|
'PhabricatorProfileMenuEngine' => 'applications/search/engine/PhabricatorProfileMenuEngine.php',
|
||||||
'PhabricatorProfileMenuItem' => 'applications/search/menuitem/PhabricatorProfileMenuItem.php',
|
'PhabricatorProfileMenuItem' => 'applications/search/menuitem/PhabricatorProfileMenuItem.php',
|
||||||
|
'PhabricatorProfileMenuItemAffectsObjectEdgeType' => 'applications/search/edge/PhabricatorProfileMenuItemAffectsObjectEdgeType.php',
|
||||||
'PhabricatorProfileMenuItemConfiguration' => 'applications/search/storage/PhabricatorProfileMenuItemConfiguration.php',
|
'PhabricatorProfileMenuItemConfiguration' => 'applications/search/storage/PhabricatorProfileMenuItemConfiguration.php',
|
||||||
'PhabricatorProfileMenuItemConfigurationQuery' => 'applications/search/query/PhabricatorProfileMenuItemConfigurationQuery.php',
|
'PhabricatorProfileMenuItemConfigurationQuery' => 'applications/search/query/PhabricatorProfileMenuItemConfigurationQuery.php',
|
||||||
'PhabricatorProfileMenuItemConfigurationTransaction' => 'applications/search/storage/PhabricatorProfileMenuItemConfigurationTransaction.php',
|
'PhabricatorProfileMenuItemConfigurationTransaction' => 'applications/search/storage/PhabricatorProfileMenuItemConfigurationTransaction.php',
|
||||||
'PhabricatorProfileMenuItemConfigurationTransactionQuery' => 'applications/search/query/PhabricatorProfileMenuItemConfigurationTransactionQuery.php',
|
'PhabricatorProfileMenuItemConfigurationTransactionQuery' => 'applications/search/query/PhabricatorProfileMenuItemConfigurationTransactionQuery.php',
|
||||||
'PhabricatorProfileMenuItemIconSet' => 'applications/search/menuitem/PhabricatorProfileMenuItemIconSet.php',
|
'PhabricatorProfileMenuItemIconSet' => 'applications/search/menuitem/PhabricatorProfileMenuItemIconSet.php',
|
||||||
|
'PhabricatorProfileMenuItemIndexEngineExtension' => 'applications/search/engineextension/PhabricatorProfileMenuItemIndexEngineExtension.php',
|
||||||
'PhabricatorProfileMenuItemPHIDType' => 'applications/search/phidtype/PhabricatorProfileMenuItemPHIDType.php',
|
'PhabricatorProfileMenuItemPHIDType' => 'applications/search/phidtype/PhabricatorProfileMenuItemPHIDType.php',
|
||||||
'PhabricatorProfileMenuItemView' => 'applications/search/engine/PhabricatorProfileMenuItemView.php',
|
'PhabricatorProfileMenuItemView' => 'applications/search/engine/PhabricatorProfileMenuItemView.php',
|
||||||
'PhabricatorProfileMenuItemViewList' => 'applications/search/engine/PhabricatorProfileMenuItemViewList.php',
|
'PhabricatorProfileMenuItemViewList' => 'applications/search/engine/PhabricatorProfileMenuItemViewList.php',
|
||||||
|
@ -7292,7 +7295,7 @@ phutil_register_library_map(array(
|
||||||
'HeraldRuleEditor' => 'PhabricatorApplicationTransactionEditor',
|
'HeraldRuleEditor' => 'PhabricatorApplicationTransactionEditor',
|
||||||
'HeraldRuleField' => 'HeraldField',
|
'HeraldRuleField' => 'HeraldField',
|
||||||
'HeraldRuleFieldGroup' => 'HeraldFieldGroup',
|
'HeraldRuleFieldGroup' => 'HeraldFieldGroup',
|
||||||
'HeraldRuleIndexEngineExtension' => 'PhabricatorIndexEngineExtension',
|
'HeraldRuleIndexEngineExtension' => 'PhabricatorEdgeIndexEngineExtension',
|
||||||
'HeraldRuleListController' => 'HeraldController',
|
'HeraldRuleListController' => 'HeraldController',
|
||||||
'HeraldRuleListView' => 'AphrontView',
|
'HeraldRuleListView' => 'AphrontView',
|
||||||
'HeraldRuleNameTransaction' => 'HeraldRuleTransactionType',
|
'HeraldRuleNameTransaction' => 'HeraldRuleTransactionType',
|
||||||
|
@ -9056,6 +9059,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorEdgeEditType' => 'PhabricatorPHIDListEditType',
|
'PhabricatorEdgeEditType' => 'PhabricatorPHIDListEditType',
|
||||||
'PhabricatorEdgeEditor' => 'Phobject',
|
'PhabricatorEdgeEditor' => 'Phobject',
|
||||||
'PhabricatorEdgeGraph' => 'AbstractDirectedGraph',
|
'PhabricatorEdgeGraph' => 'AbstractDirectedGraph',
|
||||||
|
'PhabricatorEdgeIndexEngineExtension' => 'PhabricatorIndexEngineExtension',
|
||||||
'PhabricatorEdgeObject' => array(
|
'PhabricatorEdgeObject' => array(
|
||||||
'Phobject',
|
'Phobject',
|
||||||
'PhabricatorPolicyInterface',
|
'PhabricatorPolicyInterface',
|
||||||
|
@ -10211,16 +10215,19 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorProfileMenuEditor' => 'PhabricatorApplicationTransactionEditor',
|
'PhabricatorProfileMenuEditor' => 'PhabricatorApplicationTransactionEditor',
|
||||||
'PhabricatorProfileMenuEngine' => 'Phobject',
|
'PhabricatorProfileMenuEngine' => 'Phobject',
|
||||||
'PhabricatorProfileMenuItem' => 'Phobject',
|
'PhabricatorProfileMenuItem' => 'Phobject',
|
||||||
|
'PhabricatorProfileMenuItemAffectsObjectEdgeType' => 'PhabricatorEdgeType',
|
||||||
'PhabricatorProfileMenuItemConfiguration' => array(
|
'PhabricatorProfileMenuItemConfiguration' => array(
|
||||||
'PhabricatorSearchDAO',
|
'PhabricatorSearchDAO',
|
||||||
'PhabricatorPolicyInterface',
|
'PhabricatorPolicyInterface',
|
||||||
'PhabricatorExtendedPolicyInterface',
|
'PhabricatorExtendedPolicyInterface',
|
||||||
'PhabricatorApplicationTransactionInterface',
|
'PhabricatorApplicationTransactionInterface',
|
||||||
|
'PhabricatorIndexableInterface',
|
||||||
),
|
),
|
||||||
'PhabricatorProfileMenuItemConfigurationQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
'PhabricatorProfileMenuItemConfigurationQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
||||||
'PhabricatorProfileMenuItemConfigurationTransaction' => 'PhabricatorApplicationTransaction',
|
'PhabricatorProfileMenuItemConfigurationTransaction' => 'PhabricatorApplicationTransaction',
|
||||||
'PhabricatorProfileMenuItemConfigurationTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
|
'PhabricatorProfileMenuItemConfigurationTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
|
||||||
'PhabricatorProfileMenuItemIconSet' => 'PhabricatorIconSet',
|
'PhabricatorProfileMenuItemIconSet' => 'PhabricatorIconSet',
|
||||||
|
'PhabricatorProfileMenuItemIndexEngineExtension' => 'PhabricatorEdgeIndexEngineExtension',
|
||||||
'PhabricatorProfileMenuItemPHIDType' => 'PhabricatorPHIDType',
|
'PhabricatorProfileMenuItemPHIDType' => 'PhabricatorPHIDType',
|
||||||
'PhabricatorProfileMenuItemView' => 'Phobject',
|
'PhabricatorProfileMenuItemView' => 'Phobject',
|
||||||
'PhabricatorProfileMenuItemViewList' => 'Phobject',
|
'PhabricatorProfileMenuItemViewList' => 'Phobject',
|
||||||
|
|
|
@ -32,6 +32,8 @@ final class PhabricatorDashboardViewController
|
||||||
|
|
||||||
$curtain = $this->buildCurtainView($dashboard);
|
$curtain = $this->buildCurtainView($dashboard);
|
||||||
|
|
||||||
|
$usage_box = $this->newUsageView($dashboard);
|
||||||
|
|
||||||
$timeline = $this->buildTransactionTimeline(
|
$timeline = $this->buildTransactionTimeline(
|
||||||
$dashboard,
|
$dashboard,
|
||||||
new PhabricatorDashboardTransactionQuery());
|
new PhabricatorDashboardTransactionQuery());
|
||||||
|
@ -53,6 +55,7 @@ final class PhabricatorDashboardViewController
|
||||||
->setMainColumn(
|
->setMainColumn(
|
||||||
array(
|
array(
|
||||||
$dashboard_box,
|
$dashboard_box,
|
||||||
|
$usage_box,
|
||||||
$timeline,
|
$timeline,
|
||||||
));
|
));
|
||||||
|
|
||||||
|
@ -110,5 +113,89 @@ final class PhabricatorDashboardViewController
|
||||||
return $curtain;
|
return $curtain;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function newUsageView(PhabricatorDashboard $dashboard) {
|
||||||
|
$viewer = $this->getViewer();
|
||||||
|
|
||||||
|
$custom_phids = array();
|
||||||
|
if ($viewer->getPHID()) {
|
||||||
|
$custom_phids[] = $viewer->getPHID();
|
||||||
|
}
|
||||||
|
|
||||||
|
$items = id(new PhabricatorProfileMenuItemConfigurationQuery())
|
||||||
|
->setViewer($viewer)
|
||||||
|
->withAffectedObjectPHIDs(
|
||||||
|
array(
|
||||||
|
$dashboard->getPHID(),
|
||||||
|
))
|
||||||
|
->withCustomPHIDs($custom_phids, $include_global = true)
|
||||||
|
->execute();
|
||||||
|
|
||||||
|
$handle_phids = array();
|
||||||
|
foreach ($items as $item) {
|
||||||
|
$handle_phids[] = $item->getProfilePHID();
|
||||||
|
$custom_phid = $item->getCustomPHID();
|
||||||
|
if ($custom_phid) {
|
||||||
|
$handle_phids[] = $custom_phid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($handle_phids) {
|
||||||
|
$handles = $viewer->loadHandles($handle_phids);
|
||||||
|
} else {
|
||||||
|
$handles = array();
|
||||||
|
}
|
||||||
|
|
||||||
|
$items = msortv($items, 'newUsageSortVector');
|
||||||
|
|
||||||
|
$rows = array();
|
||||||
|
foreach ($items as $item) {
|
||||||
|
$profile_phid = $item->getProfilePHID();
|
||||||
|
$custom_phid = $item->getCustomPHID();
|
||||||
|
|
||||||
|
$profile = $handles[$profile_phid]->renderLink();
|
||||||
|
$profile_icon = $handles[$profile_phid]->getIcon();
|
||||||
|
|
||||||
|
if ($custom_phid) {
|
||||||
|
$custom = $handles[$custom_phid]->renderLink();
|
||||||
|
} else {
|
||||||
|
$custom = pht('Global');
|
||||||
|
}
|
||||||
|
|
||||||
|
$type = $item->getProfileMenuTypeDescription();
|
||||||
|
|
||||||
|
$rows[] = array(
|
||||||
|
id(new PHUIIconView())->setIcon($profile_icon),
|
||||||
|
$type,
|
||||||
|
$profile,
|
||||||
|
$custom,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$usage_table = id(new AphrontTableView($rows))
|
||||||
|
->setHeaders(
|
||||||
|
array(
|
||||||
|
null,
|
||||||
|
pht('Type'),
|
||||||
|
pht('Menu'),
|
||||||
|
pht('Global/Personal'),
|
||||||
|
))
|
||||||
|
->setColumnClasses(
|
||||||
|
array(
|
||||||
|
'center',
|
||||||
|
null,
|
||||||
|
'pri',
|
||||||
|
'wide',
|
||||||
|
));
|
||||||
|
|
||||||
|
$header_view = id(new PHUIHeaderView())
|
||||||
|
->setHeader(pht('Dashboard Used By'));
|
||||||
|
|
||||||
|
$usage_box = id(new PHUIObjectBoxView())
|
||||||
|
->setTable($usage_table)
|
||||||
|
->setHeader($header_view);
|
||||||
|
|
||||||
|
return $usage_box;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,7 @@ final class PhabricatorDashboardPortalPHIDType
|
||||||
$portal = $objects[$phid];
|
$portal = $objects[$phid];
|
||||||
|
|
||||||
$handle
|
$handle
|
||||||
|
->setIcon('fa-compass')
|
||||||
->setName($portal->getName())
|
->setName($portal->getName())
|
||||||
->setURI($portal->getURI());
|
->setURI($portal->getURI());
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
final class HeraldRuleIndexEngineExtension
|
final class HeraldRuleIndexEngineExtension
|
||||||
extends PhabricatorIndexEngineExtension {
|
extends PhabricatorEdgeIndexEngineExtension {
|
||||||
|
|
||||||
const EXTENSIONKEY = 'herald.actions';
|
const EXTENSIONKEY = 'herald.actions';
|
||||||
|
|
||||||
|
@ -17,48 +17,13 @@ final class HeraldRuleIndexEngineExtension
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function indexObject(
|
protected function getIndexEdgeType() {
|
||||||
PhabricatorIndexEngine $engine,
|
return HeraldRuleActionAffectsObjectEdgeType::EDGECONST;
|
||||||
$object) {
|
|
||||||
|
|
||||||
$edge_type = HeraldRuleActionAffectsObjectEdgeType::EDGECONST;
|
|
||||||
|
|
||||||
$old_edges = PhabricatorEdgeQuery::loadDestinationPHIDs(
|
|
||||||
$object->getPHID(),
|
|
||||||
$edge_type);
|
|
||||||
$old_edges = array_fuse($old_edges);
|
|
||||||
|
|
||||||
$new_edges = $this->getPHIDsAffectedByActions($object);
|
|
||||||
$new_edges = array_fuse($new_edges);
|
|
||||||
|
|
||||||
$add_edges = array_diff_key($new_edges, $old_edges);
|
|
||||||
$rem_edges = array_diff_key($old_edges, $new_edges);
|
|
||||||
|
|
||||||
if (!$add_edges && !$rem_edges) {
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$editor = new PhabricatorEdgeEditor();
|
protected function getIndexDestinationPHIDs($object) {
|
||||||
|
$rule = $object;
|
||||||
|
|
||||||
foreach ($add_edges as $phid) {
|
|
||||||
$editor->addEdge($object->getPHID(), $edge_type, $phid);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($rem_edges as $phid) {
|
|
||||||
$editor->removeEdge($object->getPHID(), $edge_type, $phid);
|
|
||||||
}
|
|
||||||
|
|
||||||
$editor->save();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getIndexVersion($object) {
|
|
||||||
$phids = $this->getPHIDsAffectedByActions($object);
|
|
||||||
sort($phids);
|
|
||||||
$phids = implode(':', $phids);
|
|
||||||
return PhabricatorHash::digestForIndex($phids);
|
|
||||||
}
|
|
||||||
|
|
||||||
private function getPHIDsAffectedByActions(HeraldRule $rule) {
|
|
||||||
$viewer = $this->getViewer();
|
$viewer = $this->getViewer();
|
||||||
|
|
||||||
$rule = id(new HeraldRuleQuery())
|
$rule = id(new HeraldRuleQuery())
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhabricatorProfileMenuItemAffectsObjectEdgeType
|
||||||
|
extends PhabricatorEdgeType {
|
||||||
|
|
||||||
|
const EDGECONST = 70;
|
||||||
|
|
||||||
|
}
|
|
@ -121,5 +121,8 @@ final class PhabricatorProfileMenuEditor
|
||||||
return $errors;
|
return $errors;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function supportsSearch() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
abstract class PhabricatorEdgeIndexEngineExtension
|
||||||
|
extends PhabricatorIndexEngineExtension {
|
||||||
|
|
||||||
|
abstract protected function getIndexEdgeType();
|
||||||
|
abstract protected function getIndexDestinationPHIDs($object);
|
||||||
|
|
||||||
|
final public function indexObject(
|
||||||
|
PhabricatorIndexEngine $engine,
|
||||||
|
$object) {
|
||||||
|
|
||||||
|
$edge_type = $this->getIndexEdgeType();
|
||||||
|
|
||||||
|
$old_edges = PhabricatorEdgeQuery::loadDestinationPHIDs(
|
||||||
|
$object->getPHID(),
|
||||||
|
$edge_type);
|
||||||
|
$old_edges = array_fuse($old_edges);
|
||||||
|
|
||||||
|
$new_edges = $this->getIndexDestinationPHIDs($object);
|
||||||
|
$new_edges = array_fuse($new_edges);
|
||||||
|
|
||||||
|
$add_edges = array_diff_key($new_edges, $old_edges);
|
||||||
|
$rem_edges = array_diff_key($old_edges, $new_edges);
|
||||||
|
|
||||||
|
if (!$add_edges && !$rem_edges) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$editor = new PhabricatorEdgeEditor();
|
||||||
|
|
||||||
|
foreach ($add_edges as $phid) {
|
||||||
|
$editor->addEdge($object->getPHID(), $edge_type, $phid);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($rem_edges as $phid) {
|
||||||
|
$editor->removeEdge($object->getPHID(), $edge_type, $phid);
|
||||||
|
}
|
||||||
|
|
||||||
|
$editor->save();
|
||||||
|
}
|
||||||
|
|
||||||
|
final public function getIndexVersion($object) {
|
||||||
|
$phids = $this->getIndexDestinationPHIDs($object);
|
||||||
|
sort($phids);
|
||||||
|
$phids = implode(':', $phids);
|
||||||
|
return PhabricatorHash::digestForIndex($phids);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhabricatorProfileMenuItemIndexEngineExtension
|
||||||
|
extends PhabricatorEdgeIndexEngineExtension {
|
||||||
|
|
||||||
|
const EXTENSIONKEY = 'profile.menu.item';
|
||||||
|
|
||||||
|
public function getExtensionName() {
|
||||||
|
return pht('Profile Menu Item');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function shouldIndexObject($object) {
|
||||||
|
if (!($object instanceof PhabricatorProfileMenuItemConfiguration)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getIndexEdgeType() {
|
||||||
|
return PhabricatorProfileMenuItemAffectsObjectEdgeType::EDGECONST;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getIndexDestinationPHIDs($object) {
|
||||||
|
return $object->getAffectedObjectPHIDs();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -36,11 +36,19 @@ final class PhabricatorDashboardProfileMenuItem
|
||||||
return $this->dashboard;
|
return $this->dashboard;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getAffectedObjectPHIDs(
|
||||||
|
PhabricatorProfileMenuItemConfiguration $config) {
|
||||||
|
return array(
|
||||||
|
$this->getDashboardPHID($config),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public function newPageContent(
|
public function newPageContent(
|
||||||
PhabricatorProfileMenuItemConfiguration $config) {
|
PhabricatorProfileMenuItemConfiguration $config) {
|
||||||
$viewer = $this->getViewer();
|
$viewer = $this->getViewer();
|
||||||
|
|
||||||
$dashboard_phid = $config->getMenuItemProperty('dashboardPHID');
|
$dashboard_phid = $this->getDashboardPHID($config);
|
||||||
|
|
||||||
// Reload the dashboard to attach panels, which we need for rendering.
|
// Reload the dashboard to attach panels, which we need for rendering.
|
||||||
$dashboard = id(new PhabricatorDashboardQuery())
|
$dashboard = id(new PhabricatorDashboardQuery())
|
||||||
|
@ -71,7 +79,7 @@ final class PhabricatorDashboardProfileMenuItem
|
||||||
$viewer = $this->getViewer();
|
$viewer = $this->getViewer();
|
||||||
$dashboard_phids = array();
|
$dashboard_phids = array();
|
||||||
foreach ($items as $item) {
|
foreach ($items as $item) {
|
||||||
$dashboard_phids[] = $item->getMenuItemProperty('dashboardPHID');
|
$dashboard_phids[] = $this->getDashboardPHID($item);
|
||||||
}
|
}
|
||||||
|
|
||||||
$dashboards = id(new PhabricatorDashboardQuery())
|
$dashboards = id(new PhabricatorDashboardQuery())
|
||||||
|
@ -83,7 +91,7 @@ final class PhabricatorDashboardProfileMenuItem
|
||||||
|
|
||||||
$dashboards = mpull($dashboards, null, 'getPHID');
|
$dashboards = mpull($dashboards, null, 'getPHID');
|
||||||
foreach ($items as $item) {
|
foreach ($items as $item) {
|
||||||
$dashboard_phid = $item->getMenuItemProperty('dashboardPHID');
|
$dashboard_phid = $this->getDashboardPHID($item);
|
||||||
$dashboard = idx($dashboards, $dashboard_phid, null);
|
$dashboard = idx($dashboards, $dashboard_phid, null);
|
||||||
|
|
||||||
$menu_item = $item->getMenuItem();
|
$menu_item = $item->getMenuItem();
|
||||||
|
@ -125,7 +133,7 @@ final class PhabricatorDashboardProfileMenuItem
|
||||||
->setLabel(pht('Dashboard'))
|
->setLabel(pht('Dashboard'))
|
||||||
->setIsRequired(true)
|
->setIsRequired(true)
|
||||||
->setDatasource(new PhabricatorDashboardDatasource())
|
->setDatasource(new PhabricatorDashboardDatasource())
|
||||||
->setSingleValue($config->getMenuItemProperty('dashboardPHID')),
|
->setSingleValue($this->getDashboardPHID($config)),
|
||||||
id(new PhabricatorTextEditField())
|
id(new PhabricatorTextEditField())
|
||||||
->setKey('name')
|
->setKey('name')
|
||||||
->setLabel(pht('Name'))
|
->setLabel(pht('Name'))
|
||||||
|
@ -226,6 +234,11 @@ final class PhabricatorDashboardProfileMenuItem
|
||||||
return $errors;
|
return $errors;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function getDashboardPHID(
|
||||||
|
PhabricatorProfileMenuItemConfiguration $config) {
|
||||||
|
return $config->getMenuItemProperty('dashboardPHID');
|
||||||
|
}
|
||||||
|
|
||||||
private function getDashboardHandle() {
|
private function getDashboardHandle() {
|
||||||
return $this->dashboardHandle;
|
return $this->dashboardHandle;
|
||||||
}
|
}
|
||||||
|
|
|
@ -159,4 +159,9 @@ abstract class PhabricatorProfileMenuItem extends Phobject {
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getAffectedObjectPHIDs(
|
||||||
|
PhabricatorProfileMenuItemConfiguration $config) {
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ final class PhabricatorProfileMenuItemConfigurationQuery
|
||||||
private $profilePHIDs;
|
private $profilePHIDs;
|
||||||
private $customPHIDs;
|
private $customPHIDs;
|
||||||
private $includeGlobal;
|
private $includeGlobal;
|
||||||
|
private $affectedObjectPHIDs;
|
||||||
|
|
||||||
public function withIDs(array $ids) {
|
public function withIDs(array $ids) {
|
||||||
$this->ids = $ids;
|
$this->ids = $ids;
|
||||||
|
@ -30,6 +31,11 @@ final class PhabricatorProfileMenuItemConfigurationQuery
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function withAffectedObjectPHIDs(array $phids) {
|
||||||
|
$this->affectedObjectPHIDs = $phids;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
public function newResultObject() {
|
public function newResultObject() {
|
||||||
return new PhabricatorProfileMenuItemConfiguration();
|
return new PhabricatorProfileMenuItemConfiguration();
|
||||||
}
|
}
|
||||||
|
@ -44,21 +50,21 @@ final class PhabricatorProfileMenuItemConfigurationQuery
|
||||||
if ($this->ids !== null) {
|
if ($this->ids !== null) {
|
||||||
$where[] = qsprintf(
|
$where[] = qsprintf(
|
||||||
$conn,
|
$conn,
|
||||||
'id IN (%Ld)',
|
'config.id IN (%Ld)',
|
||||||
$this->ids);
|
$this->ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->phids !== null) {
|
if ($this->phids !== null) {
|
||||||
$where[] = qsprintf(
|
$where[] = qsprintf(
|
||||||
$conn,
|
$conn,
|
||||||
'phid IN (%Ls)',
|
'config.phid IN (%Ls)',
|
||||||
$this->phids);
|
$this->phids);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->profilePHIDs !== null) {
|
if ($this->profilePHIDs !== null) {
|
||||||
$where[] = qsprintf(
|
$where[] = qsprintf(
|
||||||
$conn,
|
$conn,
|
||||||
'profilePHID IN (%Ls)',
|
'config.profilePHID IN (%Ls)',
|
||||||
$this->profilePHIDs);
|
$this->profilePHIDs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,23 +72,45 @@ final class PhabricatorProfileMenuItemConfigurationQuery
|
||||||
if ($this->customPHIDs && $this->includeGlobal) {
|
if ($this->customPHIDs && $this->includeGlobal) {
|
||||||
$where[] = qsprintf(
|
$where[] = qsprintf(
|
||||||
$conn,
|
$conn,
|
||||||
'customPHID IN (%Ls) OR customPHID IS NULL',
|
'config.customPHID IN (%Ls) OR config.customPHID IS NULL',
|
||||||
$this->customPHIDs);
|
$this->customPHIDs);
|
||||||
} else if ($this->customPHIDs) {
|
} else if ($this->customPHIDs) {
|
||||||
$where[] = qsprintf(
|
$where[] = qsprintf(
|
||||||
$conn,
|
$conn,
|
||||||
'customPHID IN (%Ls)',
|
'config.customPHID IN (%Ls)',
|
||||||
$this->customPHIDs);
|
$this->customPHIDs);
|
||||||
} else {
|
} else {
|
||||||
$where[] = qsprintf(
|
$where[] = qsprintf(
|
||||||
$conn,
|
$conn,
|
||||||
'customPHID IS NULL');
|
'config.customPHID IS NULL');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($this->affectedObjectPHIDs !== null) {
|
||||||
|
$where[] = qsprintf(
|
||||||
|
$conn,
|
||||||
|
'affected.dst IN (%Ls)',
|
||||||
|
$this->affectedObjectPHIDs);
|
||||||
|
}
|
||||||
|
|
||||||
return $where;
|
return $where;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function buildJoinClauseParts(AphrontDatabaseConnection $conn) {
|
||||||
|
$joins = parent::buildJoinClauseParts($conn);
|
||||||
|
|
||||||
|
if ($this->affectedObjectPHIDs !== null) {
|
||||||
|
$joins[] = qsprintf(
|
||||||
|
$conn,
|
||||||
|
'JOIN %T affected ON affected.src = config.phid
|
||||||
|
AND affected.type = %d',
|
||||||
|
PhabricatorEdgeConfig::TABLE_NAME_EDGE,
|
||||||
|
PhabricatorProfileMenuItemAffectsObjectEdgeType::EDGECONST);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $joins;
|
||||||
|
}
|
||||||
|
|
||||||
protected function willFilterPage(array $page) {
|
protected function willFilterPage(array $page) {
|
||||||
$items = PhabricatorProfileMenuItem::getAllMenuItems();
|
$items = PhabricatorProfileMenuItem::getAllMenuItems();
|
||||||
foreach ($page as $key => $item) {
|
foreach ($page as $key => $item) {
|
||||||
|
@ -128,4 +156,8 @@ final class PhabricatorProfileMenuItemConfigurationQuery
|
||||||
return 'PhabricatorSearchApplication';
|
return 'PhabricatorSearchApplication';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function getPrimaryTableAlias() {
|
||||||
|
return 'config';
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,8 @@ final class PhabricatorProfileMenuItemConfiguration
|
||||||
implements
|
implements
|
||||||
PhabricatorPolicyInterface,
|
PhabricatorPolicyInterface,
|
||||||
PhabricatorExtendedPolicyInterface,
|
PhabricatorExtendedPolicyInterface,
|
||||||
PhabricatorApplicationTransactionInterface {
|
PhabricatorApplicationTransactionInterface,
|
||||||
|
PhabricatorIndexableInterface {
|
||||||
|
|
||||||
protected $profilePHID;
|
protected $profilePHID;
|
||||||
protected $menuItemKey;
|
protected $menuItemKey;
|
||||||
|
@ -255,6 +256,49 @@ final class PhabricatorProfileMenuItemConfiguration
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getAffectedObjectPHIDs() {
|
||||||
|
return $this->getMenuItem()->getAffectedObjectPHIDs($this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getProfileMenuTypeDescription() {
|
||||||
|
$profile_phid = $this->getProfilePHID();
|
||||||
|
|
||||||
|
$home_phid = id(new PhabricatorHomeApplication())->getPHID();
|
||||||
|
if ($profile_phid === $home_phid) {
|
||||||
|
return pht('Home Menu');
|
||||||
|
}
|
||||||
|
|
||||||
|
$favorites_phid = id(new PhabricatorFavoritesApplication())->getPHID();
|
||||||
|
if ($profile_phid === $favorites_phid) {
|
||||||
|
return pht('Favorites Menu');
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (phid_get_type($profile_phid)) {
|
||||||
|
case PhabricatorProjectProjectPHIDType::TYPECONST:
|
||||||
|
return pht('Project Menu');
|
||||||
|
case PhabricatorDashboardPortalPHIDType::TYPECONST:
|
||||||
|
return pht('Portal Menu');
|
||||||
|
}
|
||||||
|
|
||||||
|
return pht('Profile Menu');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function newUsageSortVector() {
|
||||||
|
// Used to sort items in contexts where we're showing the usage of an
|
||||||
|
// object in menus, like "Dashboard Used By" on Dashboard pages.
|
||||||
|
|
||||||
|
// Sort usage as a custom item after usage as a global item.
|
||||||
|
if ($this->getCustomPHID()) {
|
||||||
|
$is_personal = 1;
|
||||||
|
} else {
|
||||||
|
$is_personal = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return id(new PhutilSortVector())
|
||||||
|
->addInt($is_personal)
|
||||||
|
->addInt($this->getID());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* -( PhabricatorPolicyInterface )----------------------------------------- */
|
/* -( PhabricatorPolicyInterface )----------------------------------------- */
|
||||||
|
|
||||||
|
|
|
@ -261,7 +261,8 @@
|
||||||
|
|
||||||
/* - Action Icon ----------------------------------------------------------- */
|
/* - Action Icon ----------------------------------------------------------- */
|
||||||
|
|
||||||
.phui-list-sidenav .phui-list-item-has-action-icon .phui-list-item-action-href {
|
.phabricator-nav-local .phui-list-item-has-action-icon
|
||||||
|
.phui-list-item-action-href {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
width: 28px;
|
width: 28px;
|
||||||
top: 0;
|
top: 0;
|
||||||
|
@ -273,26 +274,27 @@
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.phui-list-sidenav .phui-list-item-has-action-icon.phui-list-item-selected
|
.phabricator-nav-local .phui-list-item-has-action-icon.phui-list-item-selected
|
||||||
.phui-list-item-href {
|
.phui-list-item-href {
|
||||||
padding-right: 32px;
|
padding-right: 32px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.phui-list-sidenav .phui-list-item-has-action-icon.phui-list-item-selected
|
.phabricator-nav-local .phui-list-item-has-action-icon.phui-list-item-selected
|
||||||
.phui-list-item-action-href {
|
.phui-list-item-action-href {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
.phui-list-sidenav .phui-list-item-has-action-icon
|
.phabricator-nav-local .phui-list-item-has-action-icon
|
||||||
.phui-list-item-action-href:hover {
|
.phui-list-item-action-href:hover {
|
||||||
background-color: rgba({$alphablack},.05);
|
background-color: rgba({$alphablack},.05);
|
||||||
}
|
}
|
||||||
|
|
||||||
.phui-list-sidenav .phui-list-item-has-action-icon .phui-list-item-action-icon {
|
.phabricator-nav-local .phui-list-item-has-action-icon
|
||||||
|
.phui-list-item-action-icon {
|
||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
.phui-list-sidenav .phui-list-item-has-action-icon
|
.phabricator-nav-local .phui-list-item-has-action-icon
|
||||||
.phui-list-item-action-href:hover
|
.phui-list-item-action-href:hover
|
||||||
.phui-list-item-action-icon {
|
.phui-list-item-action-icon {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
|
|
Loading…
Reference in a new issue