1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2025-01-10 23:01:04 +01:00

Use EditEngine, not CustomFields, to define Dashboard Panel edit behavior

Summary:
Depends on D20371. Ref T13272. Dashboard panels use CustomField to specify editable panel behavior. This is an older approach which was largely or entirely obsoleted by EditEngine.

Throw away all the CustomField edit stuff. Convert the "text" panel to EditEngine to prove this at least mostly works.

This breaks "query" panels and "tab" panels (they'll still work fine, but they can't be meaningfully edited). I'll restore those in a future change.

Test Plan: Created and edited a "text" panel.

Reviewers: amckinley

Reviewed By: amckinley

Maniphest Tasks: T13272

Differential Revision: https://secure.phabricator.com/D20372
This commit is contained in:
epriestley 2019-04-02 11:15:04 -07:00
parent 68d969094f
commit b1e2d3cd29
14 changed files with 67 additions and 356 deletions

View file

@ -2927,8 +2927,6 @@ phutil_register_library_map(array(
'PhabricatorDashboardObjectInstallWorkflow' => 'applications/dashboard/install/PhabricatorDashboardObjectInstallWorkflow.php',
'PhabricatorDashboardPanel' => 'applications/dashboard/storage/PhabricatorDashboardPanel.php',
'PhabricatorDashboardPanelArchiveController' => 'applications/dashboard/controller/panel/PhabricatorDashboardPanelArchiveController.php',
'PhabricatorDashboardPanelCoreCustomField' => 'applications/dashboard/customfield/PhabricatorDashboardPanelCoreCustomField.php',
'PhabricatorDashboardPanelCustomField' => 'applications/dashboard/customfield/PhabricatorDashboardPanelCustomField.php',
'PhabricatorDashboardPanelDatasource' => 'applications/dashboard/typeahead/PhabricatorDashboardPanelDatasource.php',
'PhabricatorDashboardPanelEditConduitAPIMethod' => 'applications/dashboard/conduit/PhabricatorDashboardPanelEditConduitAPIMethod.php',
'PhabricatorDashboardPanelEditController' => 'applications/dashboard/controller/panel/PhabricatorDashboardPanelEditController.php',
@ -2938,14 +2936,12 @@ phutil_register_library_map(array(
'PhabricatorDashboardPanelNameTransaction' => 'applications/dashboard/xaction/panel/PhabricatorDashboardPanelNameTransaction.php',
'PhabricatorDashboardPanelNgrams' => 'applications/dashboard/storage/PhabricatorDashboardPanelNgrams.php',
'PhabricatorDashboardPanelPHIDType' => 'applications/dashboard/phid/PhabricatorDashboardPanelPHIDType.php',
'PhabricatorDashboardPanelPropertyTransaction' => 'applications/dashboard/xaction/panel/PhabricatorDashboardPanelPropertyTransaction.php',
'PhabricatorDashboardPanelQuery' => 'applications/dashboard/query/PhabricatorDashboardPanelQuery.php',
'PhabricatorDashboardPanelRenderController' => 'applications/dashboard/controller/panel/PhabricatorDashboardPanelRenderController.php',
'PhabricatorDashboardPanelRenderingEngine' => 'applications/dashboard/engine/PhabricatorDashboardPanelRenderingEngine.php',
'PhabricatorDashboardPanelSearchApplicationCustomField' => 'applications/dashboard/customfield/PhabricatorDashboardPanelSearchApplicationCustomField.php',
'PhabricatorDashboardPanelSearchEngine' => 'applications/dashboard/query/PhabricatorDashboardPanelSearchEngine.php',
'PhabricatorDashboardPanelSearchQueryCustomField' => 'applications/dashboard/customfield/PhabricatorDashboardPanelSearchQueryCustomField.php',
'PhabricatorDashboardPanelStatusTransaction' => 'applications/dashboard/xaction/panel/PhabricatorDashboardPanelStatusTransaction.php',
'PhabricatorDashboardPanelTabsCustomField' => 'applications/dashboard/customfield/PhabricatorDashboardPanelTabsCustomField.php',
'PhabricatorDashboardPanelTransaction' => 'applications/dashboard/storage/PhabricatorDashboardPanelTransaction.php',
'PhabricatorDashboardPanelTransactionEditor' => 'applications/dashboard/editor/PhabricatorDashboardPanelTransactionEditor.php',
'PhabricatorDashboardPanelTransactionQuery' => 'applications/dashboard/query/PhabricatorDashboardPanelTransactionQuery.php',
@ -2985,6 +2981,7 @@ phutil_register_library_map(array(
'PhabricatorDashboardSchemaSpec' => 'applications/dashboard/storage/PhabricatorDashboardSchemaSpec.php',
'PhabricatorDashboardSearchEngine' => 'applications/dashboard/query/PhabricatorDashboardSearchEngine.php',
'PhabricatorDashboardTabsPanelType' => 'applications/dashboard/paneltype/PhabricatorDashboardTabsPanelType.php',
'PhabricatorDashboardTextPanelTextTransaction' => 'applications/dashboard/xaction/panel/PhabricatorDashboardTextPanelTextTransaction.php',
'PhabricatorDashboardTextPanelType' => 'applications/dashboard/paneltype/PhabricatorDashboardTextPanelType.php',
'PhabricatorDashboardTransaction' => 'applications/dashboard/storage/PhabricatorDashboardTransaction.php',
'PhabricatorDashboardTransactionEditor' => 'applications/dashboard/editor/PhabricatorDashboardTransactionEditor.php',
@ -8899,17 +8896,11 @@ phutil_register_library_map(array(
'PhabricatorDashboardDAO',
'PhabricatorApplicationTransactionInterface',
'PhabricatorPolicyInterface',
'PhabricatorCustomFieldInterface',
'PhabricatorFlaggableInterface',
'PhabricatorDestructibleInterface',
'PhabricatorNgramsInterface',
),
'PhabricatorDashboardPanelArchiveController' => 'PhabricatorDashboardController',
'PhabricatorDashboardPanelCoreCustomField' => array(
'PhabricatorDashboardPanelCustomField',
'PhabricatorStandardCustomFieldInterface',
),
'PhabricatorDashboardPanelCustomField' => 'PhabricatorCustomField',
'PhabricatorDashboardPanelDatasource' => 'PhabricatorTypeaheadDatasource',
'PhabricatorDashboardPanelEditConduitAPIMethod' => 'PhabricatorEditEngineAPIMethod',
'PhabricatorDashboardPanelEditController' => 'PhabricatorDashboardController',
@ -8919,14 +8910,12 @@ phutil_register_library_map(array(
'PhabricatorDashboardPanelNameTransaction' => 'PhabricatorDashboardPanelTransactionType',
'PhabricatorDashboardPanelNgrams' => 'PhabricatorSearchNgrams',
'PhabricatorDashboardPanelPHIDType' => 'PhabricatorPHIDType',
'PhabricatorDashboardPanelPropertyTransaction' => 'PhabricatorDashboardPanelTransactionType',
'PhabricatorDashboardPanelQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhabricatorDashboardPanelRenderController' => 'PhabricatorDashboardController',
'PhabricatorDashboardPanelRenderingEngine' => 'Phobject',
'PhabricatorDashboardPanelSearchApplicationCustomField' => 'PhabricatorStandardCustomField',
'PhabricatorDashboardPanelSearchEngine' => 'PhabricatorApplicationSearchEngine',
'PhabricatorDashboardPanelSearchQueryCustomField' => 'PhabricatorStandardCustomField',
'PhabricatorDashboardPanelStatusTransaction' => 'PhabricatorDashboardPanelTransactionType',
'PhabricatorDashboardPanelTabsCustomField' => 'PhabricatorStandardCustomField',
'PhabricatorDashboardPanelTransaction' => 'PhabricatorModularTransaction',
'PhabricatorDashboardPanelTransactionEditor' => 'PhabricatorApplicationTransactionEditor',
'PhabricatorDashboardPanelTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
@ -8971,6 +8960,7 @@ phutil_register_library_map(array(
'PhabricatorDashboardSchemaSpec' => 'PhabricatorConfigSchemaSpec',
'PhabricatorDashboardSearchEngine' => 'PhabricatorApplicationSearchEngine',
'PhabricatorDashboardTabsPanelType' => 'PhabricatorDashboardPanelType',
'PhabricatorDashboardTextPanelTextTransaction' => 'PhabricatorDashboardPanelPropertyTransaction',
'PhabricatorDashboardTextPanelType' => 'PhabricatorDashboardPanelType',
'PhabricatorDashboardTransaction' => 'PhabricatorApplicationTransaction',
'PhabricatorDashboardTransactionEditor' => 'PhabricatorApplicationTransactionEditor',

View file

@ -1,47 +0,0 @@
<?php
final class PhabricatorDashboardPanelCoreCustomField
extends PhabricatorDashboardPanelCustomField
implements PhabricatorStandardCustomFieldInterface {
public function getStandardCustomFieldNamespace() {
return 'dashboard:core';
}
public function createFields($object) {
if (!$object->getPanelType()) {
return array();
}
$impl = $object->requireImplementation();
$specs = $impl->getFieldSpecifications();
return PhabricatorStandardCustomField::buildStandardFields($this, $specs);
}
public function shouldUseStorage() {
return false;
}
public function readValueFromObject(PhabricatorCustomFieldInterface $object) {
$key = $this->getProxy()->getRawStandardFieldKey();
$this->setValueFromStorage($object->getProperty($key));
$this->didSetValueFromStorage();
}
public function applyApplicationTransactionInternalEffects(
PhabricatorApplicationTransaction $xaction) {
$object = $this->getObject();
$key = $this->getProxy()->getRawStandardFieldKey();
$this->setValueFromApplicationTransactions($xaction->getNewValue());
$value = $this->getValueForStorage();
$object->setProperty($key, $value);
}
public function applyApplicationTransactionExternalEffects(
PhabricatorApplicationTransaction $xaction) {
return;
}
}

View file

@ -1,4 +0,0 @@
<?php
abstract class PhabricatorDashboardPanelCustomField
extends PhabricatorCustomField {}

View file

@ -1,53 +0,0 @@
<?php
final class PhabricatorDashboardPanelSearchApplicationCustomField
extends PhabricatorStandardCustomField {
public function getFieldType() {
return 'search.application';
}
public function shouldAppearInApplicationSearch() {
return false;
}
public function renderEditControl(array $handles) {
$engines = id(new PhutilClassMapQuery())
->setAncestorClass('PhabricatorApplicationSearchEngine')
->setFilterMethod('canUseInPanelContext')
->execute();
$all_apps = id(new PhabricatorApplicationQuery())
->setViewer($this->getViewer())
->withUnlisted(false)
->withInstalled(true)
->execute();
foreach ($engines as $index => $engine) {
if (!isset($all_apps[$engine->getApplicationClassName()])) {
unset($engines[$index]);
continue;
}
}
$options = array();
$value = $this->getFieldValue();
if (strlen($value) && empty($engines[$value])) {
$options[$value] = $value;
}
$engines = msort($engines, 'getResultTypeDescription');
foreach ($engines as $class_name => $engine) {
$options[$class_name] = $engine->getResultTypeDescription();
}
return id(new AphrontFormSelectControl())
->setID($this->getFieldControlID())
->setLabel($this->getFieldName())
->setCaption($this->getCaption())
->setName($this->getFieldKey())
->setValue($this->getFieldValue())
->setOptions($options);
}
}

View file

@ -1,68 +0,0 @@
<?php
final class PhabricatorDashboardPanelSearchQueryCustomField
extends PhabricatorStandardCustomField {
public function getFieldType() {
return 'search.query';
}
public function shouldAppearInApplicationSearch() {
return false;
}
public function renderEditControl(array $handles) {
$engines = id(new PhutilClassMapQuery())
->setAncestorClass('PhabricatorApplicationSearchEngine')
->setFilterMethod('canUseInPanelContext')
->execute();
$value = $this->getFieldValue();
$queries = array();
$seen = false;
foreach ($engines as $engine_class => $engine) {
$engine->setViewer($this->getViewer());
$engine_queries = $engine->loadEnabledNamedQueries();
$query_map = mpull($engine_queries, 'getQueryName', 'getQueryKey');
asort($query_map);
foreach ($query_map as $key => $name) {
$queries[$engine_class][] = array('key' => $key, 'name' => $name);
if ($key == $value) {
$seen = true;
}
}
}
if (strlen($value) && !$seen) {
$name = pht('Custom Query ("%s")', $value);
} else {
$name = pht('(None)');
}
$options = array($value => $name);
$app_control_key = $this->getFieldConfigValue('control.application');
Javelin::initBehavior(
'dashboard-query-panel-select',
array(
'applicationID' => $this->getFieldControlID($app_control_key),
'queryID' => $this->getFieldControlID(),
'options' => $queries,
'value' => array(
'key' => strlen($value) ? $value : null,
'name' => $name,
),
));
return id(new AphrontFormSelectControl())
->setID($this->getFieldControlID())
->setLabel($this->getFieldName())
->setCaption($this->getCaption())
->setName($this->getFieldKey())
->setValue($this->getFieldValue())
->setOptions($options);
}
}

View file

@ -1,114 +0,0 @@
<?php
final class PhabricatorDashboardPanelTabsCustomField
extends PhabricatorStandardCustomField {
public function getFieldType() {
return 'dashboard.tabs';
}
public function shouldAppearInApplicationSearch() {
return false;
}
public function readValueFromRequest(AphrontRequest $request) {
$value = array();
$names = $request->getArr($this->getFieldKey().'_name');
$panel_ids = $request->getArr($this->getFieldKey().'_panelID');
$panels = array();
foreach ($panel_ids as $panel_id) {
$panels[] = $panel_id[0];
}
foreach ($names as $idx => $name) {
$panel_id = idx($panels, $idx);
if (strlen($name) && $panel_id) {
$value[] = array(
'name' => $name,
'panelID' => $panel_id,
);
}
}
$this->setFieldValue($value);
}
public function getApplicationTransactionTitle(
PhabricatorApplicationTransaction $xaction) {
$author_phid = $xaction->getAuthorPHID();
$old = $xaction->getOldValue();
$new = $xaction->getNewValue();
$new_tabs = array();
if ($new) {
foreach ($new as $new_tab) {
$new_tabs[] = $new_tab['name'];
}
$new_tabs = implode(' | ', $new_tabs);
}
$old_tabs = array();
if ($old) {
foreach ($old as $old_tab) {
$old_tabs[] = $old_tab['name'];
}
$old_tabs = implode(' | ', $old_tabs);
}
if (!$old) {
// In case someone makes a tab panel with no tabs.
if ($new) {
return pht(
'%s set the tabs to "%s".',
$xaction->renderHandleLink($author_phid),
$new_tabs);
}
} else if (!$new) {
return pht(
'%s removed tabs.',
$xaction->renderHandleLink($author_phid));
} else {
return pht(
'%s changed the tabs from "%s" to "%s".',
$xaction->renderHandleLink($author_phid),
$old_tabs,
$new_tabs);
}
}
public function renderEditControl(array $handles) {
// NOTE: This includes archived panels so we don't mutate the tabs
// when saving a tab panel that includes archived panels. This whole UI is
// hopefully temporary anyway.
$value = $this->getFieldValue();
if (!is_array($value)) {
$value = array();
}
$out = array();
for ($ii = 1; $ii <= 6; $ii++) {
$tab = idx($value, ($ii - 1), array());
$panel = idx($tab, 'panelID', null);
$panel_id = array();
if ($panel) {
$panel_id[] = $panel;
}
$out[] = id(new AphrontFormTextControl())
->setName($this->getFieldKey().'_name[]')
->setValue(idx($tab, 'name'))
->setLabel(pht('Tab %d Name', $ii));
$out[] = id(new AphrontFormTokenizerControl())
->setUser($this->getViewer())
->setDatasource(new PhabricatorDashboardPanelDatasource())
->setName($this->getFieldKey().'_panelID[]')
->setValue($panel_id)
->setLimit(1)
->setLabel(pht('Tab %d Panel', $ii));
}
return $out;
}
}

View file

@ -98,7 +98,7 @@ final class PhabricatorDashboardPanelEditEngine
return $dashboard->getURI();
}
return parent::getEffectiveObjectDoneURI($object);
return parent::getEffectiveObjectEditDoneURI($object);
}
protected function getObjectEditTitleText($object) {
@ -138,7 +138,7 @@ final class PhabricatorDashboardPanelEditEngine
}
protected function buildCustomEditFields($object) {
return array(
$fields = array(
id(new PhabricatorTextEditField())
->setKey('name')
->setLabel(pht('Name'))
@ -150,6 +150,13 @@ final class PhabricatorDashboardPanelEditEngine
->setIsRequired(true)
->setValue($object->getName()),
);
$panel_fields = $object->getEditEngineFields();
foreach ($panel_fields as $panel_field) {
$fields[] = $panel_field;
}
return $fields;
}
}

View file

@ -5,7 +5,6 @@ abstract class PhabricatorDashboardPanelType extends Phobject {
abstract public function getPanelTypeKey();
abstract public function getPanelTypeName();
abstract public function getPanelTypeDescription();
abstract public function getFieldSpecifications();
abstract public function getIcon();
abstract public function renderPanelContent(
@ -53,4 +52,11 @@ abstract class PhabricatorDashboardPanelType extends Phobject {
->execute();
}
final public function getEditEngineFields(PhabricatorDashboardPanel $panel) {
return $this->newEditEngineFields($panel);
}
abstract protected function newEditEngineFields(
PhabricatorDashboardPanel $panel);
}

View file

@ -21,23 +21,9 @@ final class PhabricatorDashboardQueryPanelType
'revisions you need to review.');
}
public function getFieldSpecifications() {
return array(
'class' => array(
'name' => pht('Search For'),
'type' => 'search.application',
),
'key' => array(
'name' => pht('Query'),
'type' => 'search.query',
'control.application' => 'class',
),
'limit' => array(
'name' => pht('Limit'),
'caption' => pht('Leave this blank for the default number of items.'),
'type' => 'text',
),
);
protected function newEditEngineFields(PhabricatorDashboardPanel $panel) {
// TODO: Restore this using EditEngine instead of CustomField.
return array();
}
public function initializeFieldsFromRequest(

View file

@ -19,13 +19,9 @@ final class PhabricatorDashboardTabsPanelType
return pht('Use tabs to switch between several other panels.');
}
public function getFieldSpecifications() {
return array(
'config' => array(
'name' => pht('Tabs'),
'type' => 'dashboard.tabs',
),
);
protected function newEditEngineFields(PhabricatorDashboardPanel $panel) {
// TODO: Restore this using EditEngine instead of CustomField.
return array();
}
public function shouldRenderAsync() {

View file

@ -21,12 +21,14 @@ final class PhabricatorDashboardTextPanelType
'context.');
}
public function getFieldSpecifications() {
protected function newEditEngineFields(PhabricatorDashboardPanel $panel) {
return array(
'text' => array(
'name' => pht('Text'),
'type' => 'remarkup',
),
id(new PhabricatorRemarkupEditField())
->setKey('text')
->setLabel(pht('Text'))
->setTransactionType(
PhabricatorDashboardTextPanelTextTransaction::TRANSACTIONTYPE)
->setValue($panel->getProperty('text', '')),
);
}

View file

@ -8,7 +8,6 @@ final class PhabricatorDashboardPanel
implements
PhabricatorApplicationTransactionInterface,
PhabricatorPolicyInterface,
PhabricatorCustomFieldInterface,
PhabricatorFlaggableInterface,
PhabricatorDestructibleInterface,
PhabricatorNgramsInterface {
@ -21,8 +20,6 @@ final class PhabricatorDashboardPanel
protected $isArchived = 0;
protected $properties = array();
private $customFields = self::ATTACHABLE;
public static function initializeNewPanel(PhabricatorUser $actor) {
return id(new PhabricatorDashboardPanel())
->setName('')
@ -105,6 +102,10 @@ final class PhabricatorDashboardPanel
return $impl;
}
public function getEditEngineFields() {
return $this->requireImplementation()->getEditEngineFields($this);
}
/* -( PhabricatorApplicationTransactionInterface )------------------------- */
@ -142,27 +143,6 @@ final class PhabricatorDashboardPanel
}
/* -( PhabricatorCustomFieldInterface )------------------------------------ */
public function getCustomFieldSpecificationForRole($role) {
return array();
}
public function getCustomFieldBaseClass() {
return 'PhabricatorDashboardPanelCustomField';
}
public function getCustomFields() {
return $this->assertAttached($this->customFields);
}
public function attachCustomFields(PhabricatorCustomFieldAttachment $fields) {
$this->customFields = $fields;
return $this;
}
/* -( PhabricatorDestructibleInterface )----------------------------------- */

View file

@ -0,0 +1,18 @@
<?php
abstract class PhabricatorDashboardPanelPropertyTransaction
extends PhabricatorDashboardPanelTransactionType {
abstract protected function getPropertyKey();
public function generateOldValue($object) {
$property_key = $this->getPropertyKey();
return $object->getProperty($property_key);
}
public function applyInternalEffects($object, $value) {
$property_key = $this->getPropertyKey();
$object->setProperty($property_key, $value);
}
}

View file

@ -0,0 +1,12 @@
<?php
final class PhabricatorDashboardTextPanelTextTransaction
extends PhabricatorDashboardPanelPropertyTransaction {
const TRANSACTIONTYPE = 'text.text';
protected function getPropertyKey() {
return 'text';
}
}