1
0
Fork 0
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:
epriestley 2019-04-11 11:35:34 -07:00
parent d62f4dbfc9
commit 51f2ed498d
17 changed files with 200 additions and 15 deletions

View file

@ -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',

View file

@ -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',

View file

@ -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,

View file

@ -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;
}
}

View file

@ -21,4 +21,8 @@ final class PhabricatorDashboardPanelTransactionEditor
return $types;
}
protected function supportsSearch() {
return true;
}
}

View file

@ -178,5 +178,8 @@ final class PhabricatorDashboardTransactionEditor
return $errors;
}
protected function supportsSearch() {
return true;
}
}

View file

@ -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();
}
}

View file

@ -0,0 +1,12 @@
<?php
interface PhabricatorDashboardPanelContainerInterface {
/**
* Return a list of Dashboard Panel PHIDs used by this container.
*
* @return list<phid>
*/
public function getDashboardPanelContainerPanelPHIDs();
}

View file

@ -59,4 +59,8 @@ abstract class PhabricatorDashboardPanelType extends Phobject {
abstract protected function newEditEngineFields(
PhabricatorDashboardPanel $panel);
public function getSubpanelPHIDs(PhabricatorDashboardPanel $panel) {
return array();
}
}

View file

@ -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');
}
}

View file

@ -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);

View file

@ -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';
}
}

View file

@ -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);
}
}

View file

@ -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);
}
}

View file

@ -0,0 +1,16 @@
<?php
final class PhabricatorDashboardPanelUsedByObjectEdgeType
extends PhabricatorEdgeType {
const EDGECONST = 72;
public function getInverseEdgeConstant() {
return PhabricatorObjectUsesDashboardPanelEdgeType::EDGECONST;
}
public function shouldWriteInverseTransactions() {
return true;
}
}

View file

@ -0,0 +1,16 @@
<?php
final class PhabricatorObjectUsesDashboardPanelEdgeType
extends PhabricatorEdgeType {
const EDGECONST = 71;
public function getInverseEdgeConstant() {
return PhabricatorDashboardPanelUsedByObjectEdgeType::EDGECONST;
}
public function shouldWriteInverseTransactions() {
return true;
}
}

View file

@ -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%;