mirror of https://github.com/apache/superset.git
Preserving the ordering in selectmultiple
This commit is contained in:
parent
de52449c2a
commit
c8faeed5b3
|
@ -1,22 +1,40 @@
|
|||
from wtforms import (
|
||||
Field, Form, SelectMultipleField, SelectField, TextField, TextAreaField,
|
||||
BooleanField, IntegerField, HiddenField)
|
||||
from wtforms import validators
|
||||
from wtforms.widgets import HTMLString
|
||||
from wtforms import validators, widgets
|
||||
from copy import copy
|
||||
from panoramix import app
|
||||
from six import string_types
|
||||
from collections import OrderedDict
|
||||
config = app.config
|
||||
|
||||
|
||||
# Fixes behavior of html forms omitting non checked <input>
|
||||
# (which doesn't distinguish False from NULL/missing )
|
||||
# If value is unchecked, this hidden <input> fills in False value
|
||||
class BetterBooleanField(BooleanField):
|
||||
"""
|
||||
Fixes behavior of html forms omitting non checked <input>
|
||||
(which doesn't distinguish False from NULL/missing )
|
||||
If value is unchecked, this hidden <input> fills in False value
|
||||
"""
|
||||
def __call__(self, **kwargs):
|
||||
html = super(BetterBooleanField, self).__call__(**kwargs)
|
||||
html += u'<input type="hidden" name="show_brush" value="false">'
|
||||
return HTMLString(html)
|
||||
return widgets.HTMLString(html)
|
||||
|
||||
|
||||
class BetterSelectMultipleField(SelectMultipleField):
|
||||
"""
|
||||
Works along with select2sortable to preserves the sort order
|
||||
"""
|
||||
def iter_choices(self):
|
||||
d = OrderedDict()
|
||||
for value, label in self.choices:
|
||||
selected = self.data is not None and self.coerce(value) in self.data
|
||||
d[value] = (value, label, selected)
|
||||
if self.data:
|
||||
for value in self.data:
|
||||
yield d.pop(value)
|
||||
while d:
|
||||
yield d.pop(d.keys()[0])
|
||||
|
||||
|
||||
class OmgWtForm(Form):
|
||||
|
@ -61,7 +79,7 @@ class FormFactory(object):
|
|||
default='table',
|
||||
choices=[(k, v.verbose_name) for k, v in viz_types.items()],
|
||||
description="The type of visualization to display"),
|
||||
'metrics': SelectMultipleField(
|
||||
'metrics': BetterSelectMultipleField(
|
||||
'Metrics', choices=datasource.metrics_combo,
|
||||
default=[default_metric],
|
||||
description="One or many metrics to display"),
|
||||
|
@ -69,7 +87,7 @@ class FormFactory(object):
|
|||
'Metric', choices=datasource.metrics_combo,
|
||||
default=default_metric,
|
||||
description="One or many metrics to display"),
|
||||
'groupby': SelectMultipleField(
|
||||
'groupby': BetterSelectMultipleField(
|
||||
'Group by',
|
||||
choices=self.choicify(datasource.groupby_column_names),
|
||||
description="One or many fields to group by"),
|
||||
|
@ -221,7 +239,7 @@ class FormFactory(object):
|
|||
datasource = viz.datasource
|
||||
field_css_classes = {k: ['form-control'] for k in px_form_fields.keys()}
|
||||
select2 = [
|
||||
'viz_type', 'metrics', 'groupby',
|
||||
'viz_type', 'groupby',
|
||||
'row_limit', 'rolling_type', 'series',
|
||||
'entity', 'x', 'y', 'size', 'rotation', 'metric', 'limit',
|
||||
'markup_type',]
|
||||
|
@ -232,6 +250,7 @@ class FormFactory(object):
|
|||
field_css_classes[field] += ['input-sm']
|
||||
for field in select2:
|
||||
field_css_classes[field] += ['select2']
|
||||
field_css_classes['metrics'] += ['select2Sortable']
|
||||
|
||||
|
||||
class QueryForm(OmgWtForm):
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,146 @@
|
|||
/**
|
||||
* jQuery Select2 Sortable
|
||||
* - enable select2 to be sortable via normal select element
|
||||
*
|
||||
* author : Vafour
|
||||
* modified : Kevin Provance (kprovance)
|
||||
* inspired by : jQuery Chosen Sortable (https://github.com/mrhenry/jquery-chosen-sortable)
|
||||
* License : GPL
|
||||
*/
|
||||
|
||||
(function ($) {
|
||||
$.fn.extend({
|
||||
select2SortableOrder: function () {
|
||||
var $this = this.filter('[multiple]');
|
||||
|
||||
$this.each(function () {
|
||||
var $select = $(this);
|
||||
|
||||
// skip elements not select2-ed
|
||||
if (typeof ($select.data('select2')) !== 'object') {
|
||||
return false;
|
||||
}
|
||||
|
||||
var $select2 = $select.siblings('.select2-container');
|
||||
var sorted;
|
||||
|
||||
// Opt group names
|
||||
var optArr = [];
|
||||
|
||||
$select.find('optgroup').each(function(idx, val) {
|
||||
optArr.push (val);
|
||||
});
|
||||
|
||||
$select.find('option').each(function(idx, val) {
|
||||
var groupName = $(this).parent('optgroup').prop('label');
|
||||
var optVal = this;
|
||||
|
||||
if (groupName === undefined) {
|
||||
if (this.value !== '' && !this.selected) {
|
||||
optArr.push (optVal);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
sorted = $($select2.find('.select2-choices li[class!="select2-search-field"]').map(function () {
|
||||
if (!this) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
var id = $(this).data('select2Data').id;
|
||||
|
||||
return $select.find('option[value="' + id + '"]')[0];
|
||||
}));
|
||||
|
||||
sorted.push.apply(sorted, optArr);
|
||||
|
||||
$select.children().remove();
|
||||
$select.append(sorted);
|
||||
});
|
||||
|
||||
return $this;
|
||||
},
|
||||
|
||||
select2Sortable: function () {
|
||||
var args = Array.prototype.slice.call(arguments, 0);
|
||||
$this = this.filter('[multiple]'),
|
||||
validMethods = ['destroy'];
|
||||
|
||||
if (args.length === 0 || typeof (args[0]) === 'object') {
|
||||
var defaultOptions = {
|
||||
bindOrder: 'formSubmit', // or sortableStop
|
||||
sortableOptions: {
|
||||
placeholder: 'ui-state-highlight',
|
||||
items: 'li:not(.select2-search-field)',
|
||||
tolerance: 'pointer'
|
||||
}
|
||||
};
|
||||
|
||||
var options = $.extend(defaultOptions, args[0]);
|
||||
|
||||
// Init select2 only if not already initialized to prevent select2 configuration loss
|
||||
if (typeof ($this.data('select2')) !== 'object') {
|
||||
$this.select2();
|
||||
}
|
||||
|
||||
$this.each(function () {
|
||||
var $select = $(this)
|
||||
var $select2choices = $select.siblings('.select2-container').find('.select2-choices');
|
||||
|
||||
// Init jQuery UI Sortable
|
||||
$select2choices.sortable(options.sortableOptions);
|
||||
|
||||
switch (options.bindOrder) {
|
||||
case 'sortableStop':
|
||||
// apply options ordering in sortstop event
|
||||
$select2choices.on("sortstop.select2sortable", function (event, ui) {
|
||||
$select.select2SortableOrder();
|
||||
});
|
||||
|
||||
$select.on('change', function (e) {
|
||||
$(this).select2SortableOrder();
|
||||
});
|
||||
break;
|
||||
|
||||
default:
|
||||
// apply options ordering in form submit
|
||||
$select.closest('form').unbind('submit.select2sortable').on('submit.select2sortable', function () {
|
||||
$select.select2SortableOrder();
|
||||
});
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
else if (typeof (args[0] === 'string')) {
|
||||
if ($.inArray(args[0], validMethods) == -1) {
|
||||
throw "Unknown method: " + args[0];
|
||||
}
|
||||
|
||||
if (args[0] === 'destroy') {
|
||||
$this.select2SortableDestroy();
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
},
|
||||
|
||||
select2SortableDestroy: function () {
|
||||
var $this = this.filter('[multiple]');
|
||||
$this.each(function () {
|
||||
var $select = $(this)
|
||||
var $select2choices = $select.parent().find('.select2-choices');
|
||||
|
||||
// unbind form submit event
|
||||
$select.closest('form').unbind('submit.select2sortable');
|
||||
|
||||
// unbind sortstop event
|
||||
$select2choices.unbind("sortstop.select2sortable");
|
||||
|
||||
// destroy select2Sortable
|
||||
$select2choices.sortable('destroy');
|
||||
});
|
||||
|
||||
return $this;
|
||||
}
|
||||
});
|
||||
}(jQuery));
|
|
@ -29,6 +29,7 @@ function initializeDatasourceView() {
|
|||
}
|
||||
|
||||
$(".select2").select2();
|
||||
$(".select2Sortable").select2Sortable();
|
||||
$("form").show();
|
||||
$('[data-toggle="tooltip"]').tooltip({container: 'body'});
|
||||
|
||||
|
|
|
@ -4,9 +4,12 @@
|
|||
{{super()}}
|
||||
<link rel="shortcut icon" href="{{ url_for('static', filename='chaudron.png') }}" />
|
||||
<link rel="stylesheet" type="text/css" href="/static/panoramix.css" />
|
||||
<link rel="stylesheet" type="text/css" href="/static/lib/select2.sortable.css" />
|
||||
{% endblock %}
|
||||
|
||||
{% block tail_js %}
|
||||
{{ super() }}
|
||||
<script src="/static/panoramix.js"></script>
|
||||
<script src="/static/lib/jquery-ui.min.js"></script>
|
||||
<script src="/static/lib/select2.sortable.js"></script>
|
||||
{% endblock %}
|
||||
|
|
Loading…
Reference in New Issue