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 @@ -1454,6 +1454,7 @@ 'PhabricatorDashboardPanelTypeText' => 'applications/dashboard/paneltype/PhabricatorDashboardPanelTypeText.php', 'PhabricatorDashboardPanelViewController' => 'applications/dashboard/controller/PhabricatorDashboardPanelViewController.php', 'PhabricatorDashboardQuery' => 'applications/dashboard/query/PhabricatorDashboardQuery.php', + 'PhabricatorDashboardRenderingEngine' => 'applications/dashboard/engine/PhabricatorDashboardRenderingEngine.php', 'PhabricatorDashboardSearchEngine' => 'applications/dashboard/query/PhabricatorDashboardSearchEngine.php', 'PhabricatorDashboardTransaction' => 'applications/dashboard/storage/PhabricatorDashboardTransaction.php', 'PhabricatorDashboardTransactionEditor' => 'applications/dashboard/editor/PhabricatorDashboardTransactionEditor.php', @@ -4267,6 +4268,7 @@ 'PhabricatorDashboardPanelTypeText' => 'PhabricatorDashboardPanelType', 'PhabricatorDashboardPanelViewController' => 'PhabricatorDashboardController', 'PhabricatorDashboardQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', + 'PhabricatorDashboardRenderingEngine' => 'Phobject', 'PhabricatorDashboardSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhabricatorDashboardTransaction' => 'PhabricatorApplicationTransaction', 'PhabricatorDashboardTransactionEditor' => 'PhabricatorApplicationTransactionEditor', diff --git a/src/applications/dashboard/controller/PhabricatorDashboardViewController.php b/src/applications/dashboard/controller/PhabricatorDashboardViewController.php --- a/src/applications/dashboard/controller/PhabricatorDashboardViewController.php +++ b/src/applications/dashboard/controller/PhabricatorDashboardViewController.php @@ -36,11 +36,17 @@ ->setHeader($header) ->addPropertyList($properties); + $rendered_dashboard = id(new PhabricatorDashboardRenderingEngine()) + ->setViewer($viewer) + ->setDashboard($dashboard) + ->renderDashboard(); + return $this->buildApplicationPage( array( $crumbs, $box, $timeline, + $rendered_dashboard, ), array( 'title' => $title, diff --git a/src/applications/dashboard/engine/PhabricatorDashboardPanelRenderingEngine.php b/src/applications/dashboard/engine/PhabricatorDashboardPanelRenderingEngine.php --- a/src/applications/dashboard/engine/PhabricatorDashboardPanelRenderingEngine.php +++ b/src/applications/dashboard/engine/PhabricatorDashboardPanelRenderingEngine.php @@ -4,6 +4,15 @@ private $panel; private $viewer; + private $enableAsyncRendering; + + /** + * Allow the engine to render the panel via Ajax. + */ + public function setEnableAsyncRendering($enable) { + $this->enableAsyncRendering = $enable; + return $this; + } public function setViewer(PhabricatorUser $viewer) { $this->viewer = $viewer; @@ -35,6 +44,13 @@ $panel->getPanelType())); } + if ($this->enableAsyncRendering) { + if ($panel_type->shouldRenderAsync()) { + return $this->renderAsyncPanel($panel); + } + } + + return $panel_type->renderPanel($viewer, $panel); } @@ -44,4 +60,20 @@ ->setFormErrors(array($body)); } + private function renderAsyncPanel(PhabricatorDashboardPanel $panel) { + $panel_id = celerity_generate_unique_node_id(); + + Javelin::initBehavior( + 'dashboard-async-panel', + array( + 'panelID' => $panel_id, + 'uri' => '/dashboard/panel/render/'.$panel->getID().'/', + )); + + return id(new PHUIObjectBoxView()) + ->setHeaderText($panel->getName()) + ->setID($panel_id) + ->appendChild(pht('Loading...')); + } + } diff --git a/src/applications/dashboard/engine/PhabricatorDashboardRenderingEngine.php b/src/applications/dashboard/engine/PhabricatorDashboardRenderingEngine.php new file mode 100644 --- /dev/null +++ b/src/applications/dashboard/engine/PhabricatorDashboardRenderingEngine.php @@ -0,0 +1,34 @@ +viewer = $viewer; + return $this; + } + + public function setDashboard(PhabricatorDashboard $dashboard) { + $this->dashboard = $dashboard; + return $this; + } + + public function renderDashboard() { + $dashboard = $this->dashboard; + $viewer = $this->viewer; + + $result = array(); + foreach ($dashboard->getPanels() as $panel) { + $result[] = id(new PhabricatorDashboardPanelRenderingEngine()) + ->setViewer($viewer) + ->setPanel($panel) + ->setEnableAsyncRendering(true) + ->renderPanel(); + } + + return $result; + } + +} 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 @@ -48,4 +48,10 @@ ->appendChild(pht('TODO: Panel content goes here.')); } + public function shouldRenderAsync() { + // TODO: For now, just make these things random so we can catch anything + // that breaks. + return (mt_rand(0, 1) == 1); + } + } diff --git a/webroot/rsrc/js/application/dashboard/behavior-dashboard-async-panel.js b/webroot/rsrc/js/application/dashboard/behavior-dashboard-async-panel.js new file mode 100644 --- /dev/null +++ b/webroot/rsrc/js/application/dashboard/behavior-dashboard-async-panel.js @@ -0,0 +1,17 @@ +/** + * @provides javelin-behavior-dashboard-async-panel + * @requires javelin-behavior + * javelin-dom + * javelin-workflow + */ + +JX.behavior('dashboard-async-panel', function(config) { + var panel = JX.$(config.panelID); + panel.style.opacity = '0.5'; + + new JX.Workflow(config.uri) + .setHandler(function(r) { + JX.DOM.replace(panel, JX.$H(r.panelMarkup)); + }) + .start(); +});