1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-30 02:32:42 +01:00

Fix the "Add Query to Dashboard..." flow from "Use Results" on search result pages

Summary:
Depends on D20413. Ref T13272. When you search for stuff, you can "Use Results > Add to Dashboard" to generate a query panel.

This needs some updating after the recent refactoring. All the changes are pretty straightforward. Swaps a giant `<select />` for a tokenizer with a datasource.

Test Plan: Used the "Use Results > Add to Dashboard" flow to create a panel on a dashboard using a query.

Reviewers: amckinley

Reviewed By: amckinley

Maniphest Tasks: T13272

Differential Revision: https://secure.phabricator.com/D20414
This commit is contained in:
epriestley 2019-04-12 16:46:00 -07:00
parent 4b8a67ccde
commit e99c1974b0
4 changed files with 137 additions and 130 deletions

View file

@ -7,186 +7,160 @@ final class PhabricatorDashboardQueryPanelInstallController
$viewer = $request->getViewer(); $viewer = $request->getViewer();
$v_dashboard = null; $v_dashboard = null;
$v_name = null; $e_dashboard = null;
$v_column = 0;
$v_engine = $request->getURIData('engineKey');
$v_query = $request->getURIData('queryKey');
$v_name = null;
$e_name = true; $e_name = true;
// Validate Engines $v_engine = $request->getStr('engine');
$engines = PhabricatorApplicationSearchEngine::getAllEngines(); if (!strlen($v_engine)) {
foreach ($engines as $name => $engine) { $v_engine = $request->getURIData('engineKey');
if (!$engine->canUseInPanelContext()) {
unset($engines[$name]);
}
}
if (!in_array($v_engine, array_keys($engines))) {
return new Aphront404Response();
} }
// Validate Queries $v_query = $request->getStr('query');
$engine = $engines[$v_engine]; if (!strlen($v_query)) {
$engine->setViewer($viewer); $v_query = $request->getURIData('queryKey');
$good_query = false;
if ($engine->isBuiltinQuery($v_query)) {
$good_query = true;
} else {
$saved_query = id(new PhabricatorSavedQueryQuery())
->setViewer($viewer)
->withEngineClassNames(array($v_engine))
->withQueryKeys(array($v_query))
->executeOne();
if ($saved_query) {
$good_query = true;
}
}
if (!$good_query) {
return new Aphront404Response();
} }
$engines = PhabricatorApplicationSearchEngine::getAllEngines();
$engine = idx($engines, $v_engine);
if ($engine) {
$engine = id(clone $engine)
->setViewer($viewer);
$redirect_uri = $engine->getQueryResultsPageURI($v_query);
$named_query = idx($engine->loadEnabledNamedQueries(), $v_query); $named_query = idx($engine->loadEnabledNamedQueries(), $v_query);
if ($named_query) { if ($named_query) {
$v_name = $named_query->getQueryName(); $v_name = $named_query->getQueryName();
} }
} else {
$redirect_uri = '/';
}
$errors = array(); $errors = array();
$xaction_name = PhabricatorDashboardPanelNameTransaction::TRANSACTIONTYPE;
$xaction_engine =
PhabricatorDashboardQueryPanelApplicationTransaction::TRANSACTIONTYPE;
$xaction_query =
PhabricatorDashboardQueryPanelQueryTransaction::TRANSACTIONTYPE;
if ($request->isFormPost()) { if ($request->isFormPost()) {
$v_dashboard = $request->getInt('dashboardID');
$v_name = $request->getStr('name'); $v_name = $request->getStr('name');
if (!$v_name) { if (!$v_name) {
$errors[] = pht('You must provide a name for this panel.'); $errors[] = pht('You must provide a name for this panel.');
$e_name = pht('Required'); $e_name = pht('Required');
} }
$v_dashboard = head($request->getArr('dashboardPHIDs'));
if (!$v_dashboard) {
$errors[] = pht('You must select a dashboard.');
$e_dashboard = pht('Required');
} else {
$dashboard = id(new PhabricatorDashboardQuery()) $dashboard = id(new PhabricatorDashboardQuery())
->setViewer($viewer) ->setViewer($viewer)
->withIDs(array($v_dashboard)) ->withPHIDs(array($v_dashboard))
->requireCapabilities(
array(
PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT,
))
->executeOne(); ->executeOne();
if (!$dashboard) { if (!$dashboard) {
$errors[] = pht('Please select a valid dashboard.'); $errors[] = pht('You must select a valid dashboard.');
$e_dashboard = pht('Invalid');
}
$can_edit = PhabricatorPolicyFilter::hasCapability(
$viewer,
$dashboard,
PhabricatorPolicyCapability::CAN_EDIT);
if (!$can_edit) {
$errors[] = pht(
'You must select a dashboard you have permission to edit.');
}
} }
if (!$errors) { if (!$errors) {
$redirect_uri = "/dashboard/view/{$v_dashboard}/"; $done_uri = $dashboard->getURI();
// First, create a new panel.
$panel_type = id(new PhabricatorDashboardQueryPanelType()) $panel_type = id(new PhabricatorDashboardQueryPanelType())
->getPanelTypeKey(); ->getPanelTypeKey();
$panel = PhabricatorDashboardPanel::initializeNewPanel($viewer);
$panel->setPanelType($panel_type);
$field_list = PhabricatorCustomField::getObjectFields( $panel = PhabricatorDashboardPanel::initializeNewPanel($viewer)
$panel, ->setPanelType($panel_type);
PhabricatorCustomField::ROLE_EDIT);
$field_list
->setViewer($viewer)
->readFieldsFromStorage($panel);
$panel->requireImplementation()->initializeFieldsFromRequest(
$panel,
$field_list,
$request);
$xactions = array(); $xactions = array();
$xactions[] = id(new PhabricatorDashboardPanelTransaction()) $xactions[] = $panel->getApplicationTransactionTemplate()
->setTransactionType( ->setTransactionType($xaction_engine)
PhabricatorDashboardPanelNameTransaction::TRANSACTIONTYPE)
->setNewValue($v_name);
$xactions[] = id(new PhabricatorDashboardPanelTransaction())
->setTransactionType(PhabricatorTransactions::TYPE_CUSTOMFIELD)
->setMetadataValue('customfield:key', 'std:dashboard:core:class')
->setOldValue(null)
->setNewValue($v_engine); ->setNewValue($v_engine);
$xactions[] = id(new PhabricatorDashboardPanelTransaction()) $xactions[] = $panel->getApplicationTransactionTemplate()
->setTransactionType(PhabricatorTransactions::TYPE_CUSTOMFIELD) ->setTransactionType($xaction_query)
->setMetadataValue('customfield:key', 'std:dashboard:core:key')
->setOldValue(null)
->setNewValue($v_query); ->setNewValue($v_query);
$editor = id(new PhabricatorDashboardPanelTransactionEditor()) $xactions[] = $panel->getApplicationTransactionTemplate()
->setTransactionType($xaction_name)
->setNewValue($v_name);
$editor = $panel->getApplicationTransactionEditor()
->setActor($viewer) ->setActor($viewer)
->setContinueOnNoEffect(true)
->setContentSourceFromRequest($request) ->setContentSourceFromRequest($request)
->applyTransactions($panel, $xactions); ->applyTransactions($panel, $xactions);
PhabricatorDashboardTransactionEditor::addPanelToDashboard( // Now that we've created a panel, add it to the dashboard.
$viewer,
PhabricatorContentSource::newFromRequest($request),
$panel,
$dashboard,
$request->getInt('column', 0));
return id(new AphrontRedirectResponse())->setURI($redirect_uri); $xactions = array();
$ref_list = clone $dashboard->getPanelRefList();
$ref_list->newPanelRef($panel);
$new_panels = $ref_list->toDictionary();
$xactions[] = $dashboard->getApplicationTransactionTemplate()
->setTransactionType(
PhabricatorDashboardPanelsTransaction::TRANSACTIONTYPE)
->setNewValue($new_panels);
$editor = $dashboard->getApplicationTransactionEditor()
->setActor($viewer)
->setContentSourceFromRequest($request)
->setContinueOnNoEffect(true)
->setContinueOnMissingFields(true)
->applyTransactions($dashboard, $xactions);
return id(new AphrontRedirectResponse())->setURI($done_uri);
} }
} }
// Make this a select for now, as we don't expect someone to have if ($v_dashboard) {
// edit access to a vast number of dashboards. $dashboard_phids = array($v_dashboard);
// Can add optiongroup if needed down the road. } else {
$dashboards = id(new PhabricatorDashboardQuery()) $dashboard_phids = array();
->setViewer($viewer)
->withStatuses(array(
PhabricatorDashboard::STATUS_ACTIVE,
))
->requireCapabilities(
array(
PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT,
))
->execute();
$options = mpull($dashboards, 'getName', 'getID');
asort($options);
$redirect_uri = $engine->getQueryResultsPageURI($v_query);
if (!$options) {
$notice = id(new PHUIInfoView())
->setSeverity(PHUIInfoView::SEVERITY_NOTICE)
->appendChild(pht('You do not have access to any dashboards. To '.
'continue, please create a dashboard first.'));
return $this->newDialog()
->setTitle(pht('No Dashboards'))
->setWidth(AphrontDialogView::WIDTH_FORM)
->appendChild($notice)
->addCancelButton($redirect_uri);
} }
$form = id(new AphrontFormView()) $form = id(new AphrontFormView())
->setUser($viewer) ->setViewer($viewer)
->addHiddenInput('engine', $v_engine) ->appendControl(
->addHiddenInput('query', $v_query)
->addHiddenInput('column', $v_column)
->appendChild(
id(new AphrontFormTextControl()) id(new AphrontFormTextControl())
->setLabel(pht('Name')) ->setLabel(pht('Name'))
->setName('name') ->setName('name')
->setValue($v_name) ->setValue($v_name)
->setError($e_name)) ->setError($e_name))
->appendChild( ->appendControl(
id(new AphrontFormSelectControl()) id(new AphrontFormTokenizerControl())
->setUser($this->getViewer()) ->setValue($dashboard_phids)
->setValue($v_dashboard) ->setError($e_dashboard)
->setName('dashboardID') ->setName('dashboardPHIDs')
->setOptions($options) ->setLimit(1)
->setDatasource(new PhabricatorDashboardDatasource())
->setLabel(pht('Dashboard'))); ->setLabel(pht('Dashboard')));
return $this->newDialog() return $this->newDialog()
->setTitle(pht('Add Panel to Dashboard')) ->setTitle(pht('Add Panel to Dashboard'))
->setErrors($errors) ->setErrors($errors)
->setWidth(AphrontDialogView::WIDTH_FORM) ->setWidth(AphrontDialogView::WIDTH_FORM)
->appendChild($form->buildLayoutView()) ->addHiddenInput('engine', $v_engine)
->addHiddenInput('query', $v_query)
->appendForm($form)
->addCancelButton($redirect_uri) ->addCancelButton($redirect_uri)
->addSubmitButton(pht('Add Panel')); ->addSubmitButton(pht('Add Panel'));

View file

@ -87,7 +87,14 @@ final class PhabricatorDashboardPanelRefList
return array_values(mpull($this->getPanelRefs(), 'toDictionary')); return array_values(mpull($this->getPanelRefs(), 'toDictionary'));
} }
public function newPanelRef(PhabricatorDashboardPanel $panel, $column_key) { public function newPanelRef(
PhabricatorDashboardPanel $panel,
$column_key = null) {
if ($column_key === null) {
$column_key = head_key($this->columns);
}
$ref = id(new PhabricatorDashboardPanelRef()) $ref = id(new PhabricatorDashboardPanelRef())
->setPanelKey($this->newPanelKey()) ->setPanelKey($this->newPanelKey())
->setPanelPHID($panel->getPHID()) ->setPanelPHID($panel->getPHID())

View file

@ -45,9 +45,8 @@ final class PhabricatorDashboardPanel
) + parent::getConfiguration(); ) + parent::getConfiguration();
} }
public function generatePHID() { public function getPHIDType() {
return PhabricatorPHID::generateNewPHID( return PhabricatorDashboardPanelPHIDType::TYPECONST;
PhabricatorDashboardPanelPHIDType::TYPECONST);
} }
public function getProperty($key, $default = null) { public function getProperty($key, $default = null) {

View file

@ -9,4 +9,31 @@ final class PhabricatorDashboardQueryPanelApplicationTransaction
return 'class'; return 'class';
} }
public function validateTransactions($object, array $xactions) {
$errors = array();
$engines = PhabricatorApplicationSearchEngine::getAllEngines();
$old_value = $object->getProperty($this->getPropertyKey());
foreach ($xactions as $xaction) {
$new_value = $xaction->getNewValue();
if ($new_value === $old_value) {
continue;
}
if (!isset($engines[$new_value])) {
$errors[] = $this->newInvalidError(
pht(
'Application search engine class "%s" is unknown. Query panels '.
'must use a known search engine class.',
$new_value),
$xaction);
continue;
}
}
return $errors;
}
} }