1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-18 21:02:41 +01:00

Dashboards - add remove functionality

Summary: To get there, upgrade "headerless" to "headerMode". Add a new removepanel controller. Fixes T5084.

Test Plan: removed some panels to much success

Reviewers: chad, epriestley

Reviewed By: epriestley

Subscribers: epriestley, Korvin

Maniphest Tasks: T5078, T5084

Differential Revision: https://secure.phabricator.com/D9156
This commit is contained in:
Bob Trahan 2014-05-19 14:04:26 -07:00
parent 9cb4047134
commit d9058d7f3f
17 changed files with 327 additions and 99 deletions

View file

@ -52,7 +52,7 @@ return array(
'rsrc/css/application/conpherence/widget-pane.css' => 'bf275a6c', 'rsrc/css/application/conpherence/widget-pane.css' => 'bf275a6c',
'rsrc/css/application/contentsource/content-source-view.css' => '4b8b05d4', 'rsrc/css/application/contentsource/content-source-view.css' => '4b8b05d4',
'rsrc/css/application/countdown/timer.css' => '86b7b0a0', 'rsrc/css/application/countdown/timer.css' => '86b7b0a0',
'rsrc/css/application/dashboard/dashboard.css' => '2b41640b', 'rsrc/css/application/dashboard/dashboard.css' => 'fbf815b5',
'rsrc/css/application/diff/inline-comment-summary.css' => '8cfd34e8', 'rsrc/css/application/diff/inline-comment-summary.css' => '8cfd34e8',
'rsrc/css/application/differential/add-comment.css' => 'c478bcaa', 'rsrc/css/application/differential/add-comment.css' => 'c478bcaa',
'rsrc/css/application/differential/changeset-view.css' => 'c45747f0', 'rsrc/css/application/differential/changeset-view.css' => 'c45747f0',
@ -355,7 +355,7 @@ return array(
'rsrc/js/application/conpherence/behavior-pontificate.js' => '53f6f2dd', 'rsrc/js/application/conpherence/behavior-pontificate.js' => '53f6f2dd',
'rsrc/js/application/conpherence/behavior-widget-pane.js' => '40b1ff90', 'rsrc/js/application/conpherence/behavior-widget-pane.js' => '40b1ff90',
'rsrc/js/application/countdown/timer.js' => '889c96f3', 'rsrc/js/application/countdown/timer.js' => '889c96f3',
'rsrc/js/application/dashboard/behavior-dashboard-async-panel.js' => 'f1375ea5', '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-move-panels.js' => 'fa187a68',
'rsrc/js/application/differential/DifferentialInlineCommentEditor.js' => 'f2441746', 'rsrc/js/application/differential/DifferentialInlineCommentEditor.js' => 'f2441746',
'rsrc/js/application/differential/behavior-add-reviewers-and-ccs.js' => '533a187b', 'rsrc/js/application/differential/behavior-add-reviewers-and-ccs.js' => '533a187b',
@ -550,7 +550,7 @@ return array(
'javelin-behavior-conpherence-widget-pane' => '40b1ff90', 'javelin-behavior-conpherence-widget-pane' => '40b1ff90',
'javelin-behavior-countdown-timer' => '889c96f3', 'javelin-behavior-countdown-timer' => '889c96f3',
'javelin-behavior-dark-console' => 'e9fdb5e5', 'javelin-behavior-dark-console' => 'e9fdb5e5',
'javelin-behavior-dashboard-async-panel' => 'f1375ea5', 'javelin-behavior-dashboard-async-panel' => '469c0d9e',
'javelin-behavior-dashboard-move-panels' => 'fa187a68', 'javelin-behavior-dashboard-move-panels' => 'fa187a68',
'javelin-behavior-device' => '03d6ed07', 'javelin-behavior-device' => '03d6ed07',
'javelin-behavior-differential-add-reviewers-and-ccs' => '533a187b', 'javelin-behavior-differential-add-reviewers-and-ccs' => '533a187b',
@ -698,7 +698,7 @@ return array(
'phabricator-core-css' => '40151074', 'phabricator-core-css' => '40151074',
'phabricator-countdown-css' => '86b7b0a0', 'phabricator-countdown-css' => '86b7b0a0',
'phabricator-crumbs-view-css' => '6a23399c', 'phabricator-crumbs-view-css' => '6a23399c',
'phabricator-dashboard-css' => '2b41640b', 'phabricator-dashboard-css' => 'fbf815b5',
'phabricator-drag-and-drop-file-upload' => 'ae6abfba', 'phabricator-drag-and-drop-file-upload' => 'ae6abfba',
'phabricator-draggable-list' => '1681c4d4', 'phabricator-draggable-list' => '1681c4d4',
'phabricator-fatal-config-template-css' => '25d446d6', 'phabricator-fatal-config-template-css' => '25d446d6',
@ -1129,6 +1129,12 @@ return array(
1 => 'javelin-stratcom', 1 => 'javelin-stratcom',
2 => 'javelin-dom', 2 => 'javelin-dom',
), ),
'469c0d9e' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'javelin-workflow',
),
'46efd18e' => '46efd18e' =>
array( array(
0 => 'multirow-row-manager', 0 => 'multirow-row-manager',
@ -1254,6 +1260,13 @@ return array(
2 => 'javelin-util', 2 => 'javelin-util',
3 => 'phabricator-shaped-request', 3 => 'phabricator-shaped-request',
), ),
'62e18640' =>
array(
0 => 'javelin-install',
1 => 'javelin-util',
2 => 'javelin-dom',
3 => 'javelin-typeahead-normalizer',
),
'6453c869' => '6453c869' =>
array( array(
0 => 'javelin-install', 0 => 'javelin-install',
@ -1322,13 +1335,6 @@ return array(
0 => 'javelin-behavior', 0 => 'javelin-behavior',
1 => 'javelin-dom', 1 => 'javelin-dom',
), ),
'62e18640' =>
array(
0 => 'javelin-install',
1 => 'javelin-util',
2 => 'javelin-dom',
3 => 'javelin-typeahead-normalizer',
),
'76f4ebed' => '76f4ebed' =>
array( array(
0 => 'javelin-install', 0 => 'javelin-install',
@ -1961,12 +1967,6 @@ return array(
0 => 'javelin-install', 0 => 'javelin-install',
1 => 'javelin-util', 1 => 'javelin-util',
), ),
'f1375ea5' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'javelin-workflow',
),
'f2441746' => 'f2441746' =>
array( array(
0 => 'javelin-dom', 0 => 'javelin-dom',

View file

@ -1487,6 +1487,7 @@ phutil_register_library_map(array(
'PhabricatorDashboardPanelTypeText' => 'applications/dashboard/paneltype/PhabricatorDashboardPanelTypeText.php', 'PhabricatorDashboardPanelTypeText' => 'applications/dashboard/paneltype/PhabricatorDashboardPanelTypeText.php',
'PhabricatorDashboardPanelViewController' => 'applications/dashboard/controller/PhabricatorDashboardPanelViewController.php', 'PhabricatorDashboardPanelViewController' => 'applications/dashboard/controller/PhabricatorDashboardPanelViewController.php',
'PhabricatorDashboardQuery' => 'applications/dashboard/query/PhabricatorDashboardQuery.php', 'PhabricatorDashboardQuery' => 'applications/dashboard/query/PhabricatorDashboardQuery.php',
'PhabricatorDashboardRemovePanelController' => 'applications/dashboard/controller/PhabricatorDashboardRemovePanelController.php',
'PhabricatorDashboardRenderingEngine' => 'applications/dashboard/engine/PhabricatorDashboardRenderingEngine.php', 'PhabricatorDashboardRenderingEngine' => 'applications/dashboard/engine/PhabricatorDashboardRenderingEngine.php',
'PhabricatorDashboardSearchEngine' => 'applications/dashboard/query/PhabricatorDashboardSearchEngine.php', 'PhabricatorDashboardSearchEngine' => 'applications/dashboard/query/PhabricatorDashboardSearchEngine.php',
'PhabricatorDashboardTransaction' => 'applications/dashboard/storage/PhabricatorDashboardTransaction.php', 'PhabricatorDashboardTransaction' => 'applications/dashboard/storage/PhabricatorDashboardTransaction.php',
@ -4278,6 +4279,7 @@ phutil_register_library_map(array(
'PhabricatorDashboardPanelTypeText' => 'PhabricatorDashboardPanelType', 'PhabricatorDashboardPanelTypeText' => 'PhabricatorDashboardPanelType',
'PhabricatorDashboardPanelViewController' => 'PhabricatorDashboardController', 'PhabricatorDashboardPanelViewController' => 'PhabricatorDashboardController',
'PhabricatorDashboardQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorDashboardQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhabricatorDashboardRemovePanelController' => 'PhabricatorDashboardController',
'PhabricatorDashboardRenderingEngine' => 'Phobject', 'PhabricatorDashboardRenderingEngine' => 'Phobject',
'PhabricatorDashboardSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhabricatorDashboardSearchEngine' => 'PhabricatorApplicationSearchEngine',
'PhabricatorDashboardTransaction' => 'PhabricatorApplicationTransaction', 'PhabricatorDashboardTransaction' => 'PhabricatorApplicationTransaction',

View file

@ -26,6 +26,8 @@ final class PhabricatorApplicationDashboard extends PhabricatorApplication {
'edit/(?:(?P<id>\d+)/)?' => 'PhabricatorDashboardEditController', 'edit/(?:(?P<id>\d+)/)?' => 'PhabricatorDashboardEditController',
'addpanel/(?P<id>\d+)/' => 'PhabricatorDashboardAddPanelController', 'addpanel/(?P<id>\d+)/' => 'PhabricatorDashboardAddPanelController',
'movepanel/(?P<id>\d+)/' => 'PhabricatorDashboardMovePanelController', 'movepanel/(?P<id>\d+)/' => 'PhabricatorDashboardMovePanelController',
'removepanel/(?P<id>\d+)/'
=> 'PhabricatorDashboardRemovePanelController',
'panel/' => array( 'panel/' => array(
'(?:query/(?P<queryKey>[^/]+)/)?' '(?:query/(?P<queryKey>[^/]+)/)?'
=> 'PhabricatorDashboardPanelListController', => 'PhabricatorDashboardPanelListController',

View file

@ -68,12 +68,10 @@ final class PhabricatorDashboardAddPanelController
), ),
)); ));
if ($layout_config->isMultiColumnLayout()) {
$layout_config->setPanelLocation( $layout_config->setPanelLocation(
$request->getInt('column'), $request->getInt('column', 0),
$panel->getPHID()); $panel->getPHID());
$dashboard->setLayoutConfigFromObject($layout_config); $dashboard->setLayoutConfigFromObject($layout_config);
}
$editor = id(new PhabricatorDashboardTransactionEditor()) $editor = id(new PhabricatorDashboardTransactionEditor())
->setActor($viewer) ->setActor($viewer)

View file

@ -38,21 +38,9 @@ final class PhabricatorDashboardMovePanelController
} }
$layout_config = $dashboard->getLayoutConfigObject(); $layout_config = $dashboard->getLayoutConfigObject();
$layout_config->removePanel($panel_phid);
$panel_location_grid = $layout_config->getPanelLocations(); $panel_location_grid = $layout_config->getPanelLocations();
foreach ($panel_location_grid as $column => $panel_columns) {
$found_old_column = array_search($panel_phid, $panel_columns);
if ($found_old_column !== false) {
$new_panel_columns = $panel_columns;
array_splice(
$new_panel_columns,
$found_old_column,
1,
array());
$panel_location_grid[$column] = $new_panel_columns;
break;
}
}
$panel_columns = idx($panel_location_grid, $column_id, array()); $panel_columns = idx($panel_location_grid, $column_id, array());
if ($panel_columns) { if ($panel_columns) {
$insert_at = 0; $insert_at = 0;

View file

@ -52,7 +52,7 @@ final class PhabricatorDashboardPanelEditController
$title = pht('Edit %s', $panel->getMonogram()); $title = pht('Edit %s', $panel->getMonogram());
$header = pht('Edit %s %s', $panel->getMonogram(), $panel->getName()); $header = pht('Edit %s %s', $panel->getMonogram(), $panel->getName());
$button = pht('Save Panel'); $button = pht('Save Panel');
$cancel_uri = '/'.$panel->getMonogram(); $cancel_uri = $this->getPanelRedirectURI($panel);
} }
$v_name = $panel->getName(); $v_name = $panel->getName();
@ -89,7 +89,7 @@ final class PhabricatorDashboardPanelEditController
->applyTransactions($panel, $xactions); ->applyTransactions($panel, $xactions);
return id(new AphrontRedirectResponse()) return id(new AphrontRedirectResponse())
->setURI('/'.$panel->getMonogram()); ->setURI($this->getPanelRedirectURI($panel));
} catch (PhabricatorApplicationTransactionValidationException $ex) { } catch (PhabricatorApplicationTransactionValidationException $ex) {
$validation_exception = $ex; $validation_exception = $ex;
@ -144,4 +144,16 @@ final class PhabricatorDashboardPanelEditController
)); ));
} }
private function getPanelRedirectURI(PhabricatorDashboardPanel $panel) {
$request = $this->getRequest();
$dashboard_id = $request->getInt('dashboardID');
if ($dashboard_id) {
$uri = $this->getApplicationURI('arrange/'.$dashboard_id.'/');
} else {
$uri = '/'.$panel->getMonogram();
}
return $uri;
}
} }

View file

@ -37,7 +37,8 @@ final class PhabricatorDashboardPanelRenderController
->setViewer($viewer) ->setViewer($viewer)
->setPanel($panel) ->setPanel($panel)
->setParentPanelPHIDs($parent_phids) ->setParentPanelPHIDs($parent_phids)
->setHeaderless($request->getBool('headerless')) ->setHeaderMode($request->getStr('headerMode'))
->setDashboardID($request->getInt('dashboardID'))
->renderPanel(); ->renderPanel();
if ($request->isAjax()) { if ($request->isAjax()) {

View file

@ -0,0 +1,82 @@
<?php
final class PhabricatorDashboardRemovePanelController
extends PhabricatorDashboardController {
private $id;
public function willProcessRequest(array $data) {
$this->id = idx($data, 'id');
}
public function processRequest() {
$request = $this->getRequest();
$viewer = $request->getUser();
$dashboard = id(new PhabricatorDashboardQuery())
->setViewer($viewer)
->withIDs(array($this->id))
->requireCapabilities(
array(
PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT,
))
->executeOne();
if (!$dashboard) {
return new Aphront404Response();
}
$v_panel = $request->getStr('panelPHID');
$panel = id(new PhabricatorDashboardPanelQuery())
->setViewer($viewer)
->withPHIDs(array($v_panel))
->executeOne();
if (!$panel) {
return new Aphront404Response();
}
$redirect_uri = $this->getApplicationURI(
'arrange/'.$dashboard->getID().'/');
$layout_config = $dashboard->getLayoutConfigObject();
if ($request->isFormPost()) {
$xactions = array();
$xactions[] = id(new PhabricatorDashboardTransaction())
->setTransactionType(PhabricatorTransactions::TYPE_EDGE)
->setMetadataValue(
'edge:type',
PhabricatorEdgeConfig::TYPE_DASHBOARD_HAS_PANEL)
->setNewValue(
array(
'-' => array(
$panel->getPHID() => $panel->getPHID(),
),
));
$layout_config->removePanel($panel->getPHID());
$dashboard->setLayoutConfigFromObject($layout_config);
$editor = id(new PhabricatorDashboardTransactionEditor())
->setActor($viewer)
->setContentSourceFromRequest($request)
->setContinueOnMissingFields(true)
->setContinueOnNoEffect(true)
->applyTransactions($dashboard, $xactions);
return id(new AphrontRedirectResponse())->setURI($redirect_uri);
}
$form = id(new AphrontFormView())
->setUser($viewer)
->addHiddenInput('confirm', true)
->addHiddenInput('panelPHID', $v_panel)
->appendChild(pht('Are you sure you want to remove this panel?'));
return $this->newDialog()
->setTitle(pht('Remove Panel %s', $panel->getMonogram()))
->appendChild($form->buildLayoutView())
->addCancelButton($redirect_uri)
->addSubmitButton(pht('Remove Panel'));
}
}

View file

@ -2,19 +2,33 @@
final class PhabricatorDashboardPanelRenderingEngine extends Phobject { final class PhabricatorDashboardPanelRenderingEngine extends Phobject {
const HEADER_MODE_NORMAL = 'normal';
const HEADER_MODE_NONE = 'none';
const HEADER_MODE_EDIT = 'edit';
private $panel; private $panel;
private $viewer; private $viewer;
private $enableAsyncRendering; private $enableAsyncRendering;
private $parentPanelPHIDs; private $parentPanelPHIDs;
private $headerless; private $headerMode = self::HEADER_MODE_NORMAL;
private $dashboardID;
public function setHeaderless($headerless) { public function setDashboardID($id) {
$this->headerless = $headerless; $this->dashboardID = $id;
return $this; return $this;
} }
public function getHeaderless() { public function getDashboardID() {
return $this->headerless; return $this->dashboardID;
}
public function setHeaderMode($header_mode) {
$this->headerMode = $header_mode;
return $this;
}
public function getHeaderMode() {
return $this->headerMode;
} }
/** /**
@ -39,14 +53,22 @@ final class PhabricatorDashboardPanelRenderingEngine extends Phobject {
return $this; return $this;
} }
public function getViewer() {
return $this->viewer;
}
public function setPanel(PhabricatorDashboardPanel $panel) { public function setPanel(PhabricatorDashboardPanel $panel) {
$this->panel = $panel; $this->panel = $panel;
return $this; return $this;
} }
public function getPanel() {
return $this->panel;
}
public function renderPanel() { public function renderPanel() {
$panel = $this->panel; $panel = $this->getPanel();
$viewer = $this->viewer; $viewer = $this->getViewer();
if (!$panel) { if (!$panel) {
return $this->renderErrorPanel( return $this->renderErrorPanel(
@ -69,11 +91,11 @@ final class PhabricatorDashboardPanelRenderingEngine extends Phobject {
if ($this->enableAsyncRendering) { if ($this->enableAsyncRendering) {
if ($panel_type->shouldRenderAsync()) { if ($panel_type->shouldRenderAsync()) {
return $this->renderAsyncPanel($panel); return $this->renderAsyncPanel();
} }
} }
return $panel_type->renderPanel($viewer, $panel, $this); return $this->renderNormalPanel($viewer, $panel, $this);
} catch (Exception $ex) { } catch (Exception $ex) {
return $this->renderErrorPanel( return $this->renderErrorPanel(
$panel->getName(), $panel->getName(),
@ -84,47 +106,146 @@ final class PhabricatorDashboardPanelRenderingEngine extends Phobject {
} }
} }
private function renderErrorPanel($title, $body) { private function renderNormalPanel() {
if ($this->getHeaderless()) { $panel = $this->getPanel();
return id(new AphrontErrorView()) $panel_type = $panel->getImplementation();
->setErrors(array($body));
} else { $content = $panel_type->renderPanelContent(
return id(new PHUIObjectBoxView()) $this->getViewer(),
->setHeaderText($title) $panel,
->setFormErrors(array($body)); $this);
} $header = $this->renderPanelHeader();
return $this->renderPanelDiv(
$content,
$header);
} }
private function renderAsyncPanel(PhabricatorDashboardPanel $panel) {
private function renderAsyncPanel() {
$panel = $this->getPanel();
$panel_id = celerity_generate_unique_node_id(); $panel_id = celerity_generate_unique_node_id();
$dashboard_id = $this->getDashboardID();
Javelin::initBehavior( Javelin::initBehavior(
'dashboard-async-panel', 'dashboard-async-panel',
array( array(
'panelID' => $panel_id, 'panelID' => $panel_id,
'parentPanelPHIDs' => $this->getParentPanelPHIDs(), 'parentPanelPHIDs' => $this->getParentPanelPHIDs(),
'headerless' => $this->getHeaderless(), 'headerMode' => $this->getHeaderMode(),
'dashboardID' => $dashboard_id,
'uri' => '/dashboard/panel/render/'.$panel->getID().'/', 'uri' => '/dashboard/panel/render/'.$panel->getID().'/',
)); ));
$content = pht('Loading...'); $header = $this->renderPanelHeader();
$content = id(new PHUIPropertyListView())
->addTextContent(pht('Loading...'));
if ($this->headerless) { return $this->renderPanelDiv(
return phutil_tag( $content,
$header,
$panel_id);
}
private function renderErrorPanel($title, $body) {
switch ($this->getHeaderMode()) {
case self::HEADER_MODE_NONE:
$header = null;
break;
case self::HEADER_MODE_EDIT:
$header = id(new PhabricatorActionHeaderView())
->setHeaderTitle($title)
->setHeaderColor(PhabricatorActionHeaderView::HEADER_RED);
$header = $this->addPanelHeaderActions($header);
break;
case self::HEADER_MODE_NORMAL:
default:
$header = id(new PhabricatorActionHeaderView())
->setHeaderTitle($title)
->setHeaderColor(PhabricatorActionHeaderView::HEADER_RED);
break;
}
return $this->renderPanelDiv(
id(new AphrontErrorView())
->appendChild($body),
$header);
}
private function renderPanelDiv(
$content,
$header = null,
$id = null) {
$panel = $this->getPanel();
if (!$id) {
$id = celerity_generate_unique_node_id();
}
return javelin_tag(
'div', 'div',
array( array(
'id' => $panel_id, 'id' => $id,
), 'sigil' => 'dashboard-panel',
$content); 'meta' => array(
} else { 'objectPHID' => $panel->getPHID()),
return id(new PHUIObjectBoxView()) 'class' => 'dashboard-panel'),
->addSigil('dashboard-panel') array(
->setMetadata(array( $header,
'objectPHID' => $panel->getPHID())) $content));
->setHeaderText($panel->getName())
->setID($panel_id)
->appendChild($content);
} }
private function renderPanelHeader() {
$panel = $this->getPanel();
switch ($this->getHeaderMode()) {
case self::HEADER_MODE_NONE:
$header = null;
break;
case self::HEADER_MODE_EDIT:
$header = id(new PhabricatorActionHeaderView())
->setHeaderTitle($panel->getName())
->setHeaderColor(PhabricatorActionHeaderView::HEADER_GREY);
$header = $this->addPanelHeaderActions($header);
break;
case self::HEADER_MODE_NORMAL:
default:
$header = id(new PhabricatorActionHeaderView())
->setHeaderTitle($panel->getName())
->setHeaderColor(PhabricatorActionHeaderView::HEADER_GREY);
break;
}
return $header;
}
private function addPanelHeaderActions(
PhabricatorActionHeaderView $header) {
$panel = $this->getPanel();
$dashboard_id = $this->getDashboardID();
$edit_uri = id(new PhutilURI(
'/dashboard/panel/edit/'.$panel->getID().'/'));
if ($dashboard_id) {
$edit_uri->setQueryParam('dashboardID', $dashboard_id);
}
$action_edit = id(new PHUIIconView())
->setSpriteSheet(PHUIIconView::SPRITE_ACTIONS)
->setSpriteIcon('settings-grey')
->setHref((string) $edit_uri);
$header->addAction($action_edit);
if ($dashboard_id) {
$uri = id(new PhutilURI(
'/dashboard/removepanel/'.$dashboard_id.'/'))
->setQueryParam('panelPHID', $panel->getPHID());
$action_remove = id(new PHUIIconView())
->setSpriteSheet(PHUIIconView::SPRITE_ACTIONS)
->setSpriteIcon('close-grey')
->setHref((string) $uri)
->setWorkflow(true);
$header->addAction($action_remove);
}
return $header;
} }
/** /**

View file

@ -34,6 +34,11 @@ final class PhabricatorDashboardRenderingEngine extends Phobject {
->setID($dashboard_id) ->setID($dashboard_id)
->setFluidlayout(true); ->setFluidlayout(true);
if ($this->arrangeMode) {
$h_mode = PhabricatorDashboardPanelRenderingEngine::HEADER_MODE_EDIT;
} else {
$h_mode = PhabricatorDashboardPanelRenderingEngine::HEADER_MODE_NORMAL;
}
foreach ($panel_grid_locations as $column => $panel_column_locations) { foreach ($panel_grid_locations as $column => $panel_column_locations) {
$panel_phids = $panel_column_locations; $panel_phids = $panel_column_locations;
$column_panels = array_select_keys($panels, $panel_phids); $column_panels = array_select_keys($panels, $panel_phids);
@ -42,8 +47,10 @@ final class PhabricatorDashboardRenderingEngine extends Phobject {
$column_result[] = id(new PhabricatorDashboardPanelRenderingEngine()) $column_result[] = id(new PhabricatorDashboardPanelRenderingEngine())
->setViewer($viewer) ->setViewer($viewer)
->setPanel($panel) ->setPanel($panel)
->setDashboardID($dashboard->getID())
->setEnableAsyncRendering(true) ->setEnableAsyncRendering(true)
->setParentPanelPHIDs(array()) ->setParentPanelPHIDs(array())
->setHeaderMode($h_mode)
->renderPanel(); ->renderPanel();
} }
$column_class = $layout_config->getColumnClass( $column_class = $layout_config->getColumnClass(

View file

@ -32,6 +32,24 @@ final class PhabricatorDashboardLayoutConfig {
return $this->panelLocations; return $this->panelLocations;
} }
public function removePanel($panel_phid) {
$panel_location_grid = $this->getPanelLocations();
foreach ($panel_location_grid as $column => $panel_columns) {
$found_old_column = array_search($panel_phid, $panel_columns);
if ($found_old_column !== false) {
$new_panel_columns = $panel_columns;
array_splice(
$new_panel_columns,
$found_old_column,
1,
array());
$panel_location_grid[$column] = $new_panel_columns;
break;
}
}
$this->setPanelLocations($panel_location_grid);
}
public function getDefaultPanelLocations() { public function getDefaultPanelLocations() {
switch ($this->getLayoutMode()) { switch ($this->getLayoutMode()) {
case self::MODE_HALF_AND_HALF: case self::MODE_HALF_AND_HALF:

View file

@ -40,26 +40,9 @@ abstract class PhabricatorDashboardPanelType extends Phobject {
return $types; return $types;
} }
public function renderPanel(
PhabricatorUser $viewer,
PhabricatorDashboardPanel $panel,
PhabricatorDashboardPanelRenderingEngine $engine) {
$content = $this->renderPanelContent($viewer, $panel, $engine);
if ($engine->getHeaderless()) { public function renderPanelContent(
return $content;
}
return id(new PHUIObjectBoxView())
->addSigil('dashboard-panel')
->setMetadata(array(
'objectPHID' => $panel->getPHID()))
->setHeaderText($panel->getName())
->appendChild($content);
}
protected function renderPanelContent(
PhabricatorUser $viewer, PhabricatorUser $viewer,
PhabricatorDashboardPanel $panel, PhabricatorDashboardPanel $panel,
PhabricatorDashboardPanelRenderingEngine $engine) { PhabricatorDashboardPanelRenderingEngine $engine) {

View file

@ -30,7 +30,7 @@ final class PhabricatorDashboardPanelTypeQuery
); );
} }
protected function renderPanelContent( public function renderPanelContent(
PhabricatorUser $viewer, PhabricatorUser $viewer,
PhabricatorDashboardPanel $panel, PhabricatorDashboardPanel $panel,
PhabricatorDashboardPanelRenderingEngine $engine) { PhabricatorDashboardPanelRenderingEngine $engine) {

View file

@ -25,7 +25,7 @@ final class PhabricatorDashboardPanelTypeTabs
); );
} }
protected function renderPanelContent( public function renderPanelContent(
PhabricatorUser $viewer, PhabricatorUser $viewer,
PhabricatorDashboardPanel $panel, PhabricatorDashboardPanel $panel,
PhabricatorDashboardPanelRenderingEngine $engine) { PhabricatorDashboardPanelRenderingEngine $engine) {
@ -81,6 +81,7 @@ final class PhabricatorDashboardPanelTypeTabs
$parent_phids[] = $panel->getPHID(); $parent_phids[] = $panel->getPHID();
$content = array(); $content = array();
$no_headers = PhabricatorDashboardPanelRenderingEngine::HEADER_MODE_NONE;
foreach ($config as $idx => $tab_spec) { foreach ($config as $idx => $tab_spec) {
$panel_id = idx($tab_spec, 'panelID'); $panel_id = idx($tab_spec, 'panelID');
$panel = idx($panels, $panel_id); $panel = idx($panels, $panel_id);
@ -91,7 +92,7 @@ final class PhabricatorDashboardPanelTypeTabs
->setEnableAsyncRendering(true) ->setEnableAsyncRendering(true)
->setParentPanelPHIDs($parent_phids) ->setParentPanelPHIDs($parent_phids)
->setPanel($panel) ->setPanel($panel)
->setHeaderless(true) ->setHeaderMode($no_headers)
->renderPanel(); ->renderPanel();
} else { } else {
$panel_content = pht('(Invalid Panel)'); $panel_content = pht('(Invalid Panel)');

View file

@ -26,7 +26,7 @@ final class PhabricatorDashboardPanelTypeText
); );
} }
protected function renderPanelContent( public function renderPanelContent(
PhabricatorUser $viewer, PhabricatorUser $viewer,
PhabricatorDashboardPanel $panel, PhabricatorDashboardPanel $panel,
PhabricatorDashboardPanelRenderingEngine $engine) { PhabricatorDashboardPanelRenderingEngine $engine) {

View file

@ -17,9 +17,15 @@
width: 66.66%; width: 66.66%;
} }
.aphront-multi-column-fluid
.aphront-multi-column-column-outer
.aphront-multi-column-column .dashboard-panel {
margin: 16px 16px 0px 16px;
}
.aphront-multi-column-fluid .aphront-multi-column-fluid
.aphront-multi-column-column-outer.grippable .aphront-multi-column-column-outer.grippable
.aphront-multi-column-column .phui-object-box { .aphront-multi-column-column .dashboard-panel {
cursor: move; cursor: move;
} }
@ -57,3 +63,9 @@
.dashboard-panel-placeholder { .dashboard-panel-placeholder {
display: none; display: none;
} }
.aphront-multi-column-fluid
.aphront-multi-column-column-outer
.aphront-multi-column-column .aphront-error-view {
margin: 0;
}

View file

@ -11,7 +11,8 @@ JX.behavior('dashboard-async-panel', function(config) {
var data = { var data = {
parentPanelPHIDs: config.parentPanelPHIDs.join(','), parentPanelPHIDs: config.parentPanelPHIDs.join(','),
headerless: config.headerless ? 1 : 0 headerMode: config.headerMode,
dashboardID: config.dashboardID
}; };
new JX.Workflow(config.uri) new JX.Workflow(config.uri)