mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-26 00:32:42 +01:00
On panel pages, show where panels are used
Summary: Depends on D20398. Ref T13272. Fixes T6018. Previously, panels showed "used on dashboards: x, y", but this did not include cases where a panel was used by another container panel (today, a tab panel). Do edge indexing when a dashboard or panel is saved, then pull the edges on the Panel page so we can provide a full list of uses. Test Plan: {F6369289} Reviewers: amckinley Reviewed By: amckinley Maniphest Tasks: T13272, T6018 Differential Revision: https://secure.phabricator.com/D20399
This commit is contained in:
parent
d62f4dbfc9
commit
51f2ed498d
17 changed files with 200 additions and 15 deletions
|
@ -9,7 +9,7 @@ return array(
|
|||
'names' => array(
|
||||
'conpherence.pkg.css' => '3c8a0668',
|
||||
'conpherence.pkg.js' => '020aebcf',
|
||||
'core.pkg.css' => '1db0892b',
|
||||
'core.pkg.css' => '294e365c',
|
||||
'core.pkg.js' => '794952ae',
|
||||
'differential.pkg.css' => '8d8360fb',
|
||||
'differential.pkg.js' => '67e02996',
|
||||
|
@ -30,7 +30,7 @@ return array(
|
|||
'rsrc/css/aphront/notification.css' => '30240bd2',
|
||||
'rsrc/css/aphront/panel-view.css' => '46923d46',
|
||||
'rsrc/css/aphront/phabricator-nav-view.css' => 'f8a0c1bf',
|
||||
'rsrc/css/aphront/table-view.css' => '7dc3a9c2',
|
||||
'rsrc/css/aphront/table-view.css' => '5f13a9e4',
|
||||
'rsrc/css/aphront/tokenizer.css' => 'b52d0668',
|
||||
'rsrc/css/aphront/tooltip.css' => 'e3f2412f',
|
||||
'rsrc/css/aphront/typeahead-browse.css' => 'b7ed02d2',
|
||||
|
@ -531,7 +531,7 @@ return array(
|
|||
'aphront-list-filter-view-css' => 'feb64255',
|
||||
'aphront-multi-column-view-css' => 'fbc00ba3',
|
||||
'aphront-panel-view-css' => '46923d46',
|
||||
'aphront-table-view-css' => '7dc3a9c2',
|
||||
'aphront-table-view-css' => '5f13a9e4',
|
||||
'aphront-tokenizer-control-css' => 'b52d0668',
|
||||
'aphront-tooltip-css' => 'e3f2412f',
|
||||
'aphront-typeahead-control-css' => '8779483d',
|
||||
|
|
|
@ -2930,6 +2930,8 @@ phutil_register_library_map(array(
|
|||
'PhabricatorDashboardObjectInstallWorkflow' => 'applications/dashboard/install/PhabricatorDashboardObjectInstallWorkflow.php',
|
||||
'PhabricatorDashboardPanel' => 'applications/dashboard/storage/PhabricatorDashboardPanel.php',
|
||||
'PhabricatorDashboardPanelArchiveController' => 'applications/dashboard/controller/panel/PhabricatorDashboardPanelArchiveController.php',
|
||||
'PhabricatorDashboardPanelContainerIndexEngineExtension' => 'applications/dashboard/engineextension/PhabricatorDashboardPanelContainerIndexEngineExtension.php',
|
||||
'PhabricatorDashboardPanelContainerInterface' => 'applications/dashboard/interface/PhabricatorDashboardPanelContainerInterface.php',
|
||||
'PhabricatorDashboardPanelDatasource' => 'applications/dashboard/typeahead/PhabricatorDashboardPanelDatasource.php',
|
||||
'PhabricatorDashboardPanelEditConduitAPIMethod' => 'applications/dashboard/conduit/PhabricatorDashboardPanelEditConduitAPIMethod.php',
|
||||
'PhabricatorDashboardPanelEditController' => 'applications/dashboard/controller/panel/PhabricatorDashboardPanelEditController.php',
|
||||
|
@ -2951,6 +2953,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorDashboardPanelTransactionQuery' => 'applications/dashboard/query/PhabricatorDashboardPanelTransactionQuery.php',
|
||||
'PhabricatorDashboardPanelTransactionType' => 'applications/dashboard/xaction/panel/PhabricatorDashboardPanelTransactionType.php',
|
||||
'PhabricatorDashboardPanelType' => 'applications/dashboard/paneltype/PhabricatorDashboardPanelType.php',
|
||||
'PhabricatorDashboardPanelUsedByObjectEdgeType' => 'applications/search/edge/PhabricatorDashboardPanelUsedByObjectEdgeType.php',
|
||||
'PhabricatorDashboardPanelViewController' => 'applications/dashboard/controller/panel/PhabricatorDashboardPanelViewController.php',
|
||||
'PhabricatorDashboardPortal' => 'applications/dashboard/storage/PhabricatorDashboardPortal.php',
|
||||
'PhabricatorDashboardPortalController' => 'applications/dashboard/controller/portal/PhabricatorDashboardPortalController.php',
|
||||
|
@ -3724,6 +3727,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorObjectRemarkupRule' => 'infrastructure/markup/rule/PhabricatorObjectRemarkupRule.php',
|
||||
'PhabricatorObjectSelectorDialog' => 'view/control/PhabricatorObjectSelectorDialog.php',
|
||||
'PhabricatorObjectStatus' => 'infrastructure/status/PhabricatorObjectStatus.php',
|
||||
'PhabricatorObjectUsesDashboardPanelEdgeType' => 'applications/search/edge/PhabricatorObjectUsesDashboardPanelEdgeType.php',
|
||||
'PhabricatorOffsetPagedQuery' => 'infrastructure/query/PhabricatorOffsetPagedQuery.php',
|
||||
'PhabricatorOldWorldContentSource' => 'infrastructure/contentsource/PhabricatorOldWorldContentSource.php',
|
||||
'PhabricatorOlderInlinesSetting' => 'applications/settings/setting/PhabricatorOlderInlinesSetting.php',
|
||||
|
@ -8888,6 +8892,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorDestructibleInterface',
|
||||
'PhabricatorProjectInterface',
|
||||
'PhabricatorNgramsInterface',
|
||||
'PhabricatorDashboardPanelContainerInterface',
|
||||
),
|
||||
'PhabricatorDashboardAddPanelController' => 'PhabricatorDashboardController',
|
||||
'PhabricatorDashboardApplication' => 'PhabricatorApplication',
|
||||
|
@ -8918,8 +8923,10 @@ phutil_register_library_map(array(
|
|||
'PhabricatorFlaggableInterface',
|
||||
'PhabricatorDestructibleInterface',
|
||||
'PhabricatorNgramsInterface',
|
||||
'PhabricatorDashboardPanelContainerInterface',
|
||||
),
|
||||
'PhabricatorDashboardPanelArchiveController' => 'PhabricatorDashboardController',
|
||||
'PhabricatorDashboardPanelContainerIndexEngineExtension' => 'PhabricatorEdgeIndexEngineExtension',
|
||||
'PhabricatorDashboardPanelDatasource' => 'PhabricatorTypeaheadDatasource',
|
||||
'PhabricatorDashboardPanelEditConduitAPIMethod' => 'PhabricatorEditEngineAPIMethod',
|
||||
'PhabricatorDashboardPanelEditController' => 'PhabricatorDashboardController',
|
||||
|
@ -8941,6 +8948,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorDashboardPanelTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
|
||||
'PhabricatorDashboardPanelTransactionType' => 'PhabricatorModularTransactionType',
|
||||
'PhabricatorDashboardPanelType' => 'Phobject',
|
||||
'PhabricatorDashboardPanelUsedByObjectEdgeType' => 'PhabricatorEdgeType',
|
||||
'PhabricatorDashboardPanelViewController' => 'PhabricatorDashboardController',
|
||||
'PhabricatorDashboardPortal' => array(
|
||||
'PhabricatorDashboardDAO',
|
||||
|
@ -9799,6 +9807,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorObjectRemarkupRule' => 'PhutilRemarkupRule',
|
||||
'PhabricatorObjectSelectorDialog' => 'Phobject',
|
||||
'PhabricatorObjectStatus' => 'Phobject',
|
||||
'PhabricatorObjectUsesDashboardPanelEdgeType' => 'PhabricatorEdgeType',
|
||||
'PhabricatorOffsetPagedQuery' => 'PhabricatorQuery',
|
||||
'PhabricatorOldWorldContentSource' => 'PhabricatorContentSource',
|
||||
'PhabricatorOlderInlinesSetting' => 'PhabricatorSelectSetting',
|
||||
|
|
|
@ -172,6 +172,8 @@ final class PhabricatorDashboardViewController
|
|||
}
|
||||
|
||||
$usage_table = id(new AphrontTableView($rows))
|
||||
->setNoDataString(
|
||||
pht('This dashboard has not been added to any menus.'))
|
||||
->setHeaders(
|
||||
array(
|
||||
null,
|
||||
|
|
|
@ -35,6 +35,8 @@ final class PhabricatorDashboardPanelViewController
|
|||
$header = $this->buildHeaderView($panel);
|
||||
$curtain = $this->buildCurtainView($panel);
|
||||
|
||||
$usage_box = $this->newUsageView($panel);
|
||||
|
||||
$timeline = $this->buildTransactionTimeline(
|
||||
$panel,
|
||||
new PhabricatorDashboardPanelTransactionQuery());
|
||||
|
@ -57,6 +59,7 @@ final class PhabricatorDashboardPanelViewController
|
|||
->setCurtain($curtain)
|
||||
->setMainColumn(array(
|
||||
$rendered_panel,
|
||||
$usage_box,
|
||||
$timeline,
|
||||
));
|
||||
|
||||
|
@ -122,4 +125,51 @@ final class PhabricatorDashboardPanelViewController
|
|||
return $curtain;
|
||||
}
|
||||
|
||||
private function newUsageView(PhabricatorDashboardPanel $panel) {
|
||||
$viewer = $this->getViewer();
|
||||
|
||||
$object_phids = PhabricatorEdgeQuery::loadDestinationPHIDs(
|
||||
$panel->getPHID(),
|
||||
PhabricatorDashboardPanelUsedByObjectEdgeType::EDGECONST);
|
||||
|
||||
if ($object_phids) {
|
||||
$handles = $viewer->loadHandles($object_phids);
|
||||
} else {
|
||||
$handles = array();
|
||||
}
|
||||
|
||||
$rows = array();
|
||||
foreach ($object_phids as $object_phid) {
|
||||
$handle = $handles[$object_phid];
|
||||
|
||||
$icon = $handle->getIcon();
|
||||
|
||||
$rows[] = array(
|
||||
id(new PHUIIconView())->setIcon($icon),
|
||||
$handle->getTypeName(),
|
||||
$handle->renderLink(),
|
||||
);
|
||||
}
|
||||
|
||||
$usage_table = id(new AphrontTableView($rows))
|
||||
->setNoDataString(
|
||||
pht(
|
||||
'This panel is not used on any dashboard or inside any other '.
|
||||
'panel container.'))
|
||||
->setColumnClasses(
|
||||
array(
|
||||
'center',
|
||||
'',
|
||||
'pri wide',
|
||||
));
|
||||
|
||||
$header_view = id(new PHUIHeaderView())
|
||||
->setHeader(pht('Panel Used By'));
|
||||
|
||||
$usage_box = id(new PHUIObjectBoxView())
|
||||
->setTable($usage_table)
|
||||
->setHeader($header_view);
|
||||
|
||||
return $usage_box;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,4 +21,8 @@ final class PhabricatorDashboardPanelTransactionEditor
|
|||
return $types;
|
||||
}
|
||||
|
||||
protected function supportsSearch() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -178,5 +178,8 @@ final class PhabricatorDashboardTransactionEditor
|
|||
return $errors;
|
||||
}
|
||||
|
||||
protected function supportsSearch() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorDashboardPanelContainerIndexEngineExtension
|
||||
extends PhabricatorEdgeIndexEngineExtension {
|
||||
|
||||
const EXTENSIONKEY = 'dashboard.panel.container';
|
||||
|
||||
public function getExtensionName() {
|
||||
return pht('Dashboard Panel Containers');
|
||||
}
|
||||
|
||||
public function shouldIndexObject($object) {
|
||||
if (!($object instanceof PhabricatorDashboardPanelContainerInterface)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function getIndexEdgeType() {
|
||||
return PhabricatorObjectUsesDashboardPanelEdgeType::EDGECONST;
|
||||
}
|
||||
|
||||
protected function getIndexDestinationPHIDs($object) {
|
||||
return $object->getDashboardPanelContainerPanelPHIDs();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
|
||||
interface PhabricatorDashboardPanelContainerInterface {
|
||||
|
||||
/**
|
||||
* Return a list of Dashboard Panel PHIDs used by this container.
|
||||
*
|
||||
* @return list<phid>
|
||||
*/
|
||||
public function getDashboardPanelContainerPanelPHIDs();
|
||||
|
||||
}
|
|
@ -59,4 +59,8 @@ abstract class PhabricatorDashboardPanelType extends Phobject {
|
|||
abstract protected function newEditEngineFields(
|
||||
PhabricatorDashboardPanel $panel);
|
||||
|
||||
public function getSubpanelPHIDs(PhabricatorDashboardPanel $panel) {
|
||||
return array();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -105,7 +105,7 @@ final class PhabricatorDashboardTabsPanelType
|
|||
|
||||
$tab_view = id(new PHUIListItemView())
|
||||
->setHref('#')
|
||||
->setSelected($idx == $selected)
|
||||
->setSelected((string)$idx === (string)$selected)
|
||||
->addSigil('dashboard-tab-panel-tab')
|
||||
->setMetadata(array('panelKey' => $idx))
|
||||
->setName($name);
|
||||
|
@ -292,4 +292,24 @@ final class PhabricatorDashboardTabsPanelType
|
|||
));
|
||||
}
|
||||
|
||||
public function getSubpanelPHIDs(PhabricatorDashboardPanel $panel) {
|
||||
$config = $this->getPanelConfiguration($panel);
|
||||
|
||||
$panel_ids = array();
|
||||
foreach ($config as $tab_key => $tab_spec) {
|
||||
$panel_ids[] = $tab_spec['panelID'];
|
||||
}
|
||||
|
||||
if ($panel_ids) {
|
||||
$panels = id(new PhabricatorDashboardPanelQuery())
|
||||
->setViewer(PhabricatorUser::getOmnipotentUser())
|
||||
->withIDs($panel_ids)
|
||||
->execute();
|
||||
} else {
|
||||
$panels = array();
|
||||
}
|
||||
|
||||
return mpull($panels, 'getPHID');
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -35,9 +35,11 @@ final class PhabricatorDashboardPanelPHIDType extends PhabricatorPHIDType {
|
|||
$name = $panel->getName();
|
||||
$monogram = $panel->getMonogram();
|
||||
|
||||
$handle->setName($panel->getMonogram());
|
||||
$handle->setFullName("{$monogram} {$name}");
|
||||
$handle->setURI("/{$monogram}");
|
||||
$handle
|
||||
->setIcon('fa-window-maximize')
|
||||
->setName($name)
|
||||
->setFullName("{$monogram} {$name}")
|
||||
->setURI($panel->getURI());
|
||||
|
||||
if ($panel->getIsArchived()) {
|
||||
$handle->setStatus(PhabricatorObjectHandle::STATUS_CLOSED);
|
||||
|
|
|
@ -62,35 +62,35 @@ final class PhabricatorDashboardPanelQuery
|
|||
if ($this->ids !== null) {
|
||||
$where[] = qsprintf(
|
||||
$conn,
|
||||
'id IN (%Ld)',
|
||||
'panel.id IN (%Ld)',
|
||||
$this->ids);
|
||||
}
|
||||
|
||||
if ($this->phids !== null) {
|
||||
$where[] = qsprintf(
|
||||
$conn,
|
||||
'phid IN (%Ls)',
|
||||
'panel.phid IN (%Ls)',
|
||||
$this->phids);
|
||||
}
|
||||
|
||||
if ($this->archived !== null) {
|
||||
$where[] = qsprintf(
|
||||
$conn,
|
||||
'isArchived = %d',
|
||||
'panel.isArchived = %d',
|
||||
(int)$this->archived);
|
||||
}
|
||||
|
||||
if ($this->panelTypes !== null) {
|
||||
$where[] = qsprintf(
|
||||
$conn,
|
||||
'panelType IN (%Ls)',
|
||||
'panel.panelType IN (%Ls)',
|
||||
$this->panelTypes);
|
||||
}
|
||||
|
||||
if ($this->authorPHIDs !== null) {
|
||||
$where[] = qsprintf(
|
||||
$conn,
|
||||
'authorPHID IN (%Ls)',
|
||||
'panel.authorPHID IN (%Ls)',
|
||||
$this->authorPHIDs);
|
||||
}
|
||||
|
||||
|
@ -102,7 +102,7 @@ final class PhabricatorDashboardPanelQuery
|
|||
}
|
||||
|
||||
protected function getPrimaryTableAlias() {
|
||||
return 'dashboard_panel';
|
||||
return 'panel';
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -10,7 +10,8 @@ final class PhabricatorDashboard extends PhabricatorDashboardDAO
|
|||
PhabricatorFlaggableInterface,
|
||||
PhabricatorDestructibleInterface,
|
||||
PhabricatorProjectInterface,
|
||||
PhabricatorNgramsInterface {
|
||||
PhabricatorNgramsInterface,
|
||||
PhabricatorDashboardPanelContainerInterface {
|
||||
|
||||
protected $name;
|
||||
protected $authorPHID;
|
||||
|
@ -191,4 +192,12 @@ final class PhabricatorDashboard extends PhabricatorDashboardDAO
|
|||
);
|
||||
}
|
||||
|
||||
/* -( PhabricatorDashboardPanelContainerInterface )------------------------ */
|
||||
|
||||
public function getDashboardPanelContainerPanelPHIDs() {
|
||||
return PhabricatorEdgeQuery::loadDestinationPHIDs(
|
||||
$this->getPHID(),
|
||||
PhabricatorDashboardDashboardHasPanelEdgeType::EDGECONST);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -10,7 +10,8 @@ final class PhabricatorDashboardPanel
|
|||
PhabricatorPolicyInterface,
|
||||
PhabricatorFlaggableInterface,
|
||||
PhabricatorDestructibleInterface,
|
||||
PhabricatorNgramsInterface {
|
||||
PhabricatorNgramsInterface,
|
||||
PhabricatorDashboardPanelContainerInterface {
|
||||
|
||||
protected $name;
|
||||
protected $panelType;
|
||||
|
@ -165,4 +166,10 @@ final class PhabricatorDashboardPanel
|
|||
);
|
||||
}
|
||||
|
||||
/* -( PhabricatorDashboardPanelContainerInterface )------------------------ */
|
||||
|
||||
public function getDashboardPanelContainerPanelPHIDs() {
|
||||
return $this->requireImplementation()->getSubpanelPHIDs($this);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorDashboardPanelUsedByObjectEdgeType
|
||||
extends PhabricatorEdgeType {
|
||||
|
||||
const EDGECONST = 72;
|
||||
|
||||
public function getInverseEdgeConstant() {
|
||||
return PhabricatorObjectUsesDashboardPanelEdgeType::EDGECONST;
|
||||
}
|
||||
|
||||
public function shouldWriteInverseTransactions() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorObjectUsesDashboardPanelEdgeType
|
||||
extends PhabricatorEdgeType {
|
||||
|
||||
const EDGECONST = 71;
|
||||
|
||||
public function getInverseEdgeConstant() {
|
||||
return PhabricatorDashboardPanelUsedByObjectEdgeType::EDGECONST;
|
||||
}
|
||||
|
||||
public function shouldWriteInverseTransactions() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
|
@ -160,6 +160,9 @@ th.aphront-table-view-sortable-selected {
|
|||
vertical-align: top;
|
||||
}
|
||||
|
||||
/* Apply this rule to both "<th />" and "<td />" so that the header widths
|
||||
are correct if the table has no rows. */
|
||||
.aphront-table-view th.wide,
|
||||
.aphront-table-view td.wide {
|
||||
white-space: normal;
|
||||
width: 100%;
|
||||
|
|
Loading…
Reference in a new issue