Page MenuHomePhabricator

D9572.diff
No OneTemporary

D9572.diff

diff --git a/resources/celerity/map.php b/resources/celerity/map.php
--- a/resources/celerity/map.php
+++ b/resources/celerity/map.php
@@ -354,6 +354,7 @@
'rsrc/js/application/countdown/timer.js' => '361e3ed3',
'rsrc/js/application/dashboard/behavior-dashboard-async-panel.js' => '469c0d9e',
'rsrc/js/application/dashboard/behavior-dashboard-move-panels.js' => 'fa187a68',
+ 'rsrc/js/application/dashboard/behavior-dashboard-query-panel-select.js' => '3be3eef5',
'rsrc/js/application/dashboard/behavior-dashboard-tab-panel.js' => 'aa077691',
'rsrc/js/application/differential/ChangesetViewManager.js' => 'db09a523',
'rsrc/js/application/differential/DifferentialInlineCommentEditor.js' => 'f2441746',
@@ -555,6 +556,7 @@
'javelin-behavior-dark-console' => 'e9fdb5e5',
'javelin-behavior-dashboard-async-panel' => '469c0d9e',
'javelin-behavior-dashboard-move-panels' => 'fa187a68',
+ 'javelin-behavior-dashboard-query-panel-select' => '3be3eef5',
'javelin-behavior-dashboard-tab-panel' => 'aa077691',
'javelin-behavior-device' => '03d6ed07',
'javelin-behavior-differential-add-reviewers-and-ccs' => '533a187b',
@@ -1113,6 +1115,11 @@
1 => 'javelin-dom',
2 => 'phortune-credit-card-form',
),
+ '3be3eef5' =>
+ array(
+ 0 => 'javelin-behavior',
+ 1 => 'javelin-dom',
+ ),
'40b1ff90' =>
array(
0 => 'javelin-behavior',
diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -1497,6 +1497,7 @@
'PhabricatorDashboardPanelRenderingEngine' => 'applications/dashboard/engine/PhabricatorDashboardPanelRenderingEngine.php',
'PhabricatorDashboardPanelSearchApplicationCustomField' => 'applications/dashboard/customfield/PhabricatorDashboardPanelSearchApplicationCustomField.php',
'PhabricatorDashboardPanelSearchEngine' => 'applications/dashboard/query/PhabricatorDashboardPanelSearchEngine.php',
+ 'PhabricatorDashboardPanelSearchQueryCustomField' => 'applications/dashboard/customfield/PhabricatorDashboardPanelSearchQueryCustomField.php',
'PhabricatorDashboardPanelTransaction' => 'applications/dashboard/storage/PhabricatorDashboardPanelTransaction.php',
'PhabricatorDashboardPanelTransactionEditor' => 'applications/dashboard/editor/PhabricatorDashboardPanelTransactionEditor.php',
'PhabricatorDashboardPanelTransactionQuery' => 'applications/dashboard/query/PhabricatorDashboardPanelTransactionQuery.php',
@@ -4317,6 +4318,7 @@
'PhabricatorDashboardPanelRenderingEngine' => 'Phobject',
'PhabricatorDashboardPanelSearchApplicationCustomField' => 'PhabricatorStandardCustomField',
'PhabricatorDashboardPanelSearchEngine' => 'PhabricatorApplicationSearchEngine',
+ 'PhabricatorDashboardPanelSearchQueryCustomField' => 'PhabricatorStandardCustomField',
'PhabricatorDashboardPanelTransaction' => 'PhabricatorApplicationTransaction',
'PhabricatorDashboardPanelTransactionEditor' => 'PhabricatorApplicationTransactionEditor',
'PhabricatorDashboardPanelTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
diff --git a/src/applications/dashboard/controller/PhabricatorDashboardPanelEditController.php b/src/applications/dashboard/controller/PhabricatorDashboardPanelEditController.php
--- a/src/applications/dashboard/controller/PhabricatorDashboardPanelEditController.php
+++ b/src/applications/dashboard/controller/PhabricatorDashboardPanelEditController.php
@@ -120,6 +120,13 @@
->setViewer($viewer)
->readFieldsFromStorage($panel);
+ if ($is_create && !$request->isFormPost()) {
+ $panel->requireImplementation()->initializeFieldsFromRequest(
+ $panel,
+ $field_list,
+ $request);
+ }
+
$validation_exception = null;
// NOTE: We require 'edit' to distinguish between the "Choose a Type"
diff --git a/src/applications/dashboard/customfield/PhabricatorDashboardPanelSearchApplicationCustomField.php b/src/applications/dashboard/customfield/PhabricatorDashboardPanelSearchApplicationCustomField.php
--- a/src/applications/dashboard/customfield/PhabricatorDashboardPanelSearchApplicationCustomField.php
+++ b/src/applications/dashboard/customfield/PhabricatorDashboardPanelSearchApplicationCustomField.php
@@ -30,6 +30,7 @@
}
return id(new AphrontFormSelectControl())
+ ->setID($this->getFieldControlID())
->setLabel($this->getFieldName())
->setCaption($this->getCaption())
->setName($this->getFieldKey())
diff --git a/src/applications/dashboard/customfield/PhabricatorDashboardPanelSearchQueryCustomField.php b/src/applications/dashboard/customfield/PhabricatorDashboardPanelSearchQueryCustomField.php
new file mode 100644
--- /dev/null
+++ b/src/applications/dashboard/customfield/PhabricatorDashboardPanelSearchQueryCustomField.php
@@ -0,0 +1,67 @@
+<?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 PhutilSymbolLoader())
+ ->setAncestorClass('PhabricatorApplicationSearchEngine')
+ ->loadObjects();
+
+ $value = $this->getFieldValue();
+
+ $queries = array();
+ 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);
+ }
+
+}
diff --git a/src/applications/dashboard/paneltype/PhabricatorDashboardPanelType.php b/src/applications/dashboard/paneltype/PhabricatorDashboardPanelType.php
--- a/src/applications/dashboard/paneltype/PhabricatorDashboardPanelType.php
+++ b/src/applications/dashboard/paneltype/PhabricatorDashboardPanelType.php
@@ -12,6 +12,13 @@
PhabricatorDashboardPanel $panel,
PhabricatorDashboardPanelRenderingEngine $engine);
+ public function initializeFieldsFromRequest(
+ PhabricatorDashboardPanel $panel,
+ PhabricatorCustomFieldList $field_list,
+ AphrontRequest $request) {
+ return;
+ }
+
/**
* Should this panel pull content in over AJAX?
*
diff --git a/src/applications/dashboard/paneltype/PhabricatorDashboardPanelTypeQuery.php b/src/applications/dashboard/paneltype/PhabricatorDashboardPanelTypeQuery.php
--- a/src/applications/dashboard/paneltype/PhabricatorDashboardPanelTypeQuery.php
+++ b/src/applications/dashboard/paneltype/PhabricatorDashboardPanelTypeQuery.php
@@ -25,16 +25,45 @@
),
'key' => array(
'name' => pht('Query'),
- 'type' => 'text',
+ 'type' => 'search.query',
+ 'control.application' => 'class',
),
'limit' => array(
- 'name' => pht('Maximum Number of Items'),
- 'caption' => pht('Leave this blank for the default number of items'),
+ 'name' => pht('Limit'),
+ 'caption' => pht('Leave this blank for the default number of items.'),
'type' => 'text',
),
);
}
+ public function initializeFieldsFromRequest(
+ PhabricatorDashboardPanel $panel,
+ PhabricatorCustomFieldList $field_list,
+ AphrontRequest $request) {
+
+ $map = array();
+ if (strlen($request->getStr('engine'))) {
+ $map['class'] = $request->getStr('engine');
+ }
+
+ if (strlen($request->getStr('query'))) {
+ $map['key'] = $request->getStr('query');
+ }
+
+ $full_map = array();
+ foreach ($map as $key => $value) {
+ $full_map["std:dashboard:core:{$key}"] = $value;
+ }
+
+ foreach ($field_list->getFields() as $field) {
+ $field_key = $field->getFieldKey();
+ if (isset($full_map[$field_key])) {
+ $field->setValueFromStorage($full_map[$field_key]);
+ }
+ }
+ }
+
+
public function renderPanelContent(
PhabricatorUser $viewer,
PhabricatorDashboardPanel $panel,
diff --git a/src/applications/search/controller/PhabricatorApplicationSearchController.php b/src/applications/search/controller/PhabricatorApplicationSearchController.php
--- a/src/applications/search/controller/PhabricatorApplicationSearchController.php
+++ b/src/applications/search/controller/PhabricatorApplicationSearchController.php
@@ -174,6 +174,9 @@
pht('Save Custom Query...'));
}
+ // TODO: A "Create Dashboard Panel" action goes here somewhere once
+ // we sort out T5307.
+
$form->appendChild($submit);
$filter_view = id(new AphrontListFilterView())->appendChild($form);
diff --git a/src/infrastructure/customfield/standard/PhabricatorStandardCustomField.php b/src/infrastructure/customfield/standard/PhabricatorStandardCustomField.php
--- a/src/infrastructure/customfield/standard/PhabricatorStandardCustomField.php
+++ b/src/infrastructure/customfield/standard/PhabricatorStandardCustomField.php
@@ -391,4 +391,9 @@
return $this->getFieldValue();
}
+ public function getFieldControlID($key = null) {
+ $key = coalesce($key, $this->getRawStandardFieldKey());
+ return 'std:control:'.$key;
+ }
+
}
diff --git a/webroot/rsrc/js/application/dashboard/behavior-dashboard-query-panel-select.js b/webroot/rsrc/js/application/dashboard/behavior-dashboard-query-panel-select.js
new file mode 100644
--- /dev/null
+++ b/webroot/rsrc/js/application/dashboard/behavior-dashboard-query-panel-select.js
@@ -0,0 +1,64 @@
+/**
+ * @provides javelin-behavior-dashboard-query-panel-select
+ * @requires javelin-behavior
+ * javelin-dom
+ */
+
+/**
+ * When editing a "Query" panel on dashboards, make the "Query" selector control
+ * dynamically update in response to changes to the "Engine" selector control.
+ */
+JX.behavior('dashboard-query-panel-select', function(config) {
+
+ var app_control = JX.$(config.applicationID);
+ var query_control = JX.$(config.queryID);
+
+ // If we have a currently-selected query, add it to the appropriate group
+ // in the options list if it does not already exist.
+ if (config.value.key !== null) {
+ var app = app_control.value;
+ if (!(app in config.options)) {
+ config.options[app] = [];
+ }
+
+ var found = false;
+ for (var ii = 0; ii < config.options[app].length; ii++) {
+ if (config.options[app][ii].key == config.value.key) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ config.options[app] = [config.value].concat(config.options[app]);
+ }
+ }
+
+ // When the user changes the selected search engine, update the query
+ // control to show avialable queries for that engine.
+ function update() {
+ var app = app_control.value;
+
+ var old_value = query_control.value;
+ var new_value = null;
+
+ var options = config.options[app] || [];
+ var nodes = [];
+ for (var ii = 0; ii < options.length; ii++) {
+ if (new_value === null) {
+ new_value = options[ii].key;
+ }
+ if (options[ii].key == old_value) {
+ new_value = options[ii].key;
+ }
+ nodes.push(JX.$N('option', {value: options[ii].key}, options[ii].name));
+ }
+
+ JX.DOM.setContent(query_control, nodes);
+ query_control.value = new_value;
+ }
+
+ JX.DOM.listen(app_control, 'change', null, function(e) { update(); });
+ update();
+
+});

File Metadata

Mime Type
text/plain
Expires
Aug 13 2025, 11:12 AM (9 w, 2 d ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
8370180
Default Alt Text
D9572.diff (12 KB)

Event Timeline