Merge pull request #74 from mistercrunch/fieldsets
Introducing fieldsets
This commit is contained in:
commit
021654cdf1
|
|
@ -38,19 +38,9 @@ class BetterSelectMultipleField(SelectMultipleField):
|
|||
|
||||
|
||||
class OmgWtForm(Form):
|
||||
field_order = tuple()
|
||||
fieldsets = {}
|
||||
css_classes = dict()
|
||||
|
||||
@property
|
||||
def fields(self):
|
||||
fields = []
|
||||
for field in self.field_order:
|
||||
if hasattr(self, field):
|
||||
obj = getattr(self, field)
|
||||
if isinstance(obj, Field):
|
||||
fields.append(getattr(self, field))
|
||||
return fields
|
||||
|
||||
def get_field(self, fieldname):
|
||||
return getattr(self, fieldname)
|
||||
|
||||
|
|
@ -179,7 +169,7 @@ class FormFactory(object):
|
|||
default="random",
|
||||
description="Rotation to apply to words in the cloud"),
|
||||
'line_interpolation': SelectField(
|
||||
"Line Interpolation",
|
||||
"Line Style",
|
||||
choices=self.choicify([
|
||||
'linear', 'basis', 'cardinal', 'monotone',
|
||||
'step-before', 'step-after']),
|
||||
|
|
@ -204,7 +194,7 @@ class FormFactory(object):
|
|||
default="150",
|
||||
description="Font size for the biggest value in the list"),
|
||||
'show_brush': BetterBooleanField(
|
||||
"Range Selector", default=True,
|
||||
"Range Filter", default=True,
|
||||
description=(
|
||||
"Whether to display the time range interactive selector")),
|
||||
'show_legend': BetterBooleanField(
|
||||
|
|
@ -239,7 +229,7 @@ class FormFactory(object):
|
|||
"[integer] Number of period to compare against, "
|
||||
"this is relative to the granularity selected")),
|
||||
'time_compare': TextField(
|
||||
"Time Shift Compare",
|
||||
"Time Shift",
|
||||
default="",
|
||||
description=(
|
||||
"Overlay a timeseries from a "
|
||||
|
|
@ -278,7 +268,7 @@ class FormFactory(object):
|
|||
field_css_classes[field] += ['select2Sortable']
|
||||
|
||||
class QueryForm(OmgWtForm):
|
||||
field_order = copy(viz.form_fields)
|
||||
fieldsets = copy(viz.fieldsetizer())
|
||||
css_classes = field_css_classes
|
||||
standalone = HiddenField()
|
||||
async = HiddenField()
|
||||
|
|
@ -286,6 +276,7 @@ class FormFactory(object):
|
|||
slice_id = HiddenField()
|
||||
slice_name = HiddenField()
|
||||
previous_viz_type = HiddenField(default=viz.viz_type)
|
||||
collapsed_fieldsets = HiddenField()
|
||||
|
||||
filter_cols = datasource.filterable_column_names or ['']
|
||||
for i in range(10):
|
||||
|
|
@ -300,23 +291,24 @@ class FormFactory(object):
|
|||
setattr(
|
||||
QueryForm, 'flt_eq_' + str(i),
|
||||
TextField("Super", default=''))
|
||||
for ff in viz.form_fields:
|
||||
if isinstance(ff, string_types):
|
||||
ff = [ff]
|
||||
for s in ff:
|
||||
if s:
|
||||
setattr(QueryForm, s, px_form_fields[s])
|
||||
for fieldset in viz.fieldsetizer():
|
||||
for ff in fieldset['fields']:
|
||||
if isinstance(ff, string_types):
|
||||
ff = [ff]
|
||||
for s in ff:
|
||||
if s:
|
||||
setattr(QueryForm, s, px_form_fields[s])
|
||||
|
||||
# datasource type specific form elements
|
||||
if datasource.__class__.__name__ == 'SqlaTable':
|
||||
QueryForm.field_order += ['where', 'having']
|
||||
QueryForm.fieldsets += (
|
||||
{'label': 'SQL', 'fields': ['where', 'having']},)
|
||||
setattr(QueryForm, 'where', px_form_fields['where'])
|
||||
setattr(QueryForm, 'having', px_form_fields['having'])
|
||||
|
||||
if 'granularity' in viz.form_fields:
|
||||
if 'granularity' in viz.flat_form_fields():
|
||||
setattr(
|
||||
QueryForm,
|
||||
'granularity', px_form_fields['granularity_sqla'])
|
||||
field_css_classes['granularity'] = ['form-control', 'select2']
|
||||
|
||||
return QueryForm
|
||||
|
|
|
|||
|
|
@ -10,6 +10,34 @@ form div {
|
|||
.navbar-brand a {
|
||||
color: white;
|
||||
}
|
||||
fieldset.fs-style {
|
||||
font-family: Verdana, Arial, sans-serif;
|
||||
font-size: small;
|
||||
font-weight: normal;
|
||||
border: 1px solid #CCC;
|
||||
background-color: #F4F4F4;
|
||||
border-radius: 6px;
|
||||
padding: 10px;
|
||||
margin: 10px 0px;
|
||||
}
|
||||
legend.legend-style {
|
||||
font-size: 14px;
|
||||
padding: 0px 6px;
|
||||
cursor: pointer;
|
||||
margin: 0px;
|
||||
color: #444;
|
||||
background-color: transparent;
|
||||
font-weight: bold;
|
||||
}
|
||||
.nvtooltip{
|
||||
position: relative; !important
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
legend {
|
||||
width: auto;
|
||||
border-bottom: 0px;
|
||||
}
|
||||
.navbar {
|
||||
-webkit-box-shadow: 0px 3px 3px #AAA;
|
||||
-moz-box-shadow: 0px 3px 3px #AAA;
|
||||
|
|
|
|||
|
|
@ -22,57 +22,74 @@
|
|||
|
||||
<hr>
|
||||
<form id="query" method="GET" style="display: none;">
|
||||
{% for fieldname in form.field_order %}
|
||||
{% if not fieldname.__iter__ %}
|
||||
<div>
|
||||
{% set field = form.get_field(fieldname)%}
|
||||
<div>
|
||||
{{ field.label }}
|
||||
{% if field.description %}
|
||||
<i class="fa fa-info-circle" data-toggle="tooltip" data-placement="right"
|
||||
title="{{ field.description }}"></i>
|
||||
{% endif %}:
|
||||
{{ field(class_=form.field_css_classes(field.name)) }}
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="row">
|
||||
<div class="form-group">
|
||||
{% for name in fieldname %}
|
||||
<div class="col-xs-{{ (12 / fieldname|length) | int }}">
|
||||
{% if name %}
|
||||
{% set field = form.get_field(name)%}
|
||||
{{ field.label }}
|
||||
{% if field.description %}
|
||||
<i class="fa fa-info-circle" data-toggle="tooltip" data-placement="right"
|
||||
title="{{ field.description }}"></i>
|
||||
{% endif %}:
|
||||
{{ field(class_=form.field_css_classes(field.name)) }}
|
||||
{% for fieldset in form.fieldsets %}
|
||||
<fieldset class="fs-style">
|
||||
{% if fieldset.label %}
|
||||
<legend class="legend-style">
|
||||
<span class="legend_label">{{ fieldset.label }}</span>
|
||||
<span class="collapser"> [-]</span>
|
||||
</legend>
|
||||
{% endif %}
|
||||
<div class="fieldset_content">
|
||||
{% for fieldname in fieldset.fields %}
|
||||
{% if not fieldname.__iter__ %}
|
||||
<div>
|
||||
{% set field = form.get_field(fieldname)%}
|
||||
<div>
|
||||
{{ field.label }}
|
||||
{% if field.description %}
|
||||
<i class="fa fa-info-circle" data-toggle="tooltip" data-placement="right"
|
||||
title="{{ field.description }}"></i>
|
||||
{% endif %}
|
||||
{{ field(class_=form.field_css_classes(field.name)) }}
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="row">
|
||||
<div class="form-group">
|
||||
{% for name in fieldname %}
|
||||
<div class="col-xs-{{ (12 / fieldname|length) | int }}">
|
||||
{% if name %}
|
||||
{% set field = form.get_field(name)%}
|
||||
{{ field.label }}
|
||||
{% if field.description %}
|
||||
<i class="fa fa-info-circle" data-toggle="tooltip" data-placement="right"
|
||||
title="{{ field.description }}"></i>
|
||||
{% endif %}
|
||||
{{ field(class_=form.field_css_classes(field.name)) }}
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</fieldset>
|
||||
{% endfor %}
|
||||
<hr>
|
||||
<h4>Filters</h4>
|
||||
<div id="flt0" style="display: none;">
|
||||
<span class="">{{ form.flt_col_0(class_="form-control inc") }}</span>
|
||||
<div class="row">
|
||||
<span class="col col-sm-4">{{ form.flt_op_0(class_="form-control inc") }}</span>
|
||||
<span class="col col-sm-6">{{ form.flt_eq_0(class_="form-control inc") }}</span>
|
||||
<button type="button" class="btn btn-sm remove" aria-label="Delete filter">
|
||||
<span class="glyphicon glyphicon-minus" aria-hidden="true"></span>
|
||||
<fieldset class="fs-style">
|
||||
<legend class="legend-style">
|
||||
<span class="legend_label">Filters</span>
|
||||
<span class="collapser"> [-]</span>
|
||||
</legend>
|
||||
<div class="fieldset_content">
|
||||
<div id="flt0" style="display: none;">
|
||||
<span class="">{{ form.flt_col_0(class_="form-control inc") }}</span>
|
||||
<div class="row">
|
||||
<span class="col col-sm-4">{{ form.flt_op_0(class_="form-control inc") }}</span>
|
||||
<span class="col col-sm-6">{{ form.flt_eq_0(class_="form-control inc") }}</span>
|
||||
<button type="button" class="btn btn-sm remove" aria-label="Delete filter">
|
||||
<span class="glyphicon glyphicon-minus" aria-hidden="true"></span>
|
||||
</button>
|
||||
</div>
|
||||
<hr style="margin: 5px 0px;"/>
|
||||
</div>
|
||||
<div id="filters"></div>
|
||||
<button type="button" id="plus" class="btn btn-sm" aria-label="Add a filter">
|
||||
<span class="glyphicon glyphicon-plus" aria-hidden="true"></span>
|
||||
</button>
|
||||
</div>
|
||||
<hr style="margin: 5px 0px;"/>
|
||||
</div>
|
||||
<div id="filters"></div>
|
||||
<button type="button" id="plus" class="btn btn-sm" aria-label="Add a filter">
|
||||
<span class="glyphicon glyphicon-plus" aria-hidden="true"></span>
|
||||
</button>
|
||||
<hr>
|
||||
</fieldset>
|
||||
<button type="button" class="btn btn-primary druidify">
|
||||
<i class="fa fa-bolt"></i>
|
||||
Slice!
|
||||
|
|
@ -91,6 +108,7 @@
|
|||
<img src="{{ url_for("static", filename="img/tux_panoramix.png") }}" width=250>
|
||||
{{ form.slice_id() }}
|
||||
{{ form.slice_name() }}
|
||||
{{ form.collapsed_fieldsets() }}
|
||||
<input type="hidden" name="action" id="action" value="">
|
||||
<input type="hidden" name="datasource_name" value="{{ datasource.name }}">
|
||||
<input type="hidden" name="datasource_id" value="{{ datasource.id }}">
|
||||
|
|
@ -161,6 +179,57 @@
|
|||
var widget = px.initializeWidget(data);
|
||||
$('.widget').data('widget', widget);
|
||||
widget.render();
|
||||
|
||||
function get_collapsed_fieldsets(){
|
||||
collapsed_fieldsets = $("#collapsed_fieldsets").val()
|
||||
if (collapsed_fieldsets != undefined && collapsed_fieldsets != "")
|
||||
collapsed_fieldsets = collapsed_fieldsets.split('||');
|
||||
else
|
||||
collapsed_fieldsets = [];
|
||||
return collapsed_fieldsets;
|
||||
}
|
||||
|
||||
function toggle_fieldset(legend, animation) {
|
||||
var parent = legend.parent();
|
||||
fieldset = parent.find(".legend_label").text();
|
||||
collapsed_fieldsets = get_collapsed_fieldsets();
|
||||
|
||||
if (!parent.hasClass("collapsed")){
|
||||
if (animation)
|
||||
parent.find(".fieldset_content").slideUp();
|
||||
else
|
||||
parent.find(".fieldset_content").hide();
|
||||
|
||||
parent.addClass("collapsed");
|
||||
parent.find("span.collapser").text("[+]");
|
||||
var index = collapsed_fieldsets.indexOf(fieldset);
|
||||
if (index === -1 && fieldset !== "" && fieldset !== undefined) {
|
||||
collapsed_fieldsets.push(fieldset);
|
||||
}
|
||||
} else {
|
||||
if (animation)
|
||||
parent.find(".fieldset_content").slideDown();
|
||||
else
|
||||
parent.find(".fieldset_content").show();
|
||||
parent.removeClass("collapsed");
|
||||
parent.find("span.collapser").text("[-]");
|
||||
|
||||
// removing from array, js is overcomplicated
|
||||
var index = collapsed_fieldsets.indexOf(fieldset);
|
||||
if (index !== -1) {
|
||||
collapsed_fieldsets.splice(index, 1);
|
||||
}
|
||||
}
|
||||
$("#collapsed_fieldsets").val(collapsed_fieldsets.join("||"));
|
||||
}
|
||||
|
||||
$('legend').click(function () {
|
||||
toggle_fieldset($(this), true);
|
||||
});
|
||||
collapsed_fieldsets = get_collapsed_fieldsets();
|
||||
for(var i=0; i<collapsed_fieldsets.length;i++){
|
||||
toggle_fieldset($('legend:contains("' + collapsed_fieldsets[i] + '")'), false);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
|
|
|||
|
|
@ -335,7 +335,7 @@ class Panoramix(BaseView):
|
|||
d = request.args.to_dict(flat=False)
|
||||
del d['action']
|
||||
del d['previous_viz_type']
|
||||
as_list = ('metrics', 'groupby')
|
||||
as_list = ('metrics', 'groupby', 'columns')
|
||||
for k in d:
|
||||
v = d.get(k)
|
||||
if k in as_list and not isinstance(v, list):
|
||||
|
|
|
|||
276
panoramix/viz.py
276
panoramix/viz.py
|
|
@ -24,12 +24,16 @@ class BaseViz(object):
|
|||
verbose_name = "Base Viz"
|
||||
template = None
|
||||
is_timeseries = False
|
||||
form_fields = [
|
||||
'viz_type',
|
||||
'granularity',
|
||||
('since', 'until'),
|
||||
'metrics', 'groupby',
|
||||
]
|
||||
fieldsets = (
|
||||
{
|
||||
'label': None,
|
||||
'fields': (
|
||||
'viz_type',
|
||||
'granularity',
|
||||
('since', 'until'),
|
||||
'metrics', 'groupby',
|
||||
)
|
||||
},)
|
||||
js_files = []
|
||||
css_files = []
|
||||
|
||||
|
|
@ -70,14 +74,22 @@ class BaseViz(object):
|
|||
self.groupby = self.form_data.get('groupby') or []
|
||||
self.reassignments()
|
||||
|
||||
def fieldsetizer(self):
|
||||
"""
|
||||
Makes form_fields support either a list approach or a fieldsets
|
||||
approach
|
||||
"""
|
||||
return self.fieldsets
|
||||
|
||||
@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)
|
||||
l = set()
|
||||
for d in cls.fieldsets:
|
||||
for obj in d['fields']:
|
||||
if isinstance(obj, (tuple, list)):
|
||||
l |= {a for a in obj}
|
||||
else:
|
||||
l.add(obj)
|
||||
return l
|
||||
|
||||
def reassignments(self):
|
||||
|
|
@ -198,7 +210,17 @@ class TableViz(BaseViz):
|
|||
viz_type = "table"
|
||||
verbose_name = "Table View"
|
||||
template = 'panoramix/viz_table.html'
|
||||
form_fields = BaseViz.form_fields + ['row_limit']
|
||||
fieldsets = (
|
||||
{
|
||||
'label': None,
|
||||
'fields': (
|
||||
'viz_type',
|
||||
'granularity',
|
||||
('since', 'until'),
|
||||
'metrics', 'groupby',
|
||||
'row_limit'
|
||||
)
|
||||
},)
|
||||
css_files = ['lib/dataTables/dataTables.bootstrap.css']
|
||||
is_timeseries = False
|
||||
js_files = [
|
||||
|
|
@ -231,21 +253,29 @@ class PivotTableViz(BaseViz):
|
|||
js_files = [
|
||||
'lib/dataTables/jquery.dataTables.min.js',
|
||||
'lib/dataTables/dataTables.bootstrap.js']
|
||||
form_fields = [
|
||||
'viz_type',
|
||||
'granularity',
|
||||
('since', 'until'),
|
||||
'groupby',
|
||||
'columns',
|
||||
'metrics',
|
||||
'pandas_aggfunc',
|
||||
]
|
||||
fieldsets = (
|
||||
{
|
||||
'label': None,
|
||||
'fields': (
|
||||
'viz_type',
|
||||
'granularity',
|
||||
('since', 'until'),
|
||||
'groupby',
|
||||
'columns',
|
||||
'metrics',
|
||||
'pandas_aggfunc',
|
||||
)
|
||||
},)
|
||||
|
||||
def query_obj(self):
|
||||
d = super(PivotTableViz, self).query_obj()
|
||||
groupby = self.form_data.get('groupby')
|
||||
columns = self.form_data.get('columns')
|
||||
metrics = self.form_data.get('metrics')
|
||||
if not columns:
|
||||
columns = []
|
||||
if not groupby:
|
||||
groupby = []
|
||||
if not groupby:
|
||||
raise Exception("Please choose at least one \"Group by\" field ")
|
||||
if not metrics:
|
||||
|
|
@ -255,7 +285,7 @@ class PivotTableViz(BaseViz):
|
|||
any(v in columns for v in groupby)):
|
||||
raise Exception("groupby and columns can't overlap")
|
||||
|
||||
d['groupby'] = list(set(d['groupby']) | set(self.form_data.get('columns')))
|
||||
d['groupby'] = list(set(groupby) | set(columns))
|
||||
d['is_timeseries'] = False
|
||||
d['timeseries_limit'] = None
|
||||
return d
|
||||
|
|
@ -280,7 +310,11 @@ class MarkupViz(BaseViz):
|
|||
viz_type = "markup"
|
||||
verbose_name = "Markup Widget"
|
||||
template = 'panoramix/viz_markup.html'
|
||||
form_fields = ['viz_type', 'markup_type', 'code']
|
||||
fieldsets = (
|
||||
{
|
||||
'label': None,
|
||||
'fields': ('viz_type', 'markup_type', 'code')
|
||||
},)
|
||||
is_timeseries = False
|
||||
|
||||
def rendered(self):
|
||||
|
|
@ -301,13 +335,17 @@ class WordCloudViz(BaseViz):
|
|||
verbose_name = "Word Cloud"
|
||||
template = 'panoramix/viz_word_cloud.html'
|
||||
is_timeseries = False
|
||||
form_fields = [
|
||||
'viz_type',
|
||||
('since', 'until'),
|
||||
'groupby', 'metric', 'limit',
|
||||
('size_from', 'size_to'),
|
||||
'rotation',
|
||||
]
|
||||
fieldsets = (
|
||||
{
|
||||
'label': None,
|
||||
'fields': (
|
||||
'viz_type',
|
||||
('since', 'until'),
|
||||
'groupby', 'metric', 'limit',
|
||||
('size_from', 'size_to'),
|
||||
'rotation',
|
||||
)
|
||||
},)
|
||||
js_files = [
|
||||
'lib/d3.min.js',
|
||||
'lib/d3.layout.cloud.js',
|
||||
|
|
@ -349,15 +387,19 @@ class BubbleViz(NVD3Viz):
|
|||
viz_type = "bubble"
|
||||
verbose_name = "Bubble Chart"
|
||||
is_timeseries = False
|
||||
form_fields = [
|
||||
'viz_type',
|
||||
('since', 'until'),
|
||||
('series', 'entity'),
|
||||
('x', 'y'),
|
||||
('size', 'limit'),
|
||||
('x_log_scale', 'y_log_scale'),
|
||||
('show_legend', None),
|
||||
]
|
||||
fieldsets = (
|
||||
{
|
||||
'label': None,
|
||||
'fields': (
|
||||
'viz_type',
|
||||
('since', 'until'),
|
||||
('series', 'entity'),
|
||||
('x', 'y'),
|
||||
('size', 'limit'),
|
||||
('x_log_scale', 'y_log_scale'),
|
||||
('show_legend', None),
|
||||
)
|
||||
},)
|
||||
|
||||
def query_obj(self):
|
||||
form_data = self.form_data
|
||||
|
|
@ -420,14 +462,18 @@ class BigNumberViz(BaseViz):
|
|||
css_files = [
|
||||
'widgets/viz_bignumber.css',
|
||||
]
|
||||
form_fields = [
|
||||
'viz_type',
|
||||
'granularity',
|
||||
('since', 'until'),
|
||||
'metric',
|
||||
'compare_lag',
|
||||
'compare_suffix',
|
||||
]
|
||||
fieldsets = (
|
||||
{
|
||||
'label': None,
|
||||
'fields': (
|
||||
'viz_type',
|
||||
'granularity',
|
||||
('since', 'until'),
|
||||
'metric',
|
||||
'compare_lag',
|
||||
'compare_suffix',
|
||||
)
|
||||
},)
|
||||
|
||||
def reassignments(self):
|
||||
metric = self.form_data.get('metric')
|
||||
|
|
@ -464,19 +510,33 @@ class NVD3TimeSeriesViz(NVD3Viz):
|
|||
verbose_name = "Time Series - Line Chart"
|
||||
sort_series = False
|
||||
is_timeseries = True
|
||||
form_fields = [
|
||||
'viz_type',
|
||||
'granularity', ('since', 'until'),
|
||||
'metrics',
|
||||
'groupby', 'limit',
|
||||
('rolling_type', 'rolling_periods'),
|
||||
('time_compare', 'num_period_compare'),
|
||||
('line_interpolation', None),
|
||||
('show_brush', 'show_legend'),
|
||||
('rich_tooltip', 'y_axis_zero'),
|
||||
('y_log_scale', 'contribution'),
|
||||
('y_axis_format', 'x_axis_showminmax'),
|
||||
]
|
||||
fieldsets = (
|
||||
{
|
||||
'label': None,
|
||||
'fields': (
|
||||
'viz_type',
|
||||
'granularity', ('since', 'until'),
|
||||
'metrics',
|
||||
'groupby', 'limit',
|
||||
),
|
||||
}, {
|
||||
'label': 'Chart Options',
|
||||
'fields': (
|
||||
('show_brush', 'show_legend'),
|
||||
('rich_tooltip', 'y_axis_zero'),
|
||||
('y_log_scale', 'contribution'),
|
||||
('y_axis_format', 'x_axis_showminmax'),
|
||||
('line_interpolation', None),
|
||||
),
|
||||
}, {
|
||||
'label': 'Advanced Analytics',
|
||||
'fields': (
|
||||
('rolling_type', 'rolling_periods'),
|
||||
'time_compare',
|
||||
'num_period_compare',
|
||||
),
|
||||
},
|
||||
)
|
||||
|
||||
def get_df(self, query_obj=None):
|
||||
form_data = self.form_data
|
||||
|
|
@ -582,54 +642,70 @@ class NVD3TimeSeriesViz(NVD3Viz):
|
|||
class NVD3TimeSeriesBarViz(NVD3TimeSeriesViz):
|
||||
viz_type = "bar"
|
||||
verbose_name = "Time Series - Bar Chart"
|
||||
form_fields = [
|
||||
'viz_type',
|
||||
'granularity', ('since', 'until'),
|
||||
'metrics',
|
||||
'groupby', 'limit',
|
||||
('rolling_type', 'rolling_periods'),
|
||||
'show_legend',
|
||||
]
|
||||
fieldsets = (
|
||||
{
|
||||
'label': None,
|
||||
'fields': (
|
||||
'viz_type',
|
||||
'granularity', ('since', 'until'),
|
||||
'metrics',
|
||||
'groupby', 'limit',
|
||||
('rolling_type', 'rolling_periods'),
|
||||
'show_legend',
|
||||
)
|
||||
},)
|
||||
|
||||
|
||||
class NVD3CompareTimeSeriesViz(NVD3TimeSeriesViz):
|
||||
viz_type = 'compare'
|
||||
verbose_name = "Time Series - Percent Change"
|
||||
form_fields = [
|
||||
'viz_type',
|
||||
'granularity', ('since', 'until'),
|
||||
'metrics',
|
||||
'groupby', 'limit',
|
||||
('rolling_type', 'rolling_periods'),
|
||||
'show_legend',
|
||||
]
|
||||
fieldsets = (
|
||||
{
|
||||
'label': None,
|
||||
'fields': (
|
||||
'viz_type',
|
||||
'granularity', ('since', 'until'),
|
||||
'metrics',
|
||||
'groupby', 'limit',
|
||||
('rolling_type', 'rolling_periods'),
|
||||
'show_legend',
|
||||
)
|
||||
},)
|
||||
|
||||
|
||||
class NVD3TimeSeriesStackedViz(NVD3TimeSeriesViz):
|
||||
viz_type = "area"
|
||||
verbose_name = "Time Series - Stacked"
|
||||
sort_series = True
|
||||
form_fields = [
|
||||
'viz_type',
|
||||
'granularity', ('since', 'until'),
|
||||
'metrics',
|
||||
'groupby', 'limit',
|
||||
('rolling_type', 'rolling_periods'),
|
||||
('rich_tooltip', 'show_legend'),
|
||||
]
|
||||
fieldsets = (
|
||||
{
|
||||
'label': None,
|
||||
'fields': (
|
||||
'viz_type',
|
||||
'granularity', ('since', 'until'),
|
||||
'metrics',
|
||||
'groupby', 'limit',
|
||||
('rolling_type', 'rolling_periods'),
|
||||
('rich_tooltip', 'show_legend'),
|
||||
)
|
||||
},)
|
||||
|
||||
|
||||
class DistributionPieViz(NVD3Viz):
|
||||
viz_type = "pie"
|
||||
verbose_name = "Distribution - NVD3 - Pie Chart"
|
||||
is_timeseries = False
|
||||
form_fields = [
|
||||
'viz_type',
|
||||
('since', 'until'),
|
||||
'metrics', 'groupby',
|
||||
'limit',
|
||||
('donut', 'show_legend'),
|
||||
]
|
||||
fieldsets = (
|
||||
{
|
||||
'label': None,
|
||||
'fields': (
|
||||
'viz_type',
|
||||
('since', 'until'),
|
||||
'metrics', 'groupby',
|
||||
'limit',
|
||||
('donut', 'show_legend'),
|
||||
)
|
||||
},)
|
||||
|
||||
def query_obj(self):
|
||||
d = super(DistributionPieViz, self).query_obj()
|
||||
|
|
@ -660,12 +736,16 @@ class DistributionBarViz(DistributionPieViz):
|
|||
viz_type = "dist_bar"
|
||||
verbose_name = "Distribution - Bar Chart"
|
||||
is_timeseries = False
|
||||
form_fields = [
|
||||
'viz_type', 'metrics', 'groupby',
|
||||
('since', 'until'),
|
||||
'limit',
|
||||
('show_legend', None),
|
||||
]
|
||||
fieldsets = (
|
||||
{
|
||||
'label': None,
|
||||
'fields': (
|
||||
'viz_type', 'metrics', 'groupby',
|
||||
('since', 'until'),
|
||||
'limit',
|
||||
('show_legend', None),
|
||||
)
|
||||
},)
|
||||
|
||||
def get_df(self):
|
||||
df = super(DistributionPieViz, self).get_df()
|
||||
|
|
|
|||
Loading…
Reference in New Issue