diff --git a/src/applications/fact/chart/PhabricatorChartStackedAreaDataset.php b/src/applications/fact/chart/PhabricatorChartStackedAreaDataset.php --- a/src/applications/fact/chart/PhabricatorChartStackedAreaDataset.php +++ b/src/applications/fact/chart/PhabricatorChartStackedAreaDataset.php @@ -148,9 +148,6 @@ $wire_labels = array(); foreach ($functions as $function_key => $function) { $label = $function->getFunctionLabel(); - - $label->setName(pht('Important Data %s', $function_key)); - $wire_labels[] = $label->toWireFormat(); } diff --git a/src/applications/fact/engine/PhabricatorChartEngine.php b/src/applications/fact/engine/PhabricatorChartEngine.php --- a/src/applications/fact/engine/PhabricatorChartEngine.php +++ b/src/applications/fact/engine/PhabricatorChartEngine.php @@ -4,6 +4,10 @@ extends Phobject { private $viewer; + private $engineParameters = array(); + + const KEY_ENGINE = 'engineKey'; + const KEY_PARAMETERS = 'engineParameters'; final public function setViewer(PhabricatorUser $viewer) { $this->viewer = $viewer; @@ -14,26 +18,65 @@ return $this->viewer; } + final protected function setEngineParameter($key, $value) { + $this->engineParameters[$key] = $value; + return $this; + } + + final protected function getEngineParameter($key, $default = null) { + return idx($this->engineParameters, $key, $default); + } + + final protected function getEngineParameters() { + return $this->engineParameters; + } + + final public static function newFromChart(PhabricatorFactChart $chart) { + $engine_key = $chart->getChartParameter(self::KEY_ENGINE); + + $engine_map = self::getAllChartEngines(); + if (!isset($engine_map[$engine_key])) { + throw new Exception( + pht( + 'Chart uses unknown engine key ("%s") and can not be rendered.', + $engine_key)); + } + + return clone id($engine_map[$engine_key]); + } + + final public static function getAllChartEngines() { + return id(new PhutilClassMapQuery()) + ->setAncestorClass(__CLASS__) + ->setUniqueMethod('getChartEngineKey') + ->execute(); + } + final public function getChartEngineKey() { return $this->getPhobjectClassConstant('CHARTENGINEKEY', 32); } - abstract protected function newChart(); + final public function buildChart(PhabricatorFactChart $chart) { + $map = $chart->getChartParameter(self::KEY_PARAMETERS, array()); + return $this->newChart($chart, $map); + } + + abstract protected function newChart(PhabricatorFactChart $chart, array $map); - final public function buildChart() { + final public function buildChartPanel() { $viewer = $this->getViewer(); - $chart = $this->newChart(); + $parameters = $this->getEngineParameters(); + + $chart = id(new PhabricatorFactChart()) + ->setChartParameter(self::KEY_ENGINE, $this->getChartEngineKey()) + ->setChartParameter(self::KEY_PARAMETERS, $this->getEngineParameters()); $rendering_engine = id(new PhabricatorChartRenderingEngine()) ->setViewer($viewer) ->setChart($chart); - return $rendering_engine->getStoredChart(); - } - - final public function buildChartPanel() { - $chart = $this->buildChart(); + $chart = $rendering_engine->getStoredChart(); $panel_type = id(new PhabricatorDashboardChartPanelType()) ->getPanelTypeKey(); @@ -45,4 +88,10 @@ return $chart_panel; } + final protected function newFunction($name /* , ... */) { + $argv = func_get_args(); + return id(new PhabricatorComposeChartFunction()) + ->setArguments(array($argv)); + } + } diff --git a/src/applications/fact/engine/PhabricatorChartRenderingEngine.php b/src/applications/fact/engine/PhabricatorChartRenderingEngine.php --- a/src/applications/fact/engine/PhabricatorChartRenderingEngine.php +++ b/src/applications/fact/engine/PhabricatorChartRenderingEngine.php @@ -113,6 +113,10 @@ $chart = $this->getStoredChart(); $chart_key = $chart->getChartKey(); + $chart_engine = PhabricatorChartEngine::newFromChart($chart) + ->setViewer($this->getViewer()); + $chart_engine->buildChart($chart); + $datasets = $chart->getDatasets(); $functions = array(); diff --git a/src/applications/fact/storage/PhabricatorFactChart.php b/src/applications/fact/storage/PhabricatorFactChart.php --- a/src/applications/fact/storage/PhabricatorFactChart.php +++ b/src/applications/fact/storage/PhabricatorFactChart.php @@ -7,7 +7,7 @@ protected $chartKey; protected $chartParameters = array(); - private $datasets; + private $datasets = self::ATTACHABLE; protected function getConfiguration() { return array( @@ -54,35 +54,14 @@ return parent::save(); } - public function setDatasets(array $datasets) { + public function attachDatasets(array $datasets) { assert_instances_of($datasets, 'PhabricatorChartDataset'); - - $dataset_list = array(); - foreach ($datasets as $dataset) { - $dataset_list[] = $dataset->toDictionary(); - } - - $this->setChartParameter('datasets', $dataset_list); - $this->datasets = null; - + $this->datasets = $datasets; return $this; } public function getDatasets() { - if ($this->datasets === null) { - $this->datasets = $this->newDatasets(); - } - return $this->datasets; - } - - private function newDatasets() { - $datasets = $this->getChartParameter('datasets', array()); - - foreach ($datasets as $key => $dataset) { - $datasets[$key] = PhabricatorChartDataset::newFromDictionary($dataset); - } - - return $datasets; + return $this->assertAttached($this->datasets); } public function getURI() { diff --git a/src/applications/project/chart/PhabricatorProjectBurndownChartEngine.php b/src/applications/project/chart/PhabricatorProjectBurndownChartEngine.php --- a/src/applications/project/chart/PhabricatorProjectBurndownChartEngine.php +++ b/src/applications/project/chart/PhabricatorProjectBurndownChartEngine.php @@ -5,52 +5,89 @@ const CHARTENGINEKEY = 'project.burndown'; - private $projects; - public function setProjects(array $projects) { assert_instances_of($projects, 'PhabricatorProject'); - - $this->projects = $projects; - - return $this; + $project_phids = mpull($projects, 'getPHID'); + return $this->setEngineParameter('projectPHIDs', $project_phids); } - public function getProjects() { - return $this->projects; - } + protected function newChart(PhabricatorFactChart $chart, array $map) { + $viewer = $this->getViewer(); + + $map = $map + array( + 'projectPHIDs' => array(), + ); - protected function newChart() { - if ($this->projects !== null) { - $project_phids = mpull($this->projects, 'getPHID'); + if ($map['projectPHIDs']) { + $projects = id(new PhabricatorProjectQuery()) + ->setViewer($viewer) + ->withPHIDs($map['projectPHIDs']) + ->execute(); + $project_phids = mpull($projects, 'getPHID'); } else { - $project_phids = null; + $project_phids = array(); } - $argvs = array(); + $functions = array(); if ($project_phids) { foreach ($project_phids as $project_phid) { - $argvs[] = array( + $function = $this->newFunction( 'accumulate', - array('fact', 'tasks.open-count.create.project', $project_phid), - ); - $argvs[] = array( + array('fact', 'tasks.open-count.create.project', $project_phid)); + + $function->getFunctionLabel() + ->setName(pht('Tasks Created')) + ->setColor('rgba(0, 0, 200, 1)') + ->setFillColor('rgba(0, 0, 200, 0.15)'); + + $functions[] = $function; + + + $function = $this->newFunction( 'accumulate', - array('fact', 'tasks.open-count.status.project', $project_phid), - ); - $argvs[] = array( + array('fact', 'tasks.open-count.status.project', $project_phid)); + + $function->getFunctionLabel() + ->setName(pht('Tasks Closed / Reopened')) + ->setColor('rgba(200, 0, 200, 1)') + ->setFillColor('rgba(200, 0, 200, 0.15)'); + + $functions[] = $function; + + + $function = $this->newFunction( 'accumulate', - array('fact', 'tasks.open-count.assign.project', $project_phid), - ); + array('fact', 'tasks.open-count.assign.project', $project_phid)); + + $function->getFunctionLabel() + ->setName(pht('Tasks Rescoped')) + ->setColor('rgba(0, 200, 200, 1)') + ->setFillColor('rgba(0, 200, 200, 0.15)'); + + $functions[] = $function; } } else { - $argvs[] = array('accumulate', array('fact', 'tasks.open-count.create')); - $argvs[] = array('accumulate', array('fact', 'tasks.open-count.status')); - } + $function = $this->newFunction( + 'accumulate', + array('fact', 'tasks.open-count.create')); - $functions = array(); - foreach ($argvs as $argv) { - $functions[] = id(new PhabricatorComposeChartFunction()) - ->setArguments(array($argv)); + $function->getFunctionLabel() + ->setName(pht('Tasks Created')) + ->setColor('rgba(0, 200, 200, 1)') + ->setFillColor('rgba(0, 200, 200, 0.15)'); + + $functions[] = $function; + + $function = $this->newFunction( + 'accumulate', + array('fact', 'tasks.open-count.status')); + + $function->getFunctionLabel() + ->setName(pht('Tasks Closed / Reopened')) + ->setColor('rgba(200, 0, 200, 1)') + ->setFillColor('rgba(200, 0, 200, 0.15)'); + + $functions[] = $function; } $datasets = array(); @@ -58,10 +95,7 @@ $datasets[] = id(new PhabricatorChartStackedAreaDataset()) ->setFunctions($functions); - $chart = id(new PhabricatorFactChart()) - ->setDatasets($datasets); - - return $chart; + $chart->attachDatasets($datasets); } }