Page MenuHomestyx hydra

No OneTemporary

diff --git a/src/applications/dashboard/controller/PhabricatorDashboardAddPanelController.php b/src/applications/dashboard/controller/PhabricatorDashboardAddPanelController.php
index f34bdd06ae..46712d79e9 100644
--- a/src/applications/dashboard/controller/PhabricatorDashboardAddPanelController.php
+++ b/src/applications/dashboard/controller/PhabricatorDashboardAddPanelController.php
@@ -1,102 +1,95 @@
<?php
final class PhabricatorDashboardAddPanelController
extends PhabricatorDashboardController {
public function handleRequest(AphrontRequest $request) {
$viewer = $request->getViewer();
$id = $request->getURIData('id');
$dashboard = id(new PhabricatorDashboardQuery())
->setViewer($viewer)
->withIDs(array($id))
->requireCapabilities(
array(
PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT,
))
->executeOne();
if (!$dashboard) {
return new Aphront404Response();
}
$redirect_uri = $this->getApplicationURI(
'arrange/'.$dashboard->getID().'/');
- $v_panel = $request->getStr('panel');
+ $v_panel = head($request->getArr('panel'));
$e_panel = true;
$errors = array();
if ($request->isFormPost()) {
if (strlen($v_panel)) {
$panel = id(new PhabricatorDashboardPanelQuery())
->setViewer($viewer)
->withIDs(array($v_panel))
->executeOne();
if (!$panel) {
$errors[] = pht('No such panel!');
$e_panel = pht('Invalid');
}
} else {
$errors[] = pht('Select a panel to add.');
$e_panel = pht('Required');
}
if (!$errors) {
PhabricatorDashboardTransactionEditor::addPanelToDashboard(
$viewer,
PhabricatorContentSource::newFromRequest($request),
$panel,
$dashboard,
$request->getInt('column', 0));
return id(new AphrontRedirectResponse())->setURI($redirect_uri);
}
}
$panels = id(new PhabricatorDashboardPanelQuery())
->setViewer($viewer)
->withArchived(false)
->execute();
if (!$panels) {
return $this->newDialog()
->setTitle(pht('No Panels Exist Yet'))
->appendParagraph(
pht(
'You have not created any dashboard panels yet, so you can not '.
'add an existing panel.'))
->appendParagraph(
pht('Instead, add a new panel.'))
->addCancelButton($redirect_uri);
}
- $panel_options = array();
- foreach ($panels as $panel) {
- $panel_options[$panel->getID()] = pht(
- '%s %s',
- $panel->getMonogram(),
- $panel->getName());
- }
-
$form = id(new AphrontFormView())
->setUser($viewer)
->addHiddenInput('column', $request->getInt('column'))
->appendRemarkupInstructions(
pht('Choose a panel to add to this dashboard:'))
->appendChild(
- id(new AphrontFormSelectControl())
+ id(new AphrontFormTokenizerControl())
+ ->setUser($this->getViewer())
+ ->setDatasource(new PhabricatorDashboardPanelDatasource())
+ ->setLimit(1)
->setName('panel')
->setLabel(pht('Panel'))
- ->setValue($v_panel)
- ->setError($e_panel)
- ->setOptions($panel_options));
+ ->setValue($v_panel));
return $this->newDialog()
->setTitle(pht('Add Panel'))
->setErrors($errors)
->appendChild($form->buildLayoutView())
->addCancelButton($redirect_uri)
->addSubmitButton(pht('Add Panel'));
}
}
diff --git a/src/applications/dashboard/paneltype/PhabricatorDashboardPanelType.php b/src/applications/dashboard/paneltype/PhabricatorDashboardPanelType.php
index 81e7ec80cc..34c7b1c3ee 100644
--- a/src/applications/dashboard/paneltype/PhabricatorDashboardPanelType.php
+++ b/src/applications/dashboard/paneltype/PhabricatorDashboardPanelType.php
@@ -1,55 +1,56 @@
<?php
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(
PhabricatorUser $viewer,
PhabricatorDashboardPanel $panel,
PhabricatorDashboardPanelRenderingEngine $engine);
public function initializeFieldsFromRequest(
PhabricatorDashboardPanel $panel,
PhabricatorCustomFieldList $field_list,
AphrontRequest $request) {
return;
}
/**
* Should this panel pull content in over AJAX?
*
* Normally, panels use AJAX to render their content. This makes the page
* interactable sooner, allows panels to render in parallel, and prevents one
* slow panel from slowing everything down.
*
* However, some panels are very cheap to build (i.e., no expensive service
* calls or complicated rendering). In these cases overall performance can be
* improved by disabling async rendering so the panel rendering happens in the
* same process.
*
* @return bool True to enable asynchronous rendering when appropriate.
*/
public function shouldRenderAsync() {
return true;
}
public function adjustPanelHeader(
PhabricatorUser $viewer,
PhabricatorDashboardPanel $panel,
PhabricatorDashboardPanelRenderingEngine $engine,
PHUIHeaderView $header) {
return $header;
}
public static function getAllPanelTypes() {
return id(new PhutilClassMapQuery())
->setAncestorClass(__CLASS__)
->setUniqueMethod('getPanelTypeKey')
->execute();
}
}
diff --git a/src/applications/dashboard/paneltype/PhabricatorDashboardQueryPanelType.php b/src/applications/dashboard/paneltype/PhabricatorDashboardQueryPanelType.php
index 76e6e8432b..0781d71b16 100644
--- a/src/applications/dashboard/paneltype/PhabricatorDashboardQueryPanelType.php
+++ b/src/applications/dashboard/paneltype/PhabricatorDashboardQueryPanelType.php
@@ -1,148 +1,152 @@
<?php
final class PhabricatorDashboardQueryPanelType
extends PhabricatorDashboardPanelType {
public function getPanelTypeKey() {
return 'query';
}
public function getPanelTypeName() {
return pht('Query Panel');
}
+ public function getIcon() {
+ return 'fa-search';
+ }
+
public function getPanelTypeDescription() {
return pht(
'Show results of a search query, like the most recently filed tasks or '.
'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',
),
);
}
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,
PhabricatorDashboardPanelRenderingEngine $engine) {
$engine = $this->getSearchEngine($panel);
$engine->setViewer($viewer);
$engine->setContext(PhabricatorApplicationSearchEngine::CONTEXT_PANEL);
$key = $panel->getProperty('key');
if ($engine->isBuiltinQuery($key)) {
$saved = $engine->buildSavedQueryFromBuiltin($key);
} else {
$saved = id(new PhabricatorSavedQueryQuery())
->setViewer($viewer)
->withEngineClassNames(array(get_class($engine)))
->withQueryKeys(array($key))
->executeOne();
}
if (!$saved) {
throw new Exception(
pht(
'Query "%s" is unknown to application search engine "%s"!',
$key,
get_class($engine)));
}
$query = $engine->buildQueryFromSavedQuery($saved);
$pager = $engine->newPagerForSavedQuery($saved);
if ($panel->getProperty('limit')) {
$limit = (int)$panel->getProperty('limit');
if ($pager->getPageSize() !== 0xFFFF) {
$pager->setPageSize($limit);
}
}
$results = $engine->executeQuery($query, $pager);
return $engine->renderResults($results, $saved);
}
public function adjustPanelHeader(
PhabricatorUser $viewer,
PhabricatorDashboardPanel $panel,
PhabricatorDashboardPanelRenderingEngine $engine,
PHUIHeaderView $header) {
$search_engine = $this->getSearchEngine($panel);
$key = $panel->getProperty('key');
$href = $search_engine->getQueryResultsPageURI($key);
$icon = id(new PHUIIconView())
->setIcon('fa-search')
->setHref($href);
$header->addActionItem($icon);
return $header;
}
private function getSearchEngine(PhabricatorDashboardPanel $panel) {
$class = $panel->getProperty('class');
$engine = PhabricatorApplicationSearchEngine::getEngineByClassName($class);
if (!$engine) {
throw new Exception(
pht(
'The application search engine "%s" is not known to Phabricator!',
$class));
}
if (!$engine->canUseInPanelContext()) {
throw new Exception(
pht(
'Application search engines of class "%s" can not be used to build '.
'dashboard panels.',
$class));
}
return $engine;
}
}
diff --git a/src/applications/dashboard/paneltype/PhabricatorDashboardTabsPanelType.php b/src/applications/dashboard/paneltype/PhabricatorDashboardTabsPanelType.php
index 3cb758a11a..292446fe55 100644
--- a/src/applications/dashboard/paneltype/PhabricatorDashboardTabsPanelType.php
+++ b/src/applications/dashboard/paneltype/PhabricatorDashboardTabsPanelType.php
@@ -1,126 +1,130 @@
<?php
final class PhabricatorDashboardTabsPanelType
extends PhabricatorDashboardPanelType {
public function getPanelTypeKey() {
return 'tabs';
}
public function getPanelTypeName() {
return pht('Tab Panel');
}
+ public function getIcon() {
+ return 'fa-window-maximize';
+ }
+
public function getPanelTypeDescription() {
return pht('Use tabs to switch between several other panels.');
}
public function getFieldSpecifications() {
return array(
'config' => array(
'name' => pht('Tabs'),
'type' => 'dashboard.tabs',
),
);
}
public function shouldRenderAsync() {
// The actual tab panel itself is cheap to render.
return false;
}
public function renderPanelContent(
PhabricatorUser $viewer,
PhabricatorDashboardPanel $panel,
PhabricatorDashboardPanelRenderingEngine $engine) {
$config = $panel->getProperty('config');
if (!is_array($config)) {
// NOTE: The older version of this panel stored raw JSON.
$config = phutil_json_decode($config);
}
$list = id(new PHUIListView())
->setType(PHUIListView::NAVBAR_LIST);
$selected = 0;
$node_ids = array();
foreach ($config as $idx => $tab_spec) {
$node_ids[$idx] = celerity_generate_unique_node_id();
}
foreach ($config as $idx => $tab_spec) {
$list->addMenuItem(
id(new PHUIListItemView())
->setHref('#')
->setSelected($idx == $selected)
->addSigil('dashboard-tab-panel-tab')
->setMetadata(array('idx' => $idx))
->setName(idx($tab_spec, 'name', pht('Nameless Tab'))));
}
$ids = ipull($config, 'panelID');
if ($ids) {
$panels = id(new PhabricatorDashboardPanelQuery())
->setViewer($viewer)
->withIDs($ids)
->execute();
} else {
$panels = array();
}
$parent_phids = $engine->getParentPanelPHIDs();
$parent_phids[] = $panel->getPHID();
// TODO: Currently, we'll load all the panels on page load. It would be
// vaguely nice to load hidden panels only when the user selects them.
// TODO: Maybe we should persist which panel the user selected, so it
// remains selected across page loads.
$content = array();
$no_headers = PhabricatorDashboardPanelRenderingEngine::HEADER_MODE_NONE;
foreach ($config as $idx => $tab_spec) {
$panel_id = idx($tab_spec, 'panelID');
$panel = idx($panels, $panel_id);
if ($panel) {
$panel_content = id(new PhabricatorDashboardPanelRenderingEngine())
->setViewer($viewer)
->setEnableAsyncRendering(true)
->setParentPanelPHIDs($parent_phids)
->setPanel($panel)
->setPanelPHID($panel->getPHID())
->setHeaderMode($no_headers)
->renderPanel();
} else {
$panel_content = pht('(Invalid Panel)');
}
$content[] = phutil_tag(
'div',
array(
'id' => $node_ids[$idx],
'style' => ($idx == $selected) ? null : 'display: none',
),
$panel_content);
}
Javelin::initBehavior('dashboard-tab-panel');
return javelin_tag(
'div',
array(
'sigil' => 'dashboard-tab-panel-container',
'meta' => array(
'panels' => $node_ids,
),
),
array(
$list,
$content,
));
}
}
diff --git a/src/applications/dashboard/paneltype/PhabricatorDashboardTextPanelType.php b/src/applications/dashboard/paneltype/PhabricatorDashboardTextPanelType.php
index 413d3dc856..5ecde8501f 100644
--- a/src/applications/dashboard/paneltype/PhabricatorDashboardTextPanelType.php
+++ b/src/applications/dashboard/paneltype/PhabricatorDashboardTextPanelType.php
@@ -1,64 +1,68 @@
<?php
final class PhabricatorDashboardTextPanelType
extends PhabricatorDashboardPanelType {
public function getPanelTypeKey() {
return 'text';
}
public function getPanelTypeName() {
return pht('Text Panel');
}
+ public function getIcon() {
+ return 'fa-paragraph';
+ }
+
public function getPanelTypeDescription() {
return pht(
'Add some static text to the dashboard. This can be used to '.
'provide instructions or context.');
}
public function getFieldSpecifications() {
return array(
'text' => array(
'name' => pht('Text'),
'type' => 'remarkup',
),
);
}
public function shouldRenderAsync() {
// Rendering text panels is normally a cheap cache hit.
return false;
}
public function renderPanelContent(
PhabricatorUser $viewer,
PhabricatorDashboardPanel $panel,
PhabricatorDashboardPanelRenderingEngine $engine) {
$text = $panel->getProperty('text', '');
$oneoff = id(new PhabricatorMarkupOneOff())->setContent($text);
$field = 'default';
// NOTE: We're taking extra steps here to prevent creation of a text panel
// which embeds itself using `{Wnnn}`, recursing indefinitely.
$parent_key = PhabricatorDashboardRemarkupRule::KEY_PARENT_PANEL_PHIDS;
$parent_phids = $engine->getParentPanelPHIDs();
$parent_phids[] = $panel->getPHID();
$markup_engine = id(new PhabricatorMarkupEngine())
->setViewer($viewer)
->setContextObject($panel)
->setAuxiliaryConfig($parent_key, $parent_phids);
$text_content = $markup_engine
->addObject($oneoff, $field)
->process()
->getOutput($oneoff, $field);
return id(new PHUIPropertyListView())
->addTextContent($text_content);
}
}
diff --git a/src/applications/dashboard/typeahead/PhabricatorDashboardPanelDatasource.php b/src/applications/dashboard/typeahead/PhabricatorDashboardPanelDatasource.php
index 35c8c5c212..958883d34e 100644
--- a/src/applications/dashboard/typeahead/PhabricatorDashboardPanelDatasource.php
+++ b/src/applications/dashboard/typeahead/PhabricatorDashboardPanelDatasource.php
@@ -1,46 +1,65 @@
<?php
final class PhabricatorDashboardPanelDatasource
extends PhabricatorTypeaheadDatasource {
public function getBrowseTitle() {
return pht('Browse Dashboard Panels');
}
public function getPlaceholderText() {
return pht('Type a panel name...');
}
public function getDatasourceApplicationClass() {
return 'PhabricatorDashboardApplication';
}
public function loadResults() {
- $query = id(new PhabricatorDashboardPanelQuery());
+ $results = $this->buildResults();
+ return $this->filterResultsAgainstTokens($results);
+ }
+
+
+ protected function renderSpecialTokens(array $values) {
+ return $this->renderTokensFromResults($this->buildResults(), $values);
+ }
+ public function buildResults() {
+ $query = id(new PhabricatorDashboardPanelQuery());
$panels = $this->executeQuery($query);
+
$results = array();
foreach ($panels as $panel) {
$impl = $panel->getImplementation();
if ($impl) {
$type_text = $impl->getPanelTypeName();
} else {
$type_text = nonempty($panel->getPanelType(), pht('Unknown Type'));
}
+ $id = $panel->getID();
+ $monogram = $panel->getMonogram();
+ $properties = $panel->getProperties();
$result = id(new PhabricatorTypeaheadResult())
->setName($panel->getName())
- ->setPHID($panel->getPHID())
+ ->setDisplayName($monogram.' '.$panel->getName())
+ ->setPHID($id)
+ ->setIcon($impl->getIcon())
->addAttribute($type_text);
+ if (!empty($properties['class'])) {
+ $result->addAttribute($properties['class']);
+ }
+
if ($panel->getIsArchived()) {
$result->setClosed(pht('Archived'));
}
- $results[] = $result;
+ $results[$id] = $result;
}
- return $this->filterResultsAgainstTokens($results);
+ return $results;
}
}

File Metadata

Mime Type
text/x-diff
Expires
Tue, Jun 10, 11:45 PM (23 h, 38 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
141370
Default Alt Text
(18 KB)

Event Timeline