Page MenuHomePhabricator

D20814.diff
No OneTemporary

D20814.diff

diff --git a/resources/celerity/map.php b/resources/celerity/map.php
--- a/resources/celerity/map.php
+++ b/resources/celerity/map.php
@@ -141,7 +141,7 @@
'rsrc/css/phui/phui-big-info-view.css' => '362ad37b',
'rsrc/css/phui/phui-box.css' => '5ed3b8cb',
'rsrc/css/phui/phui-bulk-editor.css' => '374d5e30',
- 'rsrc/css/phui/phui-chart.css' => '10135a9d',
+ 'rsrc/css/phui/phui-chart.css' => '14df9ae3',
'rsrc/css/phui/phui-cms.css' => '8c05c41e',
'rsrc/css/phui/phui-comment-form.css' => '68a2d99a',
'rsrc/css/phui/phui-comment-panel.css' => 'ec4e31c0',
@@ -390,7 +390,7 @@
'rsrc/js/application/diffusion/behavior-pull-lastmodified.js' => 'c715c123',
'rsrc/js/application/doorkeeper/behavior-doorkeeper-tag.js' => '6a85bc5a',
'rsrc/js/application/drydock/drydock-live-operation-status.js' => '47a0728b',
- 'rsrc/js/application/fact/Chart.js' => 'eec96de0',
+ 'rsrc/js/application/fact/Chart.js' => 'ddb9dd1f',
'rsrc/js/application/fact/ChartCurtainView.js' => '86954222',
'rsrc/js/application/fact/ChartFunctionLabel.js' => '81de1dab',
'rsrc/js/application/files/behavior-document-engine.js' => '243d6c22',
@@ -699,7 +699,7 @@
'javelin-behavior-user-menu' => '60cd9241',
'javelin-behavior-view-placeholder' => 'a9942052',
'javelin-behavior-workflow' => '9623adc1',
- 'javelin-chart' => 'eec96de0',
+ 'javelin-chart' => 'ddb9dd1f',
'javelin-chart-curtain-view' => '86954222',
'javelin-chart-function-label' => '81de1dab',
'javelin-color' => '78f811c9',
@@ -828,7 +828,7 @@
'phui-calendar-day-css' => '9597d706',
'phui-calendar-list-css' => 'ccd7e4e2',
'phui-calendar-month-css' => 'cb758c42',
- 'phui-chart-css' => '10135a9d',
+ 'phui-chart-css' => '14df9ae3',
'phui-cms-css' => '8c05c41e',
'phui-comment-form-css' => '68a2d99a',
'phui-comment-panel-css' => 'ec4e31c0',
@@ -2066,6 +2066,12 @@
'javelin-uri',
'phabricator-notification',
),
+ 'ddb9dd1f' => array(
+ 'phui-chart-css',
+ 'd3',
+ 'javelin-chart-curtain-view',
+ 'javelin-chart-function-label',
+ ),
'dfa1d313' => array(
'javelin-behavior',
'javelin-dom',
@@ -2127,12 +2133,6 @@
'phabricator-keyboard-shortcut',
'javelin-stratcom',
),
- 'eec96de0' => array(
- 'phui-chart-css',
- 'd3',
- 'javelin-chart-curtain-view',
- 'javelin-chart-function-label',
- ),
'ef836bf2' => array(
'javelin-behavior',
'javelin-dom',
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
@@ -17,8 +17,8 @@
$datapoints = $function->newDatapoints($data_query);
foreach ($datapoints as $point) {
- $x = $point['x'];
- $function_points[$function_idx][$x] = $point;
+ $x_value = $point['x'];
+ $function_points[$function_idx][$x_value] = $point;
}
}
@@ -140,12 +140,67 @@
$series = array_reverse($series);
+ // We're going to group multiple events into a single point if they have
+ // X values that are very close to one another.
+ //
+ // If the Y values are also close to one another (these points are near
+ // one another in a horizontal line), it can be hard to select any
+ // individual point with the mouse.
+ //
+ // Even if the Y values are not close together (the points are on a
+ // fairly steep slope up or down), it's usually better to be able to
+ // mouse over a single point at the top or bottom of the slope and get
+ // a summary of what's going on.
+
+ $domain_max = $data_query->getMaximumValue();
+ $domain_min = $data_query->getMinimumValue();
+ $resolution = ($domain_max - $domain_min) / 100;
+
$events = array();
foreach ($raw_points as $function_idx => $points) {
$event_list = array();
+
+ $event_group = array();
+ $head_event = null;
foreach ($points as $point) {
- $event_list[] = $point;
+ $x = $point['x'];
+
+ if ($head_event === null) {
+ // We don't have any points yet, so start a new group.
+ $head_event = $x;
+ $event_group[] = $point;
+ } else if (($x - $head_event) <= $resolution) {
+ // This point is close to the first point in this group, so
+ // add it to the existing group.
+ $event_group[] = $point;
+ } else {
+ // This point is not close to the first point in the group,
+ // so create a new group.
+ $event_list[] = $event_group;
+ $head_event = $x;
+ $event_group = array($point);
+ }
}
+
+ if ($event_group) {
+ $event_list[] = $event_group;
+ }
+
+ $event_spec = array();
+ foreach ($event_list as $key => $event_points) {
+ // NOTE: We're using the last point as the representative point so
+ // that you can learn about a section of a chart by hovering over
+ // the point to right of the section, which is more intuitive than
+ // other points.
+ $event = last($event_points);
+
+ $event = $event + array(
+ 'n' => count($event_points),
+ );
+
+ $event_list[$key] = $event;
+ }
+
$events[] = $event_list;
}
diff --git a/webroot/rsrc/css/phui/phui-chart.css b/webroot/rsrc/css/phui/phui-chart.css
--- a/webroot/rsrc/css/phui/phui-chart.css
+++ b/webroot/rsrc/css/phui/phui-chart.css
@@ -36,16 +36,17 @@
}
.chart .point {
- fill: {$lightblue};
+ fill: #ffffff;
stroke: {$blue};
- stroke-width: 1px;
+ stroke-width: 2px;
+ position: relative;
+ cursor: pointer;
}
.chart-tooltip {
position: absolute;
text-align: center;
width: 120px;
- height: 16px;
overflow: hidden;
padding: 2px;
background: {$lightbluebackground};
diff --git a/webroot/rsrc/js/application/fact/Chart.js b/webroot/rsrc/js/application/fact/Chart.js
--- a/webroot/rsrc/js/application/fact/Chart.js
+++ b/webroot/rsrc/js/application/fact/Chart.js
@@ -133,6 +133,8 @@
},
_newStackedArea: function(g, dataset, x, y, div, curtain) {
+ var ii;
+
var to_date = JX.bind(this, this._newDate);
var area = d3.area()
@@ -144,7 +146,7 @@
.x(function(d) { return x(to_date(d.x)); })
.y(function(d) { return y(d.y1); });
- for (var ii = 0; ii < dataset.data.length; ii++) {
+ for (ii = 0; ii < dataset.data.length; ii++) {
var label = new JX.ChartFunctionLabel(dataset.labels[ii]);
var fill_color = label.getFillColor() || label.getColor();
@@ -160,6 +162,11 @@
.style('stroke', stroke_color)
.attr('d', line(dataset.data[ii]));
+ curtain.addFunctionLabel(label);
+ }
+
+ // Now that we've drawn all the areas and lines, draw the dots.
+ for (ii = 0; ii < dataset.data.length; ii++) {
g.selectAll('dot')
.data(dataset.events[ii])
.enter()
@@ -178,8 +185,16 @@
var d_d = dd.getDate();
+ var y = parseInt(d.y1);
+
+ var label = d.n + ' Points';
+
+ var view =
+ d_y + '-' + d_m + '-' + d_d + ': ' + y + '<br />' +
+ label;
+
div
- .html(d_y + '-' + d_m + '-' + d_d + ': ' + d.y1)
+ .html(view)
.style('opacity', 0.9)
.style('left', (d3.event.pageX - 60) + 'px')
.style('top', (d3.event.pageY - 38) + 'px');
@@ -187,9 +202,8 @@
.on('mouseout', function() {
div.style('opacity', 0);
});
-
- curtain.addFunctionLabel(label);
}
+
},
_newDate: function(epoch) {

File Metadata

Mime Type
text/plain
Expires
Sat, Mar 22, 9:12 PM (2 d, 14 h ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7655263
Default Alt Text
D20814.diff (7 KB)

Event Timeline