提交 495c2dfe 编写于 作者: M Maxime Beauchemin

Ripping highcharts out

上级 bf8ce171
......@@ -137,3 +137,15 @@ More screenshots
![img](http://i.imgur.com/t7VOtqQ.png)
![img](http://i.imgur.com/PaiFQnH.png)
![img](http://i.imgur.com/CdcGHuC.png)
Tip of the Hat
--------------
Panoramix would not be possible without these great frameworks / libs
* Flask App Builder - Allowing us to focus on building the app quickly while
getting the foundation for free
* The Flask ecosystem - Simply amazing. So much Plug, easy play.
* NVD3 - One of the best charting library out there
* Much more, check out the requirements.txt file!
# TODO
* Add a per-datasource permission
List of TODO items for Panoramix
* in/notin filters autocomplete
* DRUID: Allow for post aggregations (ratios!)
* compare time ranges
* csv export out of table view
* SQL: Find a way to manage granularity
* Create ~/.panoramix/ to host DB and config, generate default config there
## Improvments
* Reintroduce query and stopwatch
* Sort tooltip
* Make "Test Connection" test further
* Consistent colors for same entities
* Contribution to total
* Arbitrary expressions
* Group bucketing
* ToT
* Layers
* [druid] Allow for post aggregations (ratios!)
* [sql] find a way to manage time granularity
* [sql] support arbitrary expression as column
* [sql] define column based grouping
* [sql] make "Test Connection" test further
* csv export out of table view
* in/notin filters autocomplete
## Test
* Line types
* Intelligence around series name
* Shapes
* Line highlighting - draw attention
## First Class Line Charts
* Contribution to total
* Time comparison
* Time ratios
* Use legend shapes that match line markers (useful?)
* Hover line highlighting
* More colors! the Airbnb palette is currently pretty limited
* Line types (dash, dotted)
## Bug
## New Features
* Annotations layers
* Add a per-datasource permission
......@@ -219,11 +219,11 @@ def load_examples(sample):
if not slc:
slc = Slice(
slice_name=slice_name,
viz_type='nvd3_line',
viz_type='line',
datasource_type='table',
table=tbl,
params=get_slice_json(
slice_name, viz_type="nvd3_line", groupby=['name'],
slice_name, viz_type="line", groupby=['name'],
granularity='1 day', rich_tooltip='y', show_legend='y'))
session.add(slc)
slices.append(slc)
......
......@@ -76,10 +76,19 @@ def form_factory(viz):
'rolling_periods': TextField('Periods', description=(
"Defines the size of the rolling window function, "
"relative to the 'granularity' field")),
'series': SelectField('Series', choices=group_by_choices),
'entity': SelectField('Entity', choices=group_by_choices),
'x': SelectField('X Axis', choices=datasource.metrics_combo),
'y': SelectField('Y Axis', choices=datasource.metrics_combo),
'series': SelectField(
'Series', choices=group_by_choices,
description=(
"Defines the grouping of entities. "
"Each serie is shown as a specific color on the chart and "
"has a legend toggle")),
'entity': SelectField('Entity', choices=group_by_choices,
description="This define the element to be plotted on the chart"),
'x': SelectField(
'X Axis', choices=datasource.metrics_combo,
description="Metric assigned to the [X] axis"),
'y': SelectField('Y Axis', choices=datasource.metrics_combo,
description="Metric assigned to the [Y] axis"),
'size': SelectField('Bubble Size', choices=datasource.metrics_combo),
'where': TextField('Custom WHERE clause'),
'compare_lag': TextField('Comparison Period Lag',
......@@ -120,6 +129,9 @@ def form_factory(viz):
'y_log_scale': BooleanField(
"Y Log", default=False,
description="Use a log scale for the Y axis"),
'x_log_scale': BooleanField(
"X Log", default=False,
description="Use a log scale for the X axis"),
'donut': BooleanField(
"Donut", default=False,
description="Do you want a donut or a pie?"),
......
此差异已折叠。
此差异已折叠。
因为 它太大了无法显示 source diff 。你可以改为 查看blob
......@@ -197,6 +197,7 @@
}
.nvd3 .nv-groups path.nv-line {
fill: none;
stroke-width: 2px;
}
.nvd3 .nv-groups path.nv-area {
......
input[type="checkbox"] {
display: inline-block;
width: 16px;
height: 16px;
float: right;
}
form div {
padding-top: 1px;
}
{% macro viz_html(viz) %}
<div id="{{ viz.token }}" style="height:100%; width: 100%">
<img src="{{ url_for("static", filename="loading.gif") }}" class="loading">
<div class="chart" style="height:100%; width: 100%"></div>
<div class="chart with-3d-shadow with-transitions" style="height:100%; width: 100%"></div>
</div>
{% endmacro %}
......@@ -47,7 +47,6 @@
{% else %}
var chart = nv.models.lineChart()
{% endif %}
chart.xScale(d3.time.scale());
chart.xAxis
.showMaxMin(false)
......@@ -59,11 +58,11 @@
var chart = nv.models.multiBarChart()
.showControls(true) //Allow user to switch between 'Grouped' and 'Stacked' mode.
.groupSpacing(0.1); //Distance between each group of bars.
chart.xAxis
.showMaxMin(false)
.tickFormat(function (d) {return tickMultiFormat(UTC(new Date(d))); });
chart.yAxis.tickFormat(d3.format('.3s'));
{% elif viz.chart_type == 'pie' %}
var chart = nv.models.pieChart()
chart.showLegend({{ "{}".format(viz.args.show_legend=='y')|lower }});
......@@ -73,9 +72,18 @@
{% endif %}
chart.labelsOutside(true);
chart.cornerRadius(true);
{% elif viz.chart_type == 'column' %}
var chart = nv.models.multiBarChart();
chart.yAxis.tickFormat(d3.format('.3s'));
{% elif viz.chart_type == 'bubble' %}
var chart = nv.models.scatterChart();
chart.xAxis.tickFormat(d3.format('.3s'));
chart.yAxis.tickFormat(d3.format('.3s'));
chart.showLegend({{ "{}".format(viz.args.show_legend=='y')|lower }});
chart.pointRange([5, 5000]);
{% elif viz.chart_type == 'stacked' %}
var chart = nv.models.stackedAreaChart();
chart.xScale(d3.time.scale());
......@@ -84,6 +92,7 @@
.tickFormat(function (d) {return tickMultiFormat(new Date(d)); });
chart.showLegend({{ "{}".format(viz.args.show_legend=='y')|lower }});
chart.yAxis.tickFormat(d3.format('.3s'));
{% endif %}
{% if viz.chart_type == "nvd3_line" and viz.args.rich_tooltip == 'y' %}
......@@ -95,6 +104,10 @@
chart.yScale(d3.scale.log());
{% endif %}
{% if viz.args.x_log_scale == 'y' %}
chart.xScale(d3.scale.log());
{% endif %}
token.select('.chart').append("svg")
.datum(data)
......
from collections import OrderedDict
from collections import OrderedDict, defaultdict
from datetime import datetime
import json
import uuid
......@@ -12,7 +12,6 @@ import numpy as np
import pandas as pd
from panoramix import app, utils
from panoramix.highchart import Highchart, HighchartBubble
from panoramix.forms import form_factory
config = app.config
......@@ -218,23 +217,18 @@ class NVD3Viz(BaseViz):
css_files = ['nv.d3.css']
class HighchartsViz(BaseViz):
verbose_name = "Base Highcharts Viz"
template = 'panoramix/viz_highcharts.html'
chart_kind = 'line'
chart_call = "Chart"
stacked = False
compare = False
js_files = ['highstock.js']
class BubbleViz(HighchartsViz):
class BubbleViz(NVD3Viz):
verbose_name = "Bubble Chart"
chart_type = 'bubble'
form_fields = [
'viz_type', 'since', 'until',
'series', 'entity', 'x', 'y', 'size', 'limit']
js_files = ['highstock.js', 'highcharts-more.js']
'viz_type',
('since', 'until'),
('series', 'entity'),
('x', 'y'),
('size', 'limit'),
('x_log_scale', 'y_log_scale'),
('show_legend', None),
]
def query_obj(self):
args = self.form_data
......@@ -263,15 +257,23 @@ class BubbleViz(HighchartsViz):
df = df.fillna(0)
df['x'] = df[[self.x_metric]]
df['y'] = df[[self.y_metric]]
df['z'] = df[[self.z_metric]]
df['name'] = df[[self.entity]]
df['size'] = df[[self.z_metric]]
df['shape'] = 'circle'
df['group'] = df[[self.series]]
return df
def get_json(self):
df = self.get_df()
chart = HighchartBubble(df)
return chart.json
series = defaultdict(list)
for row in df.to_dict(orient='records'):
series[row['group']].append(row)
data = []
for k, v in series.items():
data.append({
'key': k,
"color": utils.color(k),
'values': v })
return json.dumps(data)
class BigNumberViz(BaseViz):
verbose_name = "Big Number"
......@@ -310,52 +312,6 @@ class BigNumberViz(BaseViz):
return json.dumps(d)
class TimeSeriesViz(HighchartsViz):
verbose_name = "Time Series - Line Chart"
chart_type = "spline"
chart_call = "StockChart"
sort_legend_y = True
js_files = ['highstock.js', 'highcharts-more.js']
form_fields = [
'viz_type',
'granularity', ('since', 'until'),
'metrics',
'groupby', 'limit',
('rolling_type', 'rolling_periods'),
]
def get_df(self):
args = self.args
df = super(TimeSeriesViz, self).get_df()
metrics = self.metrics
df = df.pivot_table(
index="timestamp",
columns=self.groupby,
values=metrics,)
rolling_periods = args.get("rolling_periods")
rolling_type = args.get("rolling_type")
if rolling_periods and rolling_type:
if rolling_type == 'mean':
df = pd.rolling_mean(df, int(rolling_periods))
elif rolling_type == 'std':
df = pd.rolling_std(df, int(rolling_periods))
elif rolling_type == 'sum':
df = pd.rolling_sum(df, int(rolling_periods))
return df
def get_json(self):
df = self.get_df()
chart = Highchart(
df,
compare=self.compare,
chart_type=self.chart_type,
stacked=self.stacked,
sort_legend_y=self.sort_legend_y,
**CHART_ARGS)
return chart.json
class NVD3TimeSeriesViz(NVD3Viz):
verbose_name = "NVD3 - Time Series - Line Chart"
chart_type = "nvd3_line"
......@@ -441,39 +397,14 @@ class NVD3TimeSeriesStackedViz(NVD3TimeSeriesViz):
]
class TimeSeriesCompareViz(TimeSeriesViz):
verbose_name = "Time Series - Percent Change"
compare = 'percent'
class TimeSeriesCompareValueViz(TimeSeriesViz):
verbose_name = "Time Series - Value Change"
compare = 'value'
class TimeSeriesAreaViz(TimeSeriesViz):
verbose_name = "Time Series - Stacked Area Chart"
stacked = True
chart_type = "area"
class TimeSeriesBarViz(TimeSeriesViz):
verbose_name = "Time Series - Bar Chart"
chart_type = "column"
class TimeSeriesStackedBarViz(TimeSeriesViz):
verbose_name = "Time Series - Stacked Bar Chart"
chart_type = "column"
stacked = True
class DistributionPieViz(NVD3Viz):
verbose_name = "Distribution - NVD3 - Pie Chart"
chart_type = "pie"
form_fields = [
'viz_type', 'metrics', 'groupby',
('since', 'until'), 'limit',
('since', 'until'),
'limit',
('donut', 'show_legend'),
]
def query_obj(self):
......@@ -503,7 +434,7 @@ class DistributionBarViz(DistributionPieViz):
chart_type = "column"
def get_df(self):
df = super(DistributionPieViz, self).get_df()
df = super(DistributionBarViz, self).get_df()
df = df.pivot_table(
index=self.groupby,
values=self.metrics)
......@@ -537,16 +468,12 @@ class DistributionBarViz(DistributionPieViz):
viz_types = OrderedDict([
['table', TableViz],
['nvd3_line', NVD3TimeSeriesViz],
['nvd3_bar', NVD3TimeSeriesBarViz],
['line', NVD3TimeSeriesViz],
['stacked', NVD3TimeSeriesStackedViz],
['line', TimeSeriesViz],
['big_number', BigNumberViz],
['compare', TimeSeriesCompareViz],
['compare_value', TimeSeriesCompareValueViz],
['area', TimeSeriesAreaViz],
['bar', TimeSeriesBarViz],
['stacked_ts_bar', TimeSeriesStackedBarViz],
#['compare', TimeSeriesCompareViz], # TODO replace
#['area', TimeSeriesAreaViz], # TODO replace
['bar', NVD3TimeSeriesBarViz],
['dist_bar', DistributionBarViz],
['pie', DistributionPieViz],
['bubble', BubbleViz],
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册