1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-29 10:12:41 +01:00

Provide chart function labels over the wire instead of making them up

Summary: Ref T13279. Makes charts incrementally more useful by allowing the server to provide labels and colors for functions.

Test Plan: {F6438872}

Reviewers: amckinley

Reviewed By: amckinley

Subscribers: yelirekim

Maniphest Tasks: T13279

Differential Revision: https://secure.phabricator.com/D20501
This commit is contained in:
epriestley 2019-05-08 07:06:14 -07:00
parent c6052b41a6
commit a80426b339
8 changed files with 149 additions and 20 deletions

View file

@ -389,8 +389,9 @@ return array(
'rsrc/js/application/diffusion/behavior-pull-lastmodified.js' => 'c715c123', 'rsrc/js/application/diffusion/behavior-pull-lastmodified.js' => 'c715c123',
'rsrc/js/application/doorkeeper/behavior-doorkeeper-tag.js' => '6a85bc5a', 'rsrc/js/application/doorkeeper/behavior-doorkeeper-tag.js' => '6a85bc5a',
'rsrc/js/application/drydock/drydock-live-operation-status.js' => '47a0728b', 'rsrc/js/application/drydock/drydock-live-operation-status.js' => '47a0728b',
'rsrc/js/application/fact/Chart.js' => 'b88a227d', 'rsrc/js/application/fact/Chart.js' => 'eec96de0',
'rsrc/js/application/fact/ChartCurtainView.js' => 'd10a3c25', 'rsrc/js/application/fact/ChartCurtainView.js' => '86954222',
'rsrc/js/application/fact/ChartFunctionLabel.js' => '81de1dab',
'rsrc/js/application/files/behavior-document-engine.js' => '243d6c22', 'rsrc/js/application/files/behavior-document-engine.js' => '243d6c22',
'rsrc/js/application/files/behavior-icon-composer.js' => '38a6cedb', 'rsrc/js/application/files/behavior-icon-composer.js' => '38a6cedb',
'rsrc/js/application/files/behavior-launch-icon-composer.js' => 'a17b84f1', 'rsrc/js/application/files/behavior-launch-icon-composer.js' => 'a17b84f1',
@ -697,8 +698,9 @@ return array(
'javelin-behavior-user-menu' => '60cd9241', 'javelin-behavior-user-menu' => '60cd9241',
'javelin-behavior-view-placeholder' => 'a9942052', 'javelin-behavior-view-placeholder' => 'a9942052',
'javelin-behavior-workflow' => '9623adc1', 'javelin-behavior-workflow' => '9623adc1',
'javelin-chart' => 'b88a227d', 'javelin-chart' => 'eec96de0',
'javelin-chart-curtain-view' => 'd10a3c25', 'javelin-chart-curtain-view' => '86954222',
'javelin-chart-function-label' => '81de1dab',
'javelin-color' => '78f811c9', 'javelin-color' => '78f811c9',
'javelin-cookie' => '05d290ef', 'javelin-cookie' => '05d290ef',
'javelin-diffusion-locate-file-source' => '94243d89', 'javelin-diffusion-locate-file-source' => '94243d89',
@ -1933,11 +1935,6 @@ return array(
'javelin-dom', 'javelin-dom',
'phabricator-draggable-list', 'phabricator-draggable-list',
), ),
'b88a227d' => array(
'phui-chart-css',
'd3',
'javelin-chart-curtain-view',
),
'b9109f8f' => array( 'b9109f8f' => array(
'javelin-behavior', 'javelin-behavior',
'javelin-uri', 'javelin-uri',
@ -2128,6 +2125,12 @@ return array(
'phabricator-keyboard-shortcut', 'phabricator-keyboard-shortcut',
'javelin-stratcom', 'javelin-stratcom',
), ),
'eec96de0' => array(
'phui-chart-css',
'd3',
'javelin-chart-curtain-view',
'javelin-chart-function-label',
),
'ef836bf2' => array( 'ef836bf2' => array(
'javelin-behavior', 'javelin-behavior',
'javelin-dom', 'javelin-dom',

View file

@ -2668,6 +2668,7 @@ phutil_register_library_map(array(
'PhabricatorChartFunction' => 'applications/fact/chart/PhabricatorChartFunction.php', 'PhabricatorChartFunction' => 'applications/fact/chart/PhabricatorChartFunction.php',
'PhabricatorChartFunctionArgument' => 'applications/fact/chart/PhabricatorChartFunctionArgument.php', 'PhabricatorChartFunctionArgument' => 'applications/fact/chart/PhabricatorChartFunctionArgument.php',
'PhabricatorChartFunctionArgumentParser' => 'applications/fact/chart/PhabricatorChartFunctionArgumentParser.php', 'PhabricatorChartFunctionArgumentParser' => 'applications/fact/chart/PhabricatorChartFunctionArgumentParser.php',
'PhabricatorChartFunctionLabel' => 'applications/fact/chart/PhabricatorChartFunctionLabel.php',
'PhabricatorChartRenderingEngine' => 'applications/fact/engine/PhabricatorChartRenderingEngine.php', 'PhabricatorChartRenderingEngine' => 'applications/fact/engine/PhabricatorChartRenderingEngine.php',
'PhabricatorChartStackedAreaDataset' => 'applications/fact/chart/PhabricatorChartStackedAreaDataset.php', 'PhabricatorChartStackedAreaDataset' => 'applications/fact/chart/PhabricatorChartStackedAreaDataset.php',
'PhabricatorChatLogApplication' => 'applications/chatlog/application/PhabricatorChatLogApplication.php', 'PhabricatorChatLogApplication' => 'applications/chatlog/application/PhabricatorChatLogApplication.php',
@ -8683,6 +8684,7 @@ phutil_register_library_map(array(
'PhabricatorChartFunction' => 'Phobject', 'PhabricatorChartFunction' => 'Phobject',
'PhabricatorChartFunctionArgument' => 'Phobject', 'PhabricatorChartFunctionArgument' => 'Phobject',
'PhabricatorChartFunctionArgumentParser' => 'Phobject', 'PhabricatorChartFunctionArgumentParser' => 'Phobject',
'PhabricatorChartFunctionLabel' => 'Phobject',
'PhabricatorChartRenderingEngine' => 'Phobject', 'PhabricatorChartRenderingEngine' => 'Phobject',
'PhabricatorChartStackedAreaDataset' => 'PhabricatorChartDataset', 'PhabricatorChartStackedAreaDataset' => 'PhabricatorChartDataset',
'PhabricatorChatLogApplication' => 'PhabricatorApplication', 'PhabricatorChatLogApplication' => 'PhabricatorApplication',

View file

@ -4,6 +4,7 @@ abstract class PhabricatorChartFunction
extends Phobject { extends Phobject {
private $argumentParser; private $argumentParser;
private $functionLabel;
final public function getFunctionKey() { final public function getFunctionKey() {
return $this->getPhobjectClassConstant('FUNCTIONKEY', 32); return $this->getPhobjectClassConstant('FUNCTIONKEY', 32);
@ -43,6 +44,22 @@ abstract class PhabricatorChartFunction
return $this; return $this;
} }
public function setFunctionLabel(PhabricatorChartFunctionLabel $label) {
$this->functionLabel = $label;
return $this;
}
public function getFunctionLabel() {
if (!$this->functionLabel) {
$this->functionLabel = id(new PhabricatorChartFunctionLabel())
->setName(pht('Unlabeled Function'))
->setColor('rgba(255, 0, 0, 1)')
->setFillColor('rgba(255, 0, 0, 0.15)');
}
return $this->functionLabel;
}
final public static function newFromDictionary(array $map) { final public static function newFromDictionary(array $map) {
PhutilTypeSpec::checkMap( PhutilTypeSpec::checkMap(
$map, $map,

View file

@ -0,0 +1,56 @@
<?php
final class PhabricatorChartFunctionLabel
extends Phobject {
private $name;
private $color;
private $icon;
private $fillColor;
public function setName($name) {
$this->name = $name;
return $this;
}
public function getName() {
return $this->name;
}
public function setColor($color) {
$this->color = $color;
return $this;
}
public function getColor() {
return $this->color;
}
public function setIcon($icon) {
$this->icon = $icon;
return $this;
}
public function getIcon() {
return $this->icon;
}
public function setFillColor($fill_color) {
$this->fillColor = $fill_color;
return $this;
}
public function getFillColor() {
return $this->fillColor;
}
public function toWireFormat() {
return array(
'name' => $this->getName(),
'color' => $this->getColor(),
'icon' => $this->getIcon(),
'fillColor' => $this->getFillColor(),
);
}
}

View file

@ -131,15 +131,20 @@ final class PhabricatorChartStackedAreaDataset
$events[] = $event_list; $events[] = $event_list;
} }
$wire_labels = array();
foreach ($functions as $function_key => $function) {
$label = $function->getFunctionLabel();
$label->setName(pht('Important Data %s', $function_key));
$wire_labels[] = $label->toWireFormat();
}
$result = array( $result = array(
'type' => $this->getDatasetTypeKey(), 'type' => $this->getDatasetTypeKey(),
'data' => $series, 'data' => $series,
'events' => $events, 'events' => $events,
'color' => array( 'labels' => $wire_labels,
'blue',
'cyan',
'green',
),
); );
return $result; return $result;

View file

@ -3,6 +3,7 @@
* @requires phui-chart-css * @requires phui-chart-css
* d3 * d3
* javelin-chart-curtain-view * javelin-chart-curtain-view
* javelin-chart-function-label
*/ */
JX.install('Chart', { JX.install('Chart', {
@ -144,13 +145,19 @@ JX.install('Chart', {
.y(function(d) { return y(d.y1); }); .y(function(d) { return y(d.y1); });
for (var ii = 0; ii < dataset.data.length; ii++) { for (var ii = 0; ii < dataset.data.length; ii++) {
var label = new JX.ChartFunctionLabel(dataset.labels[ii]);
var fill_color = label.getFillColor() || label.getColor();
g.append('path') g.append('path')
.style('fill', dataset.color[ii % dataset.color.length]) .style('fill', fill_color)
.style('opacity', '0.15')
.attr('d', area(dataset.data[ii])); .attr('d', area(dataset.data[ii]));
var stroke_color = label.getColor();
g.append('path') g.append('path')
.attr('class', 'line') .attr('class', 'line')
.style('stroke', stroke_color)
.attr('d', line(dataset.data[ii])); .attr('d', line(dataset.data[ii]));
g.selectAll('dot') g.selectAll('dot')
@ -181,7 +188,7 @@ JX.install('Chart', {
div.style('opacity', 0); div.style('opacity', 0);
}); });
curtain.addFunctionLabel('Important Data'); curtain.addFunctionLabel(label);
} }
}, },

View file

@ -64,17 +64,21 @@ JX.install('ChartCurtainView', {
return this._labelsNode; return this._labelsNode;
}, },
_newFunctionLabelItem: function(item) { _newFunctionLabelItem: function(label) {
var item_attrs = { var item_attrs = {
className: 'chart-function-label-list-item' className: 'chart-function-label-list-item'
}; };
var icon = new JX.PHUIXIconView() var icon = new JX.PHUIXIconView()
.setIcon('fa-circle'); .setIcon(label.getIcon());
// Charts may use custom colors, so we can't rely on the CSS classes
// which only provide standard colors like "red" and "blue".
icon.getNode().style.color = label.getColor();
var content = [ var content = [
icon.getNode(), icon.getNode(),
item label.getName()
]; ];
return JX.$N('li', item_attrs, content); return JX.$N('li', item_attrs, content);

View file

@ -0,0 +1,35 @@
/**
* @provides javelin-chart-function-label
*/
JX.install('ChartFunctionLabel', {
construct: function(spec) {
this._name = spec.name;
this._color = spec.color;
this._icon = spec.icon;
this._fillColor = spec.fillColor;
},
members: {
_name: null,
_color: null,
_icon: null,
_fillColor: null,
getColor: function() {
return this._color;
},
getName: function() {
return this._name;
},
getIcon: function() {
return this._icon || 'fa-circle';
},
getFillColor: function() {
return this._fillColor;
}
}
});