mirror of
https://we.phorge.it/source/phorge.git
synced 2024-12-23 05:50:55 +01:00
Add gRaphael charting library
Summary: I typed up like 30 pages here and then got my soul crushed by T895, but here's the summary: I looked at several charting libraries. There aren't very many that seem to be any good and have an open-source license. I also want the charts to be scriptable in JS so we can add good interactivity where appropriate. Raphael is an SVG drawing library which seems very solid. gRaphael is a charting library on top of Raphael that is a lot less solid, but seems kind of OK. Overall, I think this selection gives us a lot of flexibility, although we'll have to pay some costs up front. I'd rather do that then get limited later, though. That said, I'm open to other suggestions here if anyone has experience or wants to take a different stab at researching things. This is largely for @vii and D1643. Test Plan: Created a basic, fairly OK chart (see next revision). Reviewers: btrahan, vii Reviewed By: btrahan CC: aran, epriestley Differential Revision: https://secure.phabricator.com/D1654
This commit is contained in:
parent
1caa812172
commit
228c3781a2
7 changed files with 98 additions and 30 deletions
10
externals/raphael/g.raphael.js
vendored
Normal file
10
externals/raphael/g.raphael.js
vendored
Normal file
File diff suppressed because one or more lines are too long
10
externals/raphael/g.raphael.line.js
vendored
Normal file
10
externals/raphael/g.raphael.line.js
vendored
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
/**
|
||||||
|
* @provides raphael-g-line
|
||||||
|
*/
|
||||||
|
/*!
|
||||||
|
* g.Raphael 0.5 - Charting library, based on Raphaël
|
||||||
|
*
|
||||||
|
* Copyright (c) 2009 Dmitry Baranovskiy (http://g.raphaeljs.com)
|
||||||
|
* Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) license.
|
||||||
|
*/
|
||||||
|
(function(){function a(g,n){var f=g.length/n,h=0,e=f,m=0,i=[];while(h<g.length){e--;if(e<0){m+=g[h]*(1+e);i.push(m/f);m=g[h++]*-e;e+=f}else{m+=g[h++]}}return i}function d(f,e,p,n,k,j){var h=(p-f)/2,g=(k-p)/2,q=Math.atan((p-f)/Math.abs(n-e)),o=Math.atan((k-p)/Math.abs(n-j));q=e<n?Math.PI-q:q;o=j<n?Math.PI-o:o;var i=Math.PI/2-((q+o)%(Math.PI*2))/2,s=h*Math.sin(i+q),m=h*Math.cos(i+q),r=g*Math.sin(i+o),l=g*Math.cos(i+o);return{x1:p-s,y1:n+m,x2:p+r,y2:n+l}}function b(f,P,O,e,h,A,z,J){var s=this;J=J||{};if(!f.raphael.is(A[0],"array")){A=[A]}if(!f.raphael.is(z[0],"array")){z=[z]}var q=J.gutter||10,B=Math.max(A[0].length,z[0].length),t=J.symbol||"",S=J.colors||s.colors,v=null,p=null,ad=f.set(),T=[];for(var ac=0,L=z.length;ac<L;ac++){B=Math.max(B,z[ac].length)}var ae=f.set();for(ac=0,L=z.length;ac<L;ac++){if(J.shade){ae.push(f.path().attr({stroke:"none",fill:S[ac],opacity:J.nostroke?1:0.3}))}if(z[ac].length>e-2*q){z[ac]=a(z[ac],e-2*q);B=e-2*q}if(A[ac]&&A[ac].length>e-2*q){A[ac]=a(A[ac],e-2*q)}}var W=Array.prototype.concat.apply([],A),U=Array.prototype.concat.apply([],z),u=s.snapEnds(Math.min.apply(Math,W),Math.max.apply(Math,W),A[0].length-1),E=u.from,o=u.to,N=s.snapEnds(Math.min.apply(Math,U),Math.max.apply(Math,U),z[0].length-1),C=N.from,n=N.to,Z=(e-q*2)/((o-E)||1),V=(h-q*2)/((n-C)||1);var G=f.set();if(J.axis){var m=(J.axis+"").split(/[,\s]+/);+m[0]&&G.push(s.axis(P+q,O+q,e-2*q,E,o,J.axisxstep||Math.floor((e-2*q)/20),2,f));+m[1]&&G.push(s.axis(P+e-q,O+h-q,h-2*q,C,n,J.axisystep||Math.floor((h-2*q)/20),3,f));+m[2]&&G.push(s.axis(P+q,O+h-q,e-2*q,E,o,J.axisxstep||Math.floor((e-2*q)/20),0,f));+m[3]&&G.push(s.axis(P+q,O+h-q,h-2*q,C,n,J.axisystep||Math.floor((h-2*q)/20),1,f))}var M=f.set(),aa=f.set(),r;for(ac=0,L=z.length;ac<L;ac++){if(!J.nostroke){M.push(r=f.path().attr({stroke:S[ac],"stroke-width":J.width||2,"stroke-linejoin":"round","stroke-linecap":"round","stroke-dasharray":J.dash||""}))}var g=Raphael.is(t,"array")?t[ac]:t,H=f.set();T=[];for(var ab=0,w=z[ac].length;ab<w;ab++){var l=P+q+((A[ac]||A[0])[ab]-E)*Z,k=O+h-q-(z[ac][ab]-C)*V;(Raphael.is(g,"array")?g[ab]:g)&&H.push(f[Raphael.is(g,"array")?g[ab]:g](l,k,(J.width||2)*3).attr({fill:S[ac],stroke:"none"}));if(J.smooth){if(ab&&ab!=w-1){var R=P+q+((A[ac]||A[0])[ab-1]-E)*Z,F=O+h-q-(z[ac][ab-1]-C)*V,Q=P+q+((A[ac]||A[0])[ab+1]-E)*Z,D=O+h-q-(z[ac][ab+1]-C)*V,af=d(R,F,l,k,Q,D);T=T.concat([af.x1,af.y1,l,k,af.x2,af.y2])}if(!ab){T=["M",l,k,"C",l,k]}}else{T=T.concat([ab?"L":"M",l,k])}}if(J.smooth){T=T.concat([l,k,l,k])}aa.push(H);if(J.shade){ae[ac].attr({path:T.concat(["L",l,O+h-q,"L",P+q+((A[ac]||A[0])[0]-E)*Z,O+h-q,"z"]).join(",")})}!J.nostroke&&r.attr({path:T.join(",")})}function K(an){var ak=[];for(var al=0,ap=A.length;al<ap;al++){ak=ak.concat(A[al])}ak.sort();var aq=[],ah=[];for(al=0,ap=ak.length;al<ap;al++){ak[al]!=ak[al-1]&&aq.push(ak[al])&&ah.push(P+q+(ak[al]-E)*Z)}ak=aq;ap=ak.length;var ag=an||f.set();for(al=0;al<ap;al++){var Y=ah[al]-(ah[al]-(ah[al-1]||P))/2,ao=((ah[al+1]||P+e)-ah[al])/2+(ah[al]-(ah[al-1]||P))/2,x;an?(x={}):ag.push(x=f.rect(Y-1,O,Math.max(ao+1,1),h).attr({stroke:"none",fill:"#000",opacity:0}));x.values=[];x.symbols=f.set();x.y=[];x.x=ah[al];x.axis=ak[al];for(var aj=0,am=z.length;aj<am;aj++){aq=A[aj]||A[0];for(var ai=0,y=aq.length;ai<y;ai++){if(aq[ai]==ak[al]){x.values.push(z[aj][ai]);x.y.push(O+h-q-(z[aj][ai]-C)*V);x.symbols.push(ad.symbols[aj][ai])}}}an&&an.call(x)}!an&&(v=ag)}function I(al){var ah=al||f.set(),x;for(var aj=0,an=z.length;aj<an;aj++){for(var ai=0,ak=z[aj].length;ai<ak;ai++){var ag=P+q+((A[aj]||A[0])[ai]-E)*Z,am=P+q+((A[aj]||A[0])[ai?ai-1:1]-E)*Z,y=O+h-q-(z[aj][ai]-C)*V;al?(x={}):ah.push(x=f.circle(ag,y,Math.abs(am-ag)/2).attr({stroke:"none",fill:"#000",opacity:0}));x.x=ag;x.y=y;x.value=z[aj][ai];x.line=ad.lines[aj];x.shade=ad.shades[aj];x.symbol=ad.symbols[aj][ai];x.symbols=ad.symbols[aj];x.axis=(A[aj]||A[0])[ai];al&&al.call(x)}}!al&&(p=ah)}ad.push(M,ae,aa,G,v,p);ad.lines=M;ad.shades=ae;ad.symbols=aa;ad.axis=G;ad.hoverColumn=function(j,i){!v&&K();v.mouseover(j).mouseout(i);return this};ad.clickColumn=function(i){!v&&K();v.click(i);return this};ad.hrefColumn=function(Y){var ag=f.raphael.is(arguments[0],"array")?arguments[0]:arguments;if(!(arguments.length-1)&&typeof Y=="object"){for(var j in Y){for(var y=0,X=v.length;y<X;y++){if(v[y].axis==j){v[y].attr("href",Y[j])}}}}!v&&K();for(y=0,X=ag.length;y<X;y++){v[y]&&v[y].attr("href",ag[y])}return this};ad.hover=function(j,i){!p&&I();p.mouseover(j).mouseout(i);return this};ad.click=function(i){!p&&I();p.click(i);return this};ad.each=function(i){I(i);return this};ad.eachColumn=function(i){K(i);return this};return ad}var c=function(){};c.prototype=Raphael.g;b.prototype=new c;Raphael.fn.linechart=function(f,k,g,e,j,i,h){return new b(this,f,k,g,e,j,i,h)}})();
|
11
externals/raphael/raphael.js
vendored
Normal file
11
externals/raphael/raphael.js
vendored
Normal file
File diff suppressed because one or more lines are too long
|
@ -330,6 +330,30 @@ celerity_register_resource_map(array(
|
||||||
),
|
),
|
||||||
'disk' => '/rsrc/js/javelin/lib/behavior.js',
|
'disk' => '/rsrc/js/javelin/lib/behavior.js',
|
||||||
),
|
),
|
||||||
|
'javelin-behavior-aphront-drag-and-drop' =>
|
||||||
|
array(
|
||||||
|
'uri' => '/res/ac21045a/rsrc/js/application/core/behavior-drag-and-drop.js',
|
||||||
|
'type' => 'js',
|
||||||
|
'requires' =>
|
||||||
|
array(
|
||||||
|
0 => 'javelin-behavior',
|
||||||
|
1 => 'javelin-dom',
|
||||||
|
2 => 'javelin-util',
|
||||||
|
3 => 'phabricator-drag-and-drop-file-upload',
|
||||||
|
),
|
||||||
|
'disk' => '/rsrc/js/application/core/behavior-drag-and-drop.js',
|
||||||
|
),
|
||||||
|
0 =>
|
||||||
|
array(
|
||||||
|
'uri' => '/res/b6096fdd/rsrc/js/javelin/lib/__tests__/URI.js',
|
||||||
|
'type' => 'js',
|
||||||
|
'requires' =>
|
||||||
|
array(
|
||||||
|
0 => 'javelin-uri',
|
||||||
|
1 => 'javelin-php-serializer',
|
||||||
|
),
|
||||||
|
'disk' => '/rsrc/js/javelin/lib/__tests__/URI.js',
|
||||||
|
),
|
||||||
'javelin-behavior-aphront-basic-tokenizer' =>
|
'javelin-behavior-aphront-basic-tokenizer' =>
|
||||||
array(
|
array(
|
||||||
'uri' => '/res/9be30797/rsrc/js/application/core/behavior-tokenizer.js',
|
'uri' => '/res/9be30797/rsrc/js/application/core/behavior-tokenizer.js',
|
||||||
|
@ -346,19 +370,6 @@ celerity_register_resource_map(array(
|
||||||
),
|
),
|
||||||
'disk' => '/rsrc/js/application/core/behavior-tokenizer.js',
|
'disk' => '/rsrc/js/application/core/behavior-tokenizer.js',
|
||||||
),
|
),
|
||||||
'javelin-behavior-aphront-drag-and-drop' =>
|
|
||||||
array(
|
|
||||||
'uri' => '/res/ac21045a/rsrc/js/application/core/behavior-drag-and-drop.js',
|
|
||||||
'type' => 'js',
|
|
||||||
'requires' =>
|
|
||||||
array(
|
|
||||||
0 => 'javelin-behavior',
|
|
||||||
1 => 'javelin-dom',
|
|
||||||
2 => 'javelin-util',
|
|
||||||
3 => 'phabricator-drag-and-drop-file-upload',
|
|
||||||
),
|
|
||||||
'disk' => '/rsrc/js/application/core/behavior-drag-and-drop.js',
|
|
||||||
),
|
|
||||||
'javelin-behavior-aphront-drag-and-drop-textarea' =>
|
'javelin-behavior-aphront-drag-and-drop-textarea' =>
|
||||||
array(
|
array(
|
||||||
'uri' => '/res/fa7527f9/rsrc/js/application/core/behavior-drag-and-drop-textarea.js',
|
'uri' => '/res/fa7527f9/rsrc/js/application/core/behavior-drag-and-drop-textarea.js',
|
||||||
|
@ -1517,17 +1528,6 @@ celerity_register_resource_map(array(
|
||||||
),
|
),
|
||||||
'disk' => '/rsrc/css/core/remarkup.css',
|
'disk' => '/rsrc/css/core/remarkup.css',
|
||||||
),
|
),
|
||||||
0 =>
|
|
||||||
array(
|
|
||||||
'uri' => '/res/b6096fdd/rsrc/js/javelin/lib/__tests__/URI.js',
|
|
||||||
'type' => 'js',
|
|
||||||
'requires' =>
|
|
||||||
array(
|
|
||||||
0 => 'javelin-uri',
|
|
||||||
1 => 'javelin-php-serializer',
|
|
||||||
),
|
|
||||||
'disk' => '/rsrc/js/javelin/lib/__tests__/URI.js',
|
|
||||||
),
|
|
||||||
'phabricator-search-results-css' =>
|
'phabricator-search-results-css' =>
|
||||||
array(
|
array(
|
||||||
'uri' => '/res/f8a86e27/rsrc/css/application/search/search-results.css',
|
'uri' => '/res/f8a86e27/rsrc/css/application/search/search-results.css',
|
||||||
|
@ -1736,6 +1736,33 @@ celerity_register_resource_map(array(
|
||||||
),
|
),
|
||||||
'disk' => '/rsrc/css/application/projects/project-edit.css',
|
'disk' => '/rsrc/css/application/projects/project-edit.css',
|
||||||
),
|
),
|
||||||
|
'raphael-core' =>
|
||||||
|
array(
|
||||||
|
'uri' => '/res/bae05d27/rsrc/js/raphael/raphael.js',
|
||||||
|
'type' => 'js',
|
||||||
|
'requires' =>
|
||||||
|
array(
|
||||||
|
),
|
||||||
|
'disk' => '/rsrc/js/raphael/raphael.js',
|
||||||
|
),
|
||||||
|
'raphael-g' =>
|
||||||
|
array(
|
||||||
|
'uri' => '/res/8bbdbea8/rsrc/js/raphael/g.raphael.js',
|
||||||
|
'type' => 'js',
|
||||||
|
'requires' =>
|
||||||
|
array(
|
||||||
|
),
|
||||||
|
'disk' => '/rsrc/js/raphael/g.raphael.js',
|
||||||
|
),
|
||||||
|
'raphael-g-line' =>
|
||||||
|
array(
|
||||||
|
'uri' => '/res/54504ae4/rsrc/js/raphael/g.raphael.line.js',
|
||||||
|
'type' => 'js',
|
||||||
|
'requires' =>
|
||||||
|
array(
|
||||||
|
),
|
||||||
|
'disk' => '/rsrc/js/raphael/g.raphael.line.js',
|
||||||
|
),
|
||||||
'syntax-highlighting-css' =>
|
'syntax-highlighting-css' =>
|
||||||
array(
|
array(
|
||||||
'uri' => '/res/5669beb6/rsrc/css/core/syntax.css',
|
'uri' => '/res/5669beb6/rsrc/css/core/syntax.css',
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright 2011 Facebook, Inc.
|
* Copyright 2012 Facebook, Inc.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -130,11 +130,14 @@ class PhabricatorJavelinLinter extends ArcanistLinter {
|
||||||
'@^externals/javelin/src/@',
|
'@^externals/javelin/src/@',
|
||||||
'webroot/rsrc/js/javelin/',
|
'webroot/rsrc/js/javelin/',
|
||||||
$path);
|
$path);
|
||||||
$info = $celerity->lookupFileInformation(substr($path, strlen('webroot')));
|
|
||||||
|
|
||||||
$need = $external_classes;
|
$need = $external_classes;
|
||||||
|
|
||||||
$requires = $info['requires'];
|
$info = $celerity->lookupFileInformation(substr($path, strlen('webroot')));
|
||||||
|
if (!$info) {
|
||||||
|
$info = array();
|
||||||
|
}
|
||||||
|
|
||||||
|
$requires = idx($info, 'requires', array());
|
||||||
|
|
||||||
foreach ($requires as $key => $name) {
|
foreach ($requires as $key => $name) {
|
||||||
$symbol_info = $celerity->lookupSymbolInformation($name);
|
$symbol_info = $celerity->lookupSymbolInformation($name);
|
||||||
|
@ -201,11 +204,16 @@ class PhabricatorJavelinLinter extends ArcanistLinter {
|
||||||
|
|
||||||
private function getUsedAndInstalledSymbolsForPath($path) {
|
private function getUsedAndInstalledSymbolsForPath($path) {
|
||||||
list($symbols) = $this->loadSymbols($path);
|
list($symbols) = $this->loadSymbols($path);
|
||||||
|
$symbols = trim($symbols);
|
||||||
$symbols = explode("\n", trim($symbols));
|
|
||||||
|
|
||||||
$uses = array();
|
$uses = array();
|
||||||
$installs = array();
|
$installs = array();
|
||||||
|
if (empty($symbols)) {
|
||||||
|
// This file has no symbols.
|
||||||
|
return array($uses, $installs);
|
||||||
|
}
|
||||||
|
|
||||||
|
$symbols = explode("\n", trim($symbols));
|
||||||
foreach ($symbols as $line) {
|
foreach ($symbols as $line) {
|
||||||
$matches = null;
|
$matches = null;
|
||||||
if (!preg_match('/^([?+])([^:]*):(\d+)$/', $line, $matches)) {
|
if (!preg_match('/^([?+])([^:]*):(\d+)$/', $line, $matches)) {
|
||||||
|
|
|
@ -15,6 +15,7 @@ phutil_require_module('phutil', 'filesystem');
|
||||||
phutil_require_module('phutil', 'future');
|
phutil_require_module('phutil', 'future');
|
||||||
phutil_require_module('phutil', 'future/exec');
|
phutil_require_module('phutil', 'future/exec');
|
||||||
phutil_require_module('phutil', 'moduleutils');
|
phutil_require_module('phutil', 'moduleutils');
|
||||||
|
phutil_require_module('phutil', 'utils');
|
||||||
|
|
||||||
|
|
||||||
phutil_require_source('PhabricatorJavelinLinter.php');
|
phutil_require_source('PhabricatorJavelinLinter.php');
|
||||||
|
|
1
webroot/rsrc/js/raphael
Symbolic link
1
webroot/rsrc/js/raphael
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
../../../externals/raphael/
|
Loading…
Reference in a new issue