Mostly working
This commit is contained in:
parent
f3f807d042
commit
74e5a3e868
|
|
@ -61,6 +61,8 @@ def load_examples(sample):
|
||||||
Column("num", Integer),
|
Column("num", Integer),
|
||||||
Column("ds", String(20)),
|
Column("ds", String(20)),
|
||||||
Column("gender", String(10)),
|
Column("gender", String(10)),
|
||||||
|
Column("sum_boys", Integer),
|
||||||
|
Column("sum_girls", Integer),
|
||||||
)
|
)
|
||||||
try:
|
try:
|
||||||
BirthNames.drop(db.engine)
|
BirthNames.drop(db.engine)
|
||||||
|
|
@ -82,7 +84,10 @@ def load_examples(sample):
|
||||||
state=state,
|
state=state,
|
||||||
year=year,
|
year=year,
|
||||||
ds=ds,
|
ds=ds,
|
||||||
name=name, num=num, gender=gender)
|
name=name, num=num, gender=gender,
|
||||||
|
sum_boys=num if gender == 'boy' else 0,
|
||||||
|
sum_girls=num if gender == 'girl' else 0,
|
||||||
|
)
|
||||||
if i % 5000 == 0:
|
if i % 5000 == 0:
|
||||||
print("{} loaded out of 82527 rows".format(i))
|
print("{} loaded out of 82527 rows".format(i))
|
||||||
session.commit()
|
session.commit()
|
||||||
|
|
@ -109,8 +114,11 @@ def load_examples(sample):
|
||||||
obj.main_dttm_col = 'ds'
|
obj.main_dttm_col = 'ds'
|
||||||
obj.default_endpoint = "/panoramix/datasource/table/1/?viz_type=table&granularity=one+day&since=100+years&until=now&row_limit=10&where=&flt_col_0=ds&flt_op_0=in&flt_eq_0=&flt_col_1=ds&flt_op_1=in&flt_eq_1=&slice_name=TEST&datasource_name=birth_names&datasource_id=1&datasource_type=table"
|
obj.default_endpoint = "/panoramix/datasource/table/1/?viz_type=table&granularity=one+day&since=100+years&until=now&row_limit=10&where=&flt_col_0=ds&flt_op_0=in&flt_eq_0=&flt_col_1=ds&flt_op_1=in&flt_eq_1=&slice_name=TEST&datasource_name=birth_names&datasource_id=1&datasource_type=table"
|
||||||
obj.database = dbobj
|
obj.database = dbobj
|
||||||
obj.columns = [models.TableColumn(
|
obj.columns = [
|
||||||
column_name="num", sum=True, type="INTEGER")]
|
models.TableColumn(column_name="num", sum=True, type="INTEGER"),
|
||||||
|
models.TableColumn(column_name="sum_boys", sum=True, type="INTEGER"),
|
||||||
|
models.TableColumn(column_name="sum_girls", sum=True, type="INTEGER"),
|
||||||
|
]
|
||||||
models.Table
|
models.Table
|
||||||
session.add(obj)
|
session.add(obj)
|
||||||
session.commit()
|
session.commit()
|
||||||
|
|
@ -200,7 +208,7 @@ def load_examples(sample):
|
||||||
session.add(slc)
|
session.add(slc)
|
||||||
slices.append(slc)
|
slices.append(slc)
|
||||||
|
|
||||||
slice_name = "States"
|
slice_name = "Gender by State"
|
||||||
slc = session.query(Slice).filter_by(slice_name=slice_name).first()
|
slc = session.query(Slice).filter_by(slice_name=slice_name).first()
|
||||||
if not slc:
|
if not slc:
|
||||||
slc = Slice(
|
slc = Slice(
|
||||||
|
|
@ -210,6 +218,7 @@ def load_examples(sample):
|
||||||
table=tbl,
|
table=tbl,
|
||||||
params=get_slice_json(
|
params=get_slice_json(
|
||||||
slice_name, flt_eq_1="other", viz_type="dist_bar",
|
slice_name, flt_eq_1="other", viz_type="dist_bar",
|
||||||
|
metrics=['sum__sum_girls', 'sum__sum_boys'],
|
||||||
groupby=['state'], flt_op_1='not in', flt_col_1='state'))
|
groupby=['state'], flt_op_1='not in', flt_col_1='state'))
|
||||||
session.add(slc)
|
session.add(slc)
|
||||||
slices.append(slc)
|
slices.append(slc)
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,9 @@
|
||||||
from wtforms import (
|
from wtforms import (
|
||||||
Field, Form, SelectMultipleField, SelectField, TextField, TextAreaField,
|
Field, Form, SelectMultipleField, SelectField, TextField, TextAreaField,
|
||||||
BooleanField, IntegerField)
|
BooleanField, IntegerField, HiddenField)
|
||||||
from copy import copy
|
from copy import copy
|
||||||
|
from panoramix import app
|
||||||
|
config = app.config
|
||||||
|
|
||||||
|
|
||||||
class OmgWtForm(Form):
|
class OmgWtForm(Form):
|
||||||
|
|
@ -27,157 +29,183 @@ class OmgWtForm(Form):
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
|
|
||||||
def form_factory(viz):
|
class FormFactory(object):
|
||||||
datasource = viz.datasource
|
row_limits = [10, 50, 100, 500, 1000, 5000, 10000, 50000]
|
||||||
from panoramix.viz import viz_types
|
|
||||||
row_limits = [10, 50, 100, 500, 1000, 5000, 10000]
|
|
||||||
series_limits = [0, 5, 10, 25, 50, 100, 500]
|
series_limits = [0, 5, 10, 25, 50, 100, 500]
|
||||||
group_by_choices = [(s, s) for s in datasource.groupby_column_names]
|
|
||||||
# Pool of all the fields that can be used in Panoramix
|
def __init__(self, viz):
|
||||||
px_form_fields = {
|
self.viz = viz
|
||||||
'viz_type': SelectField(
|
from panoramix.viz import viz_types
|
||||||
'Viz',
|
viz = self.viz
|
||||||
choices=[(k, v.verbose_name) for k, v in viz_types.items()],
|
datasource = viz.datasource
|
||||||
description="The type of visualization to display"),
|
group_by_choices = [(s, s) for s in datasource.groupby_column_names]
|
||||||
'metrics': SelectMultipleField(
|
# Pool of all the fields that can be used in Panoramix
|
||||||
'Metrics', choices=datasource.metrics_combo,
|
self.field_dict = {
|
||||||
description="One or many metrics to display"),
|
'viz_type': SelectField(
|
||||||
'metric': SelectField(
|
'Viz',
|
||||||
'Metric', choices=datasource.metrics_combo,
|
default='table',
|
||||||
description="One or many metrics to display"),
|
choices=[(k, v.verbose_name) for k, v in viz_types.items()],
|
||||||
'groupby': SelectMultipleField(
|
description="The type of visualization to display"),
|
||||||
'Group by',
|
'metrics': SelectMultipleField(
|
||||||
choices=[(s, s) for s in datasource.groupby_column_names],
|
'Metrics', choices=datasource.metrics_combo,
|
||||||
description="One or many fields to group by"),
|
default=[datasource.metrics_combo[0][0]],
|
||||||
'granularity': TextField(
|
description="One or many metrics to display"),
|
||||||
'Time Granularity', default="one day",
|
'metric': SelectField(
|
||||||
description=(
|
'Metric', choices=datasource.metrics_combo,
|
||||||
"The time granularity for the visualization. Note that you "
|
description="One or many metrics to display"),
|
||||||
"can type and use simple natural language as in '10 seconds', "
|
'groupby': SelectMultipleField(
|
||||||
"'1 day' or '56 weeks'")),
|
'Group by',
|
||||||
'since': TextField(
|
choices=[(s, s) for s in datasource.groupby_column_names],
|
||||||
'Since', default="one day ago", description=(
|
description="One or many fields to group by"),
|
||||||
"Timestamp from filter. This supports free form typing and "
|
'granularity': TextField(
|
||||||
"natural language as in '1 day ago', '28 days' or '3 years'")),
|
'Time Granularity', default="one day",
|
||||||
'until': TextField('Until', default="now"),
|
|
||||||
'row_limit':
|
|
||||||
SelectField(
|
|
||||||
'Row limit', choices=[(s, s) for s in row_limits]),
|
|
||||||
'limit':
|
|
||||||
SelectField(
|
|
||||||
'Series limit', choices=[(s, s) for s in series_limits],
|
|
||||||
description=(
|
description=(
|
||||||
"Limits the number of time series that get displayed")),
|
"The time granularity for the visualization. Note that you "
|
||||||
'rolling_type': SelectField(
|
"can type and use simple natural language as in '10 seconds', "
|
||||||
'Rolling',
|
"'1 day' or '56 weeks'")),
|
||||||
choices=[(s, s) for s in ['mean', 'sum', 'std']],
|
'since': TextField(
|
||||||
description=(
|
'Since', default="one day ago", description=(
|
||||||
"Defines a rolling window function to apply")),
|
"Timestamp from filter. This supports free form typing and "
|
||||||
'rolling_periods': TextField('Periods', description=(
|
"natural language as in '1 day ago', '28 days' or '3 years'")),
|
||||||
"Defines the size of the rolling window function, "
|
'until': TextField('Until', default="now"),
|
||||||
"relative to the 'granularity' field")),
|
'row_limit':
|
||||||
'series': SelectField(
|
SelectField(
|
||||||
'Series', choices=group_by_choices,
|
'Row limit',
|
||||||
description=(
|
default=config.get("ROW_LIMIT"),
|
||||||
"Defines the grouping of entities. "
|
choices=[(s, s) for s in self.row_limits]),
|
||||||
"Each serie is shown as a specific color on the chart and "
|
'limit':
|
||||||
"has a legend toggle")),
|
SelectField(
|
||||||
'entity': SelectField('Entity', choices=group_by_choices,
|
'Series limit', choices=[(s, s) for s in self.series_limits],
|
||||||
description="This define the element to be plotted on the chart"),
|
default=50,
|
||||||
'x': SelectField(
|
description=(
|
||||||
'X Axis', choices=datasource.metrics_combo,
|
"Limits the number of time series that get displayed")),
|
||||||
description="Metric assigned to the [X] axis"),
|
'rolling_type': SelectField(
|
||||||
'y': SelectField('Y Axis', choices=datasource.metrics_combo,
|
'Rolling',
|
||||||
description="Metric assigned to the [Y] axis"),
|
choices=[(s, s) for s in ['mean', 'sum', 'std']],
|
||||||
'size': SelectField('Bubble Size', choices=datasource.metrics_combo),
|
description=(
|
||||||
'where': TextField('Custom WHERE clause'),
|
"Defines a rolling window function to apply")),
|
||||||
'compare_lag': TextField('Comparison Period Lag',
|
'rolling_periods': TextField('Periods', description=(
|
||||||
description="Based on granularity, number of time periods to compare against"),
|
"Defines the size of the rolling window function, "
|
||||||
'compare_suffix': TextField('Comparison suffix',
|
"relative to the 'granularity' field")),
|
||||||
description="Suffix to apply after the percentage display"),
|
'series': SelectField(
|
||||||
'markup_type': SelectField(
|
'Series', choices=group_by_choices,
|
||||||
"Markup Type",
|
description=(
|
||||||
choices=[(s, s) for s in ['markdown', 'html']],
|
"Defines the grouping of entities. "
|
||||||
default="markdown",
|
"Each serie is shown as a specific color on the chart and "
|
||||||
description="Pick your favorite markup language"),
|
"has a legend toggle")),
|
||||||
'rotation': SelectField(
|
'entity': SelectField('Entity', choices=group_by_choices,
|
||||||
"Rotation",
|
description="This define the element to be plotted on the chart"),
|
||||||
choices=[(s, s) for s in ['random', 'flat', 'square']],
|
'x': SelectField(
|
||||||
default="random",
|
'X Axis', choices=datasource.metrics_combo,
|
||||||
description="Rotation to apply to words in the cloud"),
|
description="Metric assigned to the [X] axis"),
|
||||||
'code': TextAreaField("Code", description="Put your code here"),
|
'y': SelectField('Y Axis', choices=datasource.metrics_combo,
|
||||||
'size_from': TextField(
|
description="Metric assigned to the [Y] axis"),
|
||||||
"Font Size From",
|
'size': SelectField('Bubble Size', choices=datasource.metrics_combo),
|
||||||
default="20",
|
'where': TextField('Custom WHERE clause', default=''),
|
||||||
description="Font size for the smallest value in the list"),
|
'compare_lag': TextField('Comparison Period Lag',
|
||||||
'size_to': TextField(
|
description="Based on granularity, number of time periods to compare against"),
|
||||||
"Font Size To",
|
'compare_suffix': TextField('Comparison suffix',
|
||||||
default="150",
|
description="Suffix to apply after the percentage display"),
|
||||||
description="Font size for the biggest value in the list"),
|
'markup_type': SelectField(
|
||||||
'show_brush': BooleanField(
|
"Markup Type",
|
||||||
"Range Selector", default=True,
|
choices=[(s, s) for s in ['markdown', 'html']],
|
||||||
description="Whether to display the time range interactive selector"),
|
default="markdown",
|
||||||
'show_legend': BooleanField(
|
description="Pick your favorite markup language"),
|
||||||
"Legend", default=True, false_values=["f"],
|
'rotation': SelectField(
|
||||||
description="Whether to display the legend (toggles)"),
|
"Rotation",
|
||||||
'rich_tooltip': BooleanField(
|
choices=[(s, s) for s in ['random', 'flat', 'square']],
|
||||||
"Rich Tooltip", default=True,
|
default="random",
|
||||||
description="The rich tooltip shows a list of all series for that point in time"),
|
description="Rotation to apply to words in the cloud"),
|
||||||
'y_axis_zero': BooleanField(
|
'code': TextAreaField("Code", description="Put your code here"),
|
||||||
"Y Axis Zero", default=False,
|
'size_from': TextField(
|
||||||
description="Force the Y axis to start at 0 instead of the minimum value"),
|
"Font Size From",
|
||||||
'y_log_scale': BooleanField(
|
default="20",
|
||||||
"Y Log", default=False,
|
description="Font size for the smallest value in the list"),
|
||||||
description="Use a log scale for the Y axis"),
|
'size_to': TextField(
|
||||||
'x_log_scale': BooleanField(
|
"Font Size To",
|
||||||
"X Log", default=False,
|
default="150",
|
||||||
description="Use a log scale for the X axis"),
|
description="Font size for the biggest value in the list"),
|
||||||
'donut': BooleanField(
|
'show_brush': BooleanField(
|
||||||
"Donut", default=False,
|
"Range Selector", default=True,
|
||||||
description="Do you want a donut or a pie?"),
|
description="Whether to display the time range interactive selector"),
|
||||||
'contribution': BooleanField(
|
'show_legend': BooleanField(
|
||||||
"Contribution", default=False,
|
"Legend", default=True,
|
||||||
description="Compute the contribution to the total"),
|
description="Whether to display the legend (toggles)"),
|
||||||
'num_period_compare': IntegerField(
|
'rich_tooltip': BooleanField(
|
||||||
"Period Ratio", default=None,
|
"Rich Tooltip", default=True,
|
||||||
description=(
|
description="The rich tooltip shows a list of all series for that point in time"),
|
||||||
"Number of period to compare against, "
|
'y_axis_zero': BooleanField(
|
||||||
"this is relative to the granularity selected")),
|
"Y Axis Zero", default=False,
|
||||||
}
|
description="Force the Y axis to start at 0 instead of the minimum value"),
|
||||||
field_css_classes = {k: ['form-control'] for k in px_form_fields.keys()}
|
'y_log_scale': BooleanField(
|
||||||
select2 = [
|
"Y Log", default=False,
|
||||||
'viz_type', 'metrics', 'groupby',
|
description="Use a log scale for the Y axis"),
|
||||||
'row_limit', 'rolling_type', 'series',
|
'x_log_scale': BooleanField(
|
||||||
'entity', 'x', 'y', 'size', 'rotation', 'metric', 'limit',
|
"X Log", default=False,
|
||||||
'markup_type',]
|
description="Use a log scale for the X axis"),
|
||||||
field_css_classes['since'] += ['select2_free_since']
|
'donut': BooleanField(
|
||||||
field_css_classes['until'] += ['select2_free_until']
|
"Donut", default=False,
|
||||||
field_css_classes['granularity'] += ['select2_free_granularity']
|
description="Do you want a donut or a pie?"),
|
||||||
for field in ('show_brush', 'show_legend', 'rich_tooltip'):
|
'contribution': BooleanField(
|
||||||
field_css_classes[field] += ['input-sm']
|
"Contribution", default=False,
|
||||||
for field in select2:
|
description="Compute the contribution to the total"),
|
||||||
field_css_classes[field] += ['select2']
|
'num_period_compare': IntegerField(
|
||||||
|
"Period Ratio", default=None,
|
||||||
|
description=(
|
||||||
|
"Number of period to compare against, "
|
||||||
|
"this is relative to the granularity selected")),
|
||||||
|
}
|
||||||
|
|
||||||
class QueryForm(OmgWtForm):
|
def get_form(self, previous=False):
|
||||||
field_order = copy(viz.form_fields)
|
px_form_fields = self.field_dict
|
||||||
css_classes = field_css_classes
|
viz = self.viz
|
||||||
|
datasource = viz.datasource
|
||||||
|
field_css_classes = {k: ['form-control'] for k in px_form_fields.keys()}
|
||||||
|
select2 = [
|
||||||
|
'viz_type', 'metrics', 'groupby',
|
||||||
|
'row_limit', 'rolling_type', 'series',
|
||||||
|
'entity', 'x', 'y', 'size', 'rotation', 'metric', 'limit',
|
||||||
|
'markup_type',]
|
||||||
|
field_css_classes['since'] += ['select2_free_since']
|
||||||
|
field_css_classes['until'] += ['select2_free_until']
|
||||||
|
field_css_classes['granularity'] += ['select2_free_granularity']
|
||||||
|
for field in ('show_brush', 'show_legend', 'rich_tooltip'):
|
||||||
|
field_css_classes[field] += ['input-sm']
|
||||||
|
for field in select2:
|
||||||
|
field_css_classes[field] += ['select2']
|
||||||
|
|
||||||
for i in range(10):
|
|
||||||
setattr(QueryForm, 'flt_col_' + str(i), SelectField(
|
|
||||||
'Filter 1',
|
|
||||||
choices=[(s, s) for s in datasource.filterable_column_names]))
|
|
||||||
setattr(QueryForm, 'flt_op_' + str(i), SelectField(
|
|
||||||
'Filter 1', choices=[(m, m) for m in ['in', 'not in']]))
|
|
||||||
setattr(QueryForm, 'flt_eq_' + str(i), TextField("Super"))
|
|
||||||
for ff in viz.form_fields:
|
|
||||||
if isinstance(ff, basestring):
|
|
||||||
ff = [ff]
|
|
||||||
for s in ff:
|
|
||||||
if s:
|
|
||||||
setattr(QueryForm, s, px_form_fields[s])
|
|
||||||
|
|
||||||
# datasource type specific form elements
|
class QueryForm(OmgWtForm):
|
||||||
if datasource.__class__.__name__ == 'Table':
|
field_order = copy(viz.form_fields)
|
||||||
QueryForm.field_order += ['where']
|
css_classes = field_css_classes
|
||||||
setattr(QueryForm, 'where', px_form_fields['where'])
|
standalone = HiddenField()
|
||||||
return QueryForm
|
async = HiddenField()
|
||||||
|
json = HiddenField()
|
||||||
|
previous_viz_type = HiddenField()
|
||||||
|
standalone = HiddenField()
|
||||||
|
|
||||||
|
|
||||||
|
for i in range(10):
|
||||||
|
setattr(QueryForm, 'flt_col_' + str(i), SelectField(
|
||||||
|
'Filter 1',
|
||||||
|
default='',
|
||||||
|
choices=[(s, s) for s in datasource.filterable_column_names]))
|
||||||
|
setattr(QueryForm, 'flt_op_' + str(i), SelectField(
|
||||||
|
'Filter 1',
|
||||||
|
default='',
|
||||||
|
choices=[(m, m) for m in ['in', 'not in']]))
|
||||||
|
setattr(
|
||||||
|
QueryForm, 'flt_eq_' + str(i),
|
||||||
|
TextField("Super", default=''))
|
||||||
|
for ff in viz.form_fields:
|
||||||
|
if isinstance(ff, basestring):
|
||||||
|
ff = [ff]
|
||||||
|
for s in ff:
|
||||||
|
if s:
|
||||||
|
setattr(QueryForm, s, px_form_fields[s])
|
||||||
|
|
||||||
|
# datasource type specific form elements
|
||||||
|
if datasource.__class__.__name__ == 'Table':
|
||||||
|
QueryForm.field_order += ['where']
|
||||||
|
setattr(QueryForm, 'where', px_form_fields['where'])
|
||||||
|
return QueryForm
|
||||||
|
|
|
||||||
|
|
@ -123,6 +123,7 @@
|
||||||
<input type="hidden" name="datasource_name" value="{{ datasource.name }}">
|
<input type="hidden" name="datasource_name" value="{{ datasource.name }}">
|
||||||
<input type="hidden" name="datasource_id" value="{{ datasource.id }}">
|
<input type="hidden" name="datasource_id" value="{{ datasource.id }}">
|
||||||
<input type="hidden" name="datasource_type" value="{{ datasource.type }}">
|
<input type="hidden" name="datasource_type" value="{{ datasource.type }}">
|
||||||
|
{{ form.previous_viz_type() }}
|
||||||
</form><br>
|
</form><br>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -132,7 +133,7 @@
|
||||||
<span class="label label-success">
|
<span class="label label-success">
|
||||||
{{ "{0:0.4f}".format(results.duration.total_seconds()) }} s
|
{{ "{0:0.4f}".format(results.duration.total_seconds()) }} s
|
||||||
</span>
|
</span>
|
||||||
<span class="label label-info btn"
|
<span class="label label-info btn"
|
||||||
data-toggle="modal" data-target="#query_modal">query</span>
|
data-toggle="modal" data-target="#query_modal">query</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</h3>
|
</h3>
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
{% if viz.form_data.get("json") == "true" %}
|
{% if viz.form_data.get("json") == "true" %}
|
||||||
{{ viz.get_json() }}
|
{{ viz.get_json() }}
|
||||||
{% else %}
|
{% else %}
|
||||||
{% if viz.form_data.get("standalone") == "true" %}
|
{% if viz.request.args.get("standalone") == "true" %}
|
||||||
{% extends 'panoramix/viz_standalone.html' %}
|
{% extends 'panoramix/viz_standalone.html' %}
|
||||||
{% else %}
|
{% else %}
|
||||||
{% extends 'panoramix/datasource.html' %}
|
{% extends 'panoramix/datasource.html' %}
|
||||||
|
|
@ -16,7 +16,7 @@
|
||||||
|
|
||||||
{% block head_css %}
|
{% block head_css %}
|
||||||
{{super()}}
|
{{super()}}
|
||||||
{% if viz.form_data.get("skip_libs") != "true" %}
|
{% if viz.request.args.get("skip_libs") != "true" %}
|
||||||
{% for css in viz.css_files %}
|
{% for css in viz.css_files %}
|
||||||
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename=css) }}">
|
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename=css) }}">
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
@ -27,11 +27,11 @@
|
||||||
|
|
||||||
{% block tail %}
|
{% block tail %}
|
||||||
{{super()}}
|
{{super()}}
|
||||||
{% if viz.form_data.get("skip_libs") != "true" %}
|
{% if viz.request.args.get("skip_libs") != "true" %}
|
||||||
{% for js in viz.js_files %}
|
{% for js in viz.js_files %}
|
||||||
<script src="{{ url_for('static', filename=js) }}"></script>
|
<script src="{{ url_for('static', filename=js) }}"></script>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
{{ viz_macros.viz_js(viz) }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{{ viz_macros.viz_js(viz) }}
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@
|
||||||
nv.addGraph(function() {
|
nv.addGraph(function() {
|
||||||
// chart_type is {{ viz.chart_type }}
|
// chart_type is {{ viz.chart_type }}
|
||||||
{% if viz.chart_type == 'line' %}
|
{% if viz.chart_type == 'line' %}
|
||||||
{% if viz.form_data.show_brush == 'y' %}
|
{% if viz.form_data.show_brush %}
|
||||||
var chart = nv.models.lineWithFocusChart()
|
var chart = nv.models.lineWithFocusChart()
|
||||||
var xext = chart.xAxis.scale().domain();
|
var xext = chart.xAxis.scale().domain();
|
||||||
chart
|
chart
|
||||||
|
|
@ -52,10 +52,10 @@
|
||||||
chart.xAxis
|
chart.xAxis
|
||||||
.showMaxMin(false)
|
.showMaxMin(false)
|
||||||
.tickFormat(function (d) {return tickMultiFormat(new Date(d)); });
|
.tickFormat(function (d) {return tickMultiFormat(new Date(d)); });
|
||||||
chart.showLegend({{ "{}".format(viz.form_data.show_legend=='y')|lower }});
|
chart.showLegend({{ "{}".format(viz.form_data.show_legend)|lower }});
|
||||||
chart.yAxis.tickFormat(d3.format('.3s'));
|
chart.yAxis.tickFormat(d3.format('.3s'));
|
||||||
|
|
||||||
{% if viz.form_data.contribution=='y' or viz.form_data.get("num_period_compare") %}
|
{% if viz.form_data.contribution or viz.form_data.get("num_period_compare") %}
|
||||||
chart.yAxis.tickFormat(d3.format('.3p'));
|
chart.yAxis.tickFormat(d3.format('.3p'));
|
||||||
chart.y2Axis.tickFormat(d3.format('.3p'));
|
chart.y2Axis.tickFormat(d3.format('.3p'));
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
@ -71,8 +71,8 @@
|
||||||
|
|
||||||
{% elif viz.chart_type == 'pie' %}
|
{% elif viz.chart_type == 'pie' %}
|
||||||
var chart = nv.models.pieChart()
|
var chart = nv.models.pieChart()
|
||||||
chart.showLegend({{ "{}".format(viz.form_data.show_legend=='y')|lower }});
|
chart.showLegend({{ "{}".format(viz.form_data.show_legend)|lower }});
|
||||||
{% if viz.form_data.donut=='y' %}
|
{% if viz.form_data.donut %}
|
||||||
chart.donut(true);
|
chart.donut(true);
|
||||||
chart.donutLabelsOutside(true);
|
chart.donutLabelsOutside(true);
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
@ -91,14 +91,14 @@
|
||||||
chart.xAxis
|
chart.xAxis
|
||||||
.showMaxMin(false)
|
.showMaxMin(false)
|
||||||
.tickFormat(function (d) {return tickMultiFormat(new Date(d)); });
|
.tickFormat(function (d) {return tickMultiFormat(new Date(d)); });
|
||||||
chart.showLegend({{ "{}".format(viz.form_data.show_legend=='y')|lower }});
|
chart.showLegend({{ "{}".format(viz.form_data.show_legend)|lower }});
|
||||||
chart.yAxis.tickFormat(d3.format('.3p'));
|
chart.yAxis.tickFormat(d3.format('.3p'));
|
||||||
|
|
||||||
{% elif viz.chart_type == 'bubble' %}
|
{% elif viz.chart_type == 'bubble' %}
|
||||||
var chart = nv.models.scatterChart();
|
var chart = nv.models.scatterChart();
|
||||||
chart.xAxis.tickFormat(d3.format('.3s'));
|
chart.xAxis.tickFormat(d3.format('.3s'));
|
||||||
chart.yAxis.tickFormat(d3.format('.3s'));
|
chart.yAxis.tickFormat(d3.format('.3s'));
|
||||||
chart.showLegend({{ "{}".format(viz.form_data.show_legend=='y')|lower }});
|
chart.showLegend({{ "{}".format(viz.form_data.show_legend)|lower }});
|
||||||
chart.pointRange([5, 5000]);
|
chart.pointRange([5, 5000]);
|
||||||
|
|
||||||
{% elif viz.chart_type == 'stacked' %}
|
{% elif viz.chart_type == 'stacked' %}
|
||||||
|
|
@ -107,21 +107,21 @@
|
||||||
chart.xAxis
|
chart.xAxis
|
||||||
.showMaxMin(false)
|
.showMaxMin(false)
|
||||||
.tickFormat(function (d) {return tickMultiFormat(new Date(d)); });
|
.tickFormat(function (d) {return tickMultiFormat(new Date(d)); });
|
||||||
chart.showLegend({{ "{}".format(viz.form_data.show_legend=='y')|lower }});
|
chart.showLegend({{ "{}".format(viz.form_data.show_legend)|lower }});
|
||||||
chart.yAxis.tickFormat(d3.format('.3s'));
|
chart.yAxis.tickFormat(d3.format('.3s'));
|
||||||
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% if viz.chart_type in ("line", "stacked") and viz.form_data.rich_tooltip == 'y' %}
|
{% if viz.chart_type in ("line", "stacked") and viz.form_data.rich_tooltip %}
|
||||||
chart.useInteractiveGuideline(true);
|
chart.useInteractiveGuideline(true);
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if viz.form_data.y_axis_zero == 'y' %}
|
{% if viz.form_data.y_axis_zero %}
|
||||||
chart.forceY([0, 1]);
|
chart.forceY([0, 1]);
|
||||||
{% elif viz.form_data.y_log_scale == 'y' %}
|
{% elif viz.form_data.y_log_scale %}
|
||||||
chart.yScale(d3.scale.log());
|
chart.yScale(d3.scale.log());
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% if viz.form_data.x_log_scale == 'y' %}
|
{% if viz.form_data.x_log_scale %}
|
||||||
chart.xScale(d3.scale.log());
|
chart.xScale(d3.scale.log());
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
{% if viz.form_data.get("skip_libs") != "true" %}
|
{% if viz.request.args.get("skip_libs") != "true" %}
|
||||||
{% block head %}
|
{% block head %}
|
||||||
<script src="{{url_for('appbuilder.static',filename='js/jquery-latest.js')}}"></script>
|
<script src="{{url_for('appbuilder.static',filename='js/jquery-latest.js')}}"></script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
{% macro viz_html(viz) %}
|
{% macro viz_html(viz) %}
|
||||||
{% if viz.form_data.get("async") == "true" %}
|
{% if viz.request.args.get("async") == "true" %}
|
||||||
{% set df = viz.get_df() %}
|
{% set df = viz.get_df() %}
|
||||||
<table class="dataframe table table-striped table-bordered table-condensed">
|
<table class="dataframe table table-striped table-bordered table-condensed">
|
||||||
<thead>
|
<thead>
|
||||||
|
|
|
||||||
|
|
@ -3,23 +3,19 @@ from datetime import datetime
|
||||||
import json
|
import json
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
from flask import flash
|
from flask import flash, request
|
||||||
from markdown import markdown
|
from markdown import markdown
|
||||||
from pandas.io.json import dumps
|
from pandas.io.json import dumps
|
||||||
from werkzeug.datastructures import MultiDict
|
from werkzeug.datastructures import ImmutableMultiDict
|
||||||
from werkzeug.urls import Href
|
from werkzeug.urls import Href
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
|
|
||||||
from panoramix import app, utils
|
from panoramix import app, utils
|
||||||
from panoramix.forms import form_factory
|
from panoramix.forms import FormFactory
|
||||||
|
|
||||||
config = app.config
|
config = app.config
|
||||||
|
|
||||||
CHART_ARGS = {
|
|
||||||
'title': None,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class BaseViz(object):
|
class BaseViz(object):
|
||||||
verbose_name = "Base Viz"
|
verbose_name = "Base Viz"
|
||||||
|
|
@ -32,12 +28,26 @@ class BaseViz(object):
|
||||||
|
|
||||||
def __init__(self, datasource, form_data):
|
def __init__(self, datasource, form_data):
|
||||||
self.datasource = datasource
|
self.datasource = datasource
|
||||||
form = self.form_class(form_data)
|
self.request = request
|
||||||
form.validate()
|
|
||||||
raise
|
ff = FormFactory(self)
|
||||||
self.form_data = form_data
|
form_class = ff.get_form()
|
||||||
if isinstance(form_data, MultiDict):
|
defaults = form_class().data.copy()
|
||||||
self.form_data = form_data.to_dict(flat=False)
|
if isinstance(form_data, ImmutableMultiDict):
|
||||||
|
form = form_class(form_data)
|
||||||
|
else:
|
||||||
|
form = form_class(**form_data)
|
||||||
|
data = form.data.copy()
|
||||||
|
previous_viz_type = form_data.get('previous_viz_type')
|
||||||
|
if previous_viz_type in viz_types:
|
||||||
|
data = {
|
||||||
|
k: form.data[k]
|
||||||
|
for k in form_data.keys()
|
||||||
|
if k in viz_types[previous_viz_type].flat_form_fields() and k in form.data}
|
||||||
|
defaults.update(data)
|
||||||
|
self.form_data = defaults
|
||||||
|
|
||||||
|
self.form_data['previous_viz_type'] = form_data.get("viz_type")
|
||||||
self.token = self.form_data.get(
|
self.token = self.form_data.get(
|
||||||
'token', 'token_' + uuid.uuid4().hex[:8])
|
'token', 'token_' + uuid.uuid4().hex[:8])
|
||||||
|
|
||||||
|
|
@ -48,9 +58,19 @@ class BaseViz(object):
|
||||||
elif k not in as_list and isinstance(v, list) and v:
|
elif k not in as_list and isinstance(v, list) and v:
|
||||||
self.form_data[k] = v[0]
|
self.form_data[k] = v[0]
|
||||||
|
|
||||||
self.metrics = self.form_data.get('metrics') or ['count']
|
self.metrics = self.form_data.get('metrics') or []
|
||||||
self.groupby = self.form_data.get('groupby') or []
|
self.groupby = self.form_data.get('groupby') or []
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def flat_form_fields(cls):
|
||||||
|
l = []
|
||||||
|
for obj in cls.form_fields:
|
||||||
|
if isinstance(obj, (tuple, list)):
|
||||||
|
l += [a for a in obj]
|
||||||
|
else:
|
||||||
|
l.append(obj)
|
||||||
|
return l
|
||||||
|
|
||||||
def get_url(self, **kwargs):
|
def get_url(self, **kwargs):
|
||||||
d = self.form_data.copy()
|
d = self.form_data.copy()
|
||||||
if 'action' in d:
|
if 'action' in d:
|
||||||
|
|
@ -80,7 +100,7 @@ class BaseViz(object):
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def form_class(self):
|
def form_class(self):
|
||||||
return form_factory(self)
|
return FormFactory(self).get_form()
|
||||||
|
|
||||||
def query_filters(self):
|
def query_filters(self):
|
||||||
form_data = self.form_data
|
form_data = self.form_data
|
||||||
|
|
@ -334,11 +354,13 @@ class NVD3TimeSeriesViz(NVD3Viz):
|
||||||
form_data = self.form_data
|
form_data = self.form_data
|
||||||
df = super(NVD3TimeSeriesViz, self).get_df()
|
df = super(NVD3TimeSeriesViz, self).get_df()
|
||||||
df = df.fillna(0)
|
df = df.fillna(0)
|
||||||
metrics = self.metrics
|
if form_data.get("granularity") == "all":
|
||||||
|
raise Exception("Pick a time granularity for your time series")
|
||||||
|
|
||||||
df = df.pivot_table(
|
df = df.pivot_table(
|
||||||
index="timestamp",
|
index="timestamp",
|
||||||
columns=self.groupby,
|
columns=self.form_data.get('groupby'),
|
||||||
values=metrics,)
|
values=self.form_data.get('metrics'))
|
||||||
|
|
||||||
if self.sort_series:
|
if self.sort_series:
|
||||||
dfs = df.sum()
|
dfs = df.sum()
|
||||||
|
|
@ -379,7 +401,7 @@ class NVD3TimeSeriesViz(NVD3Viz):
|
||||||
series_title = name
|
series_title = name
|
||||||
else:
|
else:
|
||||||
name = ["{}".format(s) for s in name]
|
name = ["{}".format(s) for s in name]
|
||||||
if len(self.metrics) > 1:
|
if len(self.form_data.get('metrics')) > 1:
|
||||||
series_title = ", ".join(name)
|
series_title = ", ".join(name)
|
||||||
else:
|
else:
|
||||||
series_title = ", ".join(name[1:])
|
series_title = ", ".join(name[1:])
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue