mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-10 08:52:39 +01:00
Select the domain (X-axis range) for charts before pulling data
Summary: Depends on D20441. Ref T13279. Currently, we pull all the data, then decide what the X-axis should look like. Since users will reasonably want to do stuff like "show me march-april 2018" in the future, we need to move toward flipping this around so that we can support cases where the domain is specified by the user. For actual chart functions (like "constant(3)" or "cos(x)"), we must also know the domain before we pull data, since there are an infinite number of places where we can evaluate the function "constant(3)". See note in T13279 about continunity. Test Plan: {F6382356} Reviewers: amckinley Reviewed By: amckinley Subscribers: yelirekim Maniphest Tasks: T13279 Differential Revision: https://secure.phabricator.com/D20442
This commit is contained in:
parent
954831f533
commit
23d8f000f7
5 changed files with 140 additions and 14 deletions
|
@ -2649,7 +2649,8 @@ phutil_register_library_map(array(
|
|||
'PhabricatorChangeParserTestCase' => 'applications/repository/worker/__tests__/PhabricatorChangeParserTestCase.php',
|
||||
'PhabricatorChangesetCachePurger' => 'applications/cache/purger/PhabricatorChangesetCachePurger.php',
|
||||
'PhabricatorChangesetResponse' => 'infrastructure/diff/PhabricatorChangesetResponse.php',
|
||||
'PhabricatorChartFunction' => 'applications/fact/function/PhabricatorChartFunction.php',
|
||||
'PhabricatorChartAxis' => 'applications/fact/chart/PhabricatorChartAxis.php',
|
||||
'PhabricatorChartFunction' => 'applications/fact/chart/PhabricatorChartFunction.php',
|
||||
'PhabricatorChatLogApplication' => 'applications/chatlog/application/PhabricatorChatLogApplication.php',
|
||||
'PhabricatorChatLogChannel' => 'applications/chatlog/storage/PhabricatorChatLogChannel.php',
|
||||
'PhabricatorChatLogChannelListController' => 'applications/chatlog/controller/PhabricatorChatLogChannelListController.php',
|
||||
|
@ -3204,7 +3205,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorFactApplication' => 'applications/fact/application/PhabricatorFactApplication.php',
|
||||
'PhabricatorFactChart' => 'applications/fact/storage/PhabricatorFactChart.php',
|
||||
'PhabricatorFactChartController' => 'applications/fact/controller/PhabricatorFactChartController.php',
|
||||
'PhabricatorFactChartFunction' => 'applications/fact/function/PhabricatorFactChartFunction.php',
|
||||
'PhabricatorFactChartFunction' => 'applications/fact/chart/PhabricatorFactChartFunction.php',
|
||||
'PhabricatorFactController' => 'applications/fact/controller/PhabricatorFactController.php',
|
||||
'PhabricatorFactCursor' => 'applications/fact/storage/PhabricatorFactCursor.php',
|
||||
'PhabricatorFactDAO' => 'applications/fact/storage/PhabricatorFactDAO.php',
|
||||
|
@ -8621,6 +8622,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorChangeParserTestCase' => 'PhabricatorWorkingCopyTestCase',
|
||||
'PhabricatorChangesetCachePurger' => 'PhabricatorCachePurger',
|
||||
'PhabricatorChangesetResponse' => 'AphrontProxyResponse',
|
||||
'PhabricatorChartAxis' => 'Phobject',
|
||||
'PhabricatorChartFunction' => 'Phobject',
|
||||
'PhabricatorChatLogApplication' => 'PhabricatorApplication',
|
||||
'PhabricatorChatLogChannel' => array(
|
||||
|
|
27
src/applications/fact/chart/PhabricatorChartAxis.php
Normal file
27
src/applications/fact/chart/PhabricatorChartAxis.php
Normal file
|
@ -0,0 +1,27 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorChartAxis
|
||||
extends Phobject {
|
||||
|
||||
private $minimumValue;
|
||||
private $maximumValue;
|
||||
|
||||
public function setMinimumValue($minimum_value) {
|
||||
$this->minimumValue = $minimum_value;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getMinimumValue() {
|
||||
return $this->minimumValue;
|
||||
}
|
||||
|
||||
public function setMaximumValue($maximum_value) {
|
||||
$this->maximumValue = $maximum_value;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getMaximumValue() {
|
||||
return $this->maximumValue;
|
||||
}
|
||||
|
||||
}
|
|
@ -3,6 +3,10 @@
|
|||
abstract class PhabricatorChartFunction
|
||||
extends Phobject {
|
||||
|
||||
private $xAxis;
|
||||
private $yAxis;
|
||||
private $limit;
|
||||
|
||||
final public function getFunctionKey() {
|
||||
return $this->getPhobjectClassConstant('FUNCTIONKEY', 32);
|
||||
}
|
||||
|
@ -21,4 +25,22 @@ abstract class PhabricatorChartFunction
|
|||
|
||||
abstract protected function newArguments(array $arguments);
|
||||
|
||||
final public function setXAxis(PhabricatorChartAxis $x_axis) {
|
||||
$this->xAxis = $x_axis;
|
||||
return $this;
|
||||
}
|
||||
|
||||
final public function getXAxis() {
|
||||
return $this->xAxis;
|
||||
}
|
||||
|
||||
final public function setYAxis(PhabricatorChartAxis $y_axis) {
|
||||
$this->yAxis = $y_axis;
|
||||
return $this;
|
||||
}
|
||||
|
||||
final public function getYAxis() {
|
||||
return $this->yAxis;
|
||||
}
|
||||
|
||||
}
|
|
@ -83,6 +83,26 @@ final class PhabricatorFactChartFunction
|
|||
return array();
|
||||
}
|
||||
|
||||
$axis = $this->getXAxis();
|
||||
$x_min = $axis->getMinimumValue();
|
||||
$x_max = $axis->getMaximumValue();
|
||||
|
||||
if ($x_min !== null) {
|
||||
foreach ($points as $key => $point) {
|
||||
if ($point['x'] < $x_min) {
|
||||
unset($points[$key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($x_max !== null) {
|
||||
foreach ($points as $key => $point) {
|
||||
if ($point['x'] > $x_max) {
|
||||
unset($points[$key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If we have too many data points, throw away some of the data.
|
||||
$count = count($points);
|
||||
if ($count > $limit) {
|
||||
|
@ -99,4 +119,15 @@ final class PhabricatorFactChartFunction
|
|||
return $points;
|
||||
}
|
||||
|
||||
public function hasDomain() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getDomain() {
|
||||
// TODO: We can examine the data to fit a better domain.
|
||||
|
||||
$now = PhabricatorTime::getNow();
|
||||
return array($now - phutil_units('90 days in seconds'), $now);
|
||||
}
|
||||
|
||||
}
|
|
@ -24,8 +24,16 @@ final class PhabricatorFactChartController extends PhabricatorFactController {
|
|||
return $this->newChartResponse();
|
||||
}
|
||||
|
||||
list($domain_min, $domain_max) = $this->getDomain($functions);
|
||||
|
||||
$axis = id(new PhabricatorChartAxis())
|
||||
->setMinimumValue($domain_min)
|
||||
->setMaximumValue($domain_max);
|
||||
|
||||
$datasets = array();
|
||||
foreach ($functions as $function) {
|
||||
$function->setXAxis($axis);
|
||||
|
||||
$function->loadData();
|
||||
|
||||
$points = $function->getDatapoints(2000);
|
||||
|
@ -45,10 +53,9 @@ final class PhabricatorFactChartController extends PhabricatorFactController {
|
|||
);
|
||||
}
|
||||
|
||||
|
||||
$y_min = 0;
|
||||
$y_max = 0;
|
||||
$x_min = null;
|
||||
$x_max = 0;
|
||||
foreach ($datasets as $dataset) {
|
||||
if (!$dataset['y']) {
|
||||
continue;
|
||||
|
@ -56,20 +63,12 @@ final class PhabricatorFactChartController extends PhabricatorFactController {
|
|||
|
||||
$y_min = min($y_min, min($dataset['y']));
|
||||
$y_max = max($y_max, max($dataset['y']));
|
||||
|
||||
if ($x_min === null) {
|
||||
$x_min = min($dataset['x']);
|
||||
} else {
|
||||
$x_min = min($x_min, min($dataset['x']));
|
||||
}
|
||||
|
||||
$x_max = max($x_max, max($dataset['x']));
|
||||
}
|
||||
|
||||
$chart_data = array(
|
||||
'datasets' => $datasets,
|
||||
'xMin' => $x_min,
|
||||
'xMax' => $x_max,
|
||||
'xMin' => $domain_min,
|
||||
'xMax' => $domain_max,
|
||||
'yMin' => $y_min,
|
||||
'yMax' => $y_max,
|
||||
);
|
||||
|
@ -117,4 +116,49 @@ final class PhabricatorFactChartController extends PhabricatorFactController {
|
|||
|
||||
}
|
||||
|
||||
private function getDomain(array $functions) {
|
||||
$domain_min_list = null;
|
||||
$domain_max_list = null;
|
||||
foreach ($functions as $function) {
|
||||
if ($function->hasDomain()) {
|
||||
$domain = $function->getDomain();
|
||||
|
||||
list($domain_min, $domain_max) = $domain;
|
||||
|
||||
if ($domain_min !== null) {
|
||||
$domain_min_list[] = $domain_min;
|
||||
}
|
||||
|
||||
if ($domain_max !== null) {
|
||||
$domain_max_list[] = $domain_max;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$domain_min = null;
|
||||
$domain_max = null;
|
||||
|
||||
if ($domain_min_list) {
|
||||
$domain_min = min($domain_min_list);
|
||||
}
|
||||
|
||||
if ($domain_max_list) {
|
||||
$domain_max = max($domain_max_list);
|
||||
}
|
||||
|
||||
// If we don't have any domain data from the actual functions, pick a
|
||||
// plausible domain automatically.
|
||||
|
||||
if ($domain_max === null) {
|
||||
$domain_max = PhabricatorTime::getNow();
|
||||
}
|
||||
|
||||
if ($domain_min === null) {
|
||||
$domain_min = $domain_max - phutil_units('365 days in seconds');
|
||||
}
|
||||
|
||||
return array($domain_min, $domain_max);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue