mirror of
https://we.phorge.it/source/phorge.git
synced 2024-12-27 16:00:59 +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();
|
||||
|
||||
$v_dashboard = null;
|
||||
$v_name = null;
|
||||
$v_column = 0;
|
||||
$v_engine = $request->getURIData('engineKey');
|
||||
$v_query = $request->getURIData('queryKey');
|
||||
$e_dashboard = null;
|
||||
|
||||
$v_name = null;
|
||||
$e_name = true;
|
||||
|
||||
// Validate Engines
|
||||
$v_engine = $request->getStr('engine');
|
||||
if (!strlen($v_engine)) {
|
||||
$v_engine = $request->getURIData('engineKey');
|
||||
}
|
||||
|
||||
$v_query = $request->getStr('query');
|
||||
if (!strlen($v_query)) {
|
||||
$v_query = $request->getURIData('queryKey');
|
||||
}
|
||||
|
||||
$engines = PhabricatorApplicationSearchEngine::getAllEngines();
|
||||
foreach ($engines as $name => $engine) {
|
||||
if (!$engine->canUseInPanelContext()) {
|
||||
unset($engines[$name]);
|
||||
}
|
||||
}
|
||||
if (!in_array($v_engine, array_keys($engines))) {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
$engine = idx($engines, $v_engine);
|
||||
if ($engine) {
|
||||
$engine = id(clone $engine)
|
||||
->setViewer($viewer);
|
||||
|
||||
// Validate Queries
|
||||
$engine = $engines[$v_engine];
|
||||
$engine->setViewer($viewer);
|
||||
$good_query = false;
|
||||
if ($engine->isBuiltinQuery($v_query)) {
|
||||
$good_query = true;
|
||||
$redirect_uri = $engine->getQueryResultsPageURI($v_query);
|
||||
|
||||
$named_query = idx($engine->loadEnabledNamedQueries(), $v_query);
|
||||
if ($named_query) {
|
||||
$v_name = $named_query->getQueryName();
|
||||
}
|
||||
} 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();
|
||||
}
|
||||
|
||||
$named_query = idx($engine->loadEnabledNamedQueries(), $v_query);
|
||||
if ($named_query) {
|
||||
$v_name = $named_query->getQueryName();
|
||||
$redirect_uri = '/';
|
||||
}
|
||||
|
||||
$errors = array();
|
||||
|
||||
$xaction_name = PhabricatorDashboardPanelNameTransaction::TRANSACTIONTYPE;
|
||||
$xaction_engine =
|
||||
PhabricatorDashboardQueryPanelApplicationTransaction::TRANSACTIONTYPE;
|
||||
$xaction_query =
|
||||
PhabricatorDashboardQueryPanelQueryTransaction::TRANSACTIONTYPE;
|
||||
|
||||
if ($request->isFormPost()) {
|
||||
$v_dashboard = $request->getInt('dashboardID');
|
||||
$v_name = $request->getStr('name');
|
||||
if (!$v_name) {
|
||||
$errors[] = pht('You must provide a name for this panel.');
|
||||
$e_name = pht('Required');
|
||||
}
|
||||
|
||||
$dashboard = id(new PhabricatorDashboardQuery())
|
||||
->setViewer($viewer)
|
||||
->withIDs(array($v_dashboard))
|
||||
->requireCapabilities(
|
||||
array(
|
||||
PhabricatorPolicyCapability::CAN_VIEW,
|
||||
PhabricatorPolicyCapability::CAN_EDIT,
|
||||
))
|
||||
->executeOne();
|
||||
$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())
|
||||
->setViewer($viewer)
|
||||
->withPHIDs(array($v_dashboard))
|
||||
->executeOne();
|
||||
if (!$dashboard) {
|
||||
$errors[] = pht('You must select a valid dashboard.');
|
||||
$e_dashboard = pht('Invalid');
|
||||
}
|
||||
|
||||
if (!$dashboard) {
|
||||
$errors[] = pht('Please select a valid dashboard.');
|
||||
$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) {
|
||||
$redirect_uri = "/dashboard/view/{$v_dashboard}/";
|
||||
$done_uri = $dashboard->getURI();
|
||||
|
||||
// First, create a new panel.
|
||||
|
||||
$panel_type = id(new PhabricatorDashboardQueryPanelType())
|
||||
->getPanelTypeKey();
|
||||
$panel = PhabricatorDashboardPanel::initializeNewPanel($viewer);
|
||||
$panel->setPanelType($panel_type);
|
||||
|
||||
$field_list = PhabricatorCustomField::getObjectFields(
|
||||
$panel,
|
||||
PhabricatorCustomField::ROLE_EDIT);
|
||||
|
||||
$field_list
|
||||
->setViewer($viewer)
|
||||
->readFieldsFromStorage($panel);
|
||||
|
||||
$panel->requireImplementation()->initializeFieldsFromRequest(
|
||||
$panel,
|
||||
$field_list,
|
||||
$request);
|
||||
$panel = PhabricatorDashboardPanel::initializeNewPanel($viewer)
|
||||
->setPanelType($panel_type);
|
||||
|
||||
$xactions = array();
|
||||
|
||||
$xactions[] = id(new PhabricatorDashboardPanelTransaction())
|
||||
->setTransactionType(
|
||||
PhabricatorDashboardPanelNameTransaction::TRANSACTIONTYPE)
|
||||
->setNewValue($v_name);
|
||||
|
||||
$xactions[] = id(new PhabricatorDashboardPanelTransaction())
|
||||
->setTransactionType(PhabricatorTransactions::TYPE_CUSTOMFIELD)
|
||||
->setMetadataValue('customfield:key', 'std:dashboard:core:class')
|
||||
->setOldValue(null)
|
||||
$xactions[] = $panel->getApplicationTransactionTemplate()
|
||||
->setTransactionType($xaction_engine)
|
||||
->setNewValue($v_engine);
|
||||
|
||||
$xactions[] = id(new PhabricatorDashboardPanelTransaction())
|
||||
->setTransactionType(PhabricatorTransactions::TYPE_CUSTOMFIELD)
|
||||
->setMetadataValue('customfield:key', 'std:dashboard:core:key')
|
||||
->setOldValue(null)
|
||||
$xactions[] = $panel->getApplicationTransactionTemplate()
|
||||
->setTransactionType($xaction_query)
|
||||
->setNewValue($v_query);
|
||||
|
||||
$editor = id(new PhabricatorDashboardPanelTransactionEditor())
|
||||
$xactions[] = $panel->getApplicationTransactionTemplate()
|
||||
->setTransactionType($xaction_name)
|
||||
->setNewValue($v_name);
|
||||
|
||||
$editor = $panel->getApplicationTransactionEditor()
|
||||
->setActor($viewer)
|
||||
->setContinueOnNoEffect(true)
|
||||
->setContentSourceFromRequest($request)
|
||||
->applyTransactions($panel, $xactions);
|
||||
|
||||
PhabricatorDashboardTransactionEditor::addPanelToDashboard(
|
||||
$viewer,
|
||||
PhabricatorContentSource::newFromRequest($request),
|
||||
$panel,
|
||||
$dashboard,
|
||||
$request->getInt('column', 0));
|
||||
// Now that we've created a panel, add it to the dashboard.
|
||||
|
||||
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
|
||||
// edit access to a vast number of dashboards.
|
||||
// Can add optiongroup if needed down the road.
|
||||
$dashboards = id(new PhabricatorDashboardQuery())
|
||||
->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);
|
||||
if ($v_dashboard) {
|
||||
$dashboard_phids = array($v_dashboard);
|
||||
} else {
|
||||
$dashboard_phids = array();
|
||||
}
|
||||
|
||||
$form = id(new AphrontFormView())
|
||||
->setUser($viewer)
|
||||
->addHiddenInput('engine', $v_engine)
|
||||
->addHiddenInput('query', $v_query)
|
||||
->addHiddenInput('column', $v_column)
|
||||
->appendChild(
|
||||
->setViewer($viewer)
|
||||
->appendControl(
|
||||
id(new AphrontFormTextControl())
|
||||
->setLabel(pht('Name'))
|
||||
->setName('name')
|
||||
->setValue($v_name)
|
||||
->setError($e_name))
|
||||
->appendChild(
|
||||
id(new AphrontFormSelectControl())
|
||||
->setUser($this->getViewer())
|
||||
->setValue($v_dashboard)
|
||||
->setName('dashboardID')
|
||||
->setOptions($options)
|
||||
->appendControl(
|
||||
id(new AphrontFormTokenizerControl())
|
||||
->setValue($dashboard_phids)
|
||||
->setError($e_dashboard)
|
||||
->setName('dashboardPHIDs')
|
||||
->setLimit(1)
|
||||
->setDatasource(new PhabricatorDashboardDatasource())
|
||||
->setLabel(pht('Dashboard')));
|
||||
|
||||
return $this->newDialog()
|
||||
->setTitle(pht('Add Panel to Dashboard'))
|
||||
->setErrors($errors)
|
||||
->setWidth(AphrontDialogView::WIDTH_FORM)
|
||||
->appendChild($form->buildLayoutView())
|
||||
->addHiddenInput('engine', $v_engine)
|
||||
->addHiddenInput('query', $v_query)
|
||||
->appendForm($form)
|
||||
->addCancelButton($redirect_uri)
|
||||
->addSubmitButton(pht('Add Panel'));
|
||||
|
||||
|
|
|
@ -87,7 +87,14 @@ final class PhabricatorDashboardPanelRefList
|
|||
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())
|
||||
->setPanelKey($this->newPanelKey())
|
||||
->setPanelPHID($panel->getPHID())
|
||||
|
|
|
@ -45,9 +45,8 @@ final class PhabricatorDashboardPanel
|
|||
) + parent::getConfiguration();
|
||||
}
|
||||
|
||||
public function generatePHID() {
|
||||
return PhabricatorPHID::generateNewPHID(
|
||||
PhabricatorDashboardPanelPHIDType::TYPECONST);
|
||||
public function getPHIDType() {
|
||||
return PhabricatorDashboardPanelPHIDType::TYPECONST;
|
||||
}
|
||||
|
||||
public function getProperty($key, $default = null) {
|
||||
|
|
|
@ -9,4 +9,31 @@ final class PhabricatorDashboardQueryPanelApplicationTransaction
|
|||
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