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:
parent
4b8a67ccde
commit
e99c1974b0
4 changed files with 137 additions and 130 deletions
|
@ -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'));
|
||||||
|
|
||||||
|
|
|
@ -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())
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue