Skip to content

Commit

Permalink
Merge pull request #74 from mistercrunch/fieldsets
Browse files Browse the repository at this point in the history
Introducing fieldsets
  • Loading branch information
mistercrunch committed Dec 8, 2015
2 parents 6f2c953 + a32712d commit 021654c
Show file tree
Hide file tree
Showing 5 changed files with 338 additions and 169 deletions.
40 changes: 16 additions & 24 deletions panoramix/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,19 +38,9 @@ def iter_choices(self):


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)

Expand Down Expand Up @@ -179,7 +169,7 @@ def __init__(self, viz):
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']),
Expand All @@ -204,7 +194,7 @@ def __init__(self, viz):
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(
Expand Down Expand Up @@ -239,7 +229,7 @@ def __init__(self, viz):
"[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 "
Expand Down Expand Up @@ -278,14 +268,15 @@ def get_form(self, previous=False):
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()
json = HiddenField()
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):
Expand All @@ -300,23 +291,24 @@ class QueryForm(OmgWtForm):
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
28 changes: 28 additions & 0 deletions panoramix/static/panoramix.css
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
161 changes: 115 additions & 46 deletions panoramix/templates/panoramix/explore.html
Original file line number Diff line number Diff line change
Expand Up @@ -22,57 +22,74 @@ <h4>

<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!
Expand All @@ -91,6 +108,7 @@ <h4>Filters</h4>
<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 }}">
Expand Down Expand Up @@ -161,6 +179,57 @@ <h4 class="modal-title" id="myModalLabel">Query</h4>
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 %}
2 changes: 1 addition & 1 deletion panoramix/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,7 @@ def explore(self, datasource_type, datasource_id):
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):
Expand Down
Loading

0 comments on commit 021654c

Please sign in to comment.