Add "between" verb for numeric grid filters
This commit is contained in:
parent
3e8924e7cc
commit
deed2111fb
|
@ -76,8 +76,7 @@ class NumericValueRenderer(FilterValueRenderer):
|
||||||
"""
|
"""
|
||||||
Input renderer for numeric values.
|
Input renderer for numeric values.
|
||||||
"""
|
"""
|
||||||
# TODO
|
data_type = 'number'
|
||||||
# data_type = 'number'
|
|
||||||
|
|
||||||
def render(self, value=None, **kwargs):
|
def render(self, value=None, **kwargs):
|
||||||
kwargs.setdefault('step', '0.001')
|
kwargs.setdefault('step', '0.001')
|
||||||
|
@ -137,6 +136,7 @@ class GridFilter(object):
|
||||||
'less_equal': "less than or equal to",
|
'less_equal': "less than or equal to",
|
||||||
'is_empty': "is empty",
|
'is_empty': "is empty",
|
||||||
'is_not_empty': "is not empty",
|
'is_not_empty': "is not empty",
|
||||||
|
'between': "between",
|
||||||
'is_null': "is null",
|
'is_null': "is null",
|
||||||
'is_not_null': "is not null",
|
'is_not_null': "is not null",
|
||||||
'is_true': "is true",
|
'is_true': "is true",
|
||||||
|
@ -378,6 +378,47 @@ class AlchemyGridFilter(GridFilter):
|
||||||
return query
|
return query
|
||||||
return query.filter(self.column <= self.encode_value(value))
|
return query.filter(self.column <= self.encode_value(value))
|
||||||
|
|
||||||
|
def filter_between(self, query, value):
|
||||||
|
"""
|
||||||
|
Filter data with a "between" query. Really this uses ">=" and
|
||||||
|
"<=" (inclusive) logic instead of SQL "between" keyword.
|
||||||
|
"""
|
||||||
|
if value is None or value == '':
|
||||||
|
return query
|
||||||
|
|
||||||
|
if '|' not in value:
|
||||||
|
return query
|
||||||
|
|
||||||
|
values = value.split('|')
|
||||||
|
if len(values) != 2:
|
||||||
|
return query
|
||||||
|
|
||||||
|
start_value, end_value = values
|
||||||
|
|
||||||
|
# we'll only filter if we have start and/or end value
|
||||||
|
if not start_value and not end_value:
|
||||||
|
return query
|
||||||
|
|
||||||
|
return self.filter_for_range(query, start_value, end_value)
|
||||||
|
|
||||||
|
def filter_for_range(self, query, start_value, end_value):
|
||||||
|
"""
|
||||||
|
This method should actually apply filter(s) to the query,
|
||||||
|
according to the given value range. Subclasses may override
|
||||||
|
this logic.
|
||||||
|
"""
|
||||||
|
if start_value:
|
||||||
|
if self.value_invalid(start_value):
|
||||||
|
return query
|
||||||
|
query = query.filter(self.column >= start_value)
|
||||||
|
|
||||||
|
if end_value:
|
||||||
|
if self.value_invalid(end_value):
|
||||||
|
return query
|
||||||
|
query = query.filter(self.column <= end_value)
|
||||||
|
|
||||||
|
return query
|
||||||
|
|
||||||
|
|
||||||
class AlchemyStringFilter(AlchemyGridFilter):
|
class AlchemyStringFilter(AlchemyGridFilter):
|
||||||
"""
|
"""
|
||||||
|
@ -532,7 +573,8 @@ class AlchemyNumericFilter(AlchemyGridFilter):
|
||||||
|
|
||||||
# expose greater-than / less-than verbs in addition to core
|
# expose greater-than / less-than verbs in addition to core
|
||||||
default_verbs = ['equal', 'not_equal', 'greater_than', 'greater_equal',
|
default_verbs = ['equal', 'not_equal', 'greater_than', 'greater_equal',
|
||||||
'less_than', 'less_equal', 'is_null', 'is_not_null', 'is_any']
|
'less_than', 'less_equal', 'between',
|
||||||
|
'is_null', 'is_not_null', 'is_any']
|
||||||
|
|
||||||
# TODO: what follows "works" in that it prevents an error...but from the
|
# TODO: what follows "works" in that it prevents an error...but from the
|
||||||
# user's perspective it still fails silently...need to improve on front-end
|
# user's perspective it still fails silently...need to improve on front-end
|
||||||
|
@ -541,6 +583,13 @@ class AlchemyNumericFilter(AlchemyGridFilter):
|
||||||
# term for integer field...
|
# term for integer field...
|
||||||
|
|
||||||
def value_invalid(self, value):
|
def value_invalid(self, value):
|
||||||
|
|
||||||
|
# first just make sure it's somewhat numeric
|
||||||
|
try:
|
||||||
|
float(value)
|
||||||
|
except ValueError:
|
||||||
|
return True
|
||||||
|
|
||||||
return bool(value and len(six.text_type(value)) > 8)
|
return bool(value and len(six.text_type(value)) > 8)
|
||||||
|
|
||||||
def filter_equal(self, query, value):
|
def filter_equal(self, query, value):
|
||||||
|
@ -726,6 +775,7 @@ class AlchemyDateFilter(AlchemyGridFilter):
|
||||||
return query
|
return query
|
||||||
return query.filter(self.column <= self.encode_value(date))
|
return query.filter(self.column <= self.encode_value(date))
|
||||||
|
|
||||||
|
# TODO: this should be merged into parent class
|
||||||
def filter_between(self, query, value):
|
def filter_between(self, query, value):
|
||||||
"""
|
"""
|
||||||
Filter data with a "between" query. Really this uses ">=" and "<="
|
Filter data with a "between" query. Really this uses ">=" and "<="
|
||||||
|
@ -753,6 +803,7 @@ class AlchemyDateFilter(AlchemyGridFilter):
|
||||||
|
|
||||||
return self.filter_date_range(query, start_date, end_date)
|
return self.filter_date_range(query, start_date, end_date)
|
||||||
|
|
||||||
|
# TODO: this should be merged into parent class
|
||||||
def filter_date_range(self, query, start_date, end_date):
|
def filter_date_range(self, query, start_date, end_date):
|
||||||
"""
|
"""
|
||||||
This method should actually apply filter(s) to the query, according to
|
This method should actually apply filter(s) to the query, according to
|
||||||
|
|
|
@ -1,4 +1,53 @@
|
||||||
|
|
||||||
|
const GridFilterNumericValue = {
|
||||||
|
template: '#grid-filter-numeric-value-template',
|
||||||
|
props: {
|
||||||
|
value: String,
|
||||||
|
wantsRange: Boolean,
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
startValue: null,
|
||||||
|
endValue: null,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
if (this.wantsRange) {
|
||||||
|
if (this.value.includes('|')) {
|
||||||
|
let values = this.value.split('|')
|
||||||
|
if (values.length == 2) {
|
||||||
|
this.startValue = values[0]
|
||||||
|
this.endValue = values[1]
|
||||||
|
} else {
|
||||||
|
this.startValue = this.value
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.startValue = this.value
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.startValue = this.value
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
focus() {
|
||||||
|
this.$refs.startValue.focus()
|
||||||
|
},
|
||||||
|
startValueChanged(value) {
|
||||||
|
if (this.wantsRange) {
|
||||||
|
value += '|' + this.endValue
|
||||||
|
}
|
||||||
|
this.$emit('input', value)
|
||||||
|
},
|
||||||
|
endValueChanged(value) {
|
||||||
|
value = this.startValue + '|' + value
|
||||||
|
this.$emit('input', value)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
Vue.component('grid-filter-numeric-value', GridFilterNumericValue)
|
||||||
|
|
||||||
|
|
||||||
const GridFilterDateValue = {
|
const GridFilterDateValue = {
|
||||||
template: '#grid-filter-date-value-template',
|
template: '#grid-filter-date-value-template',
|
||||||
props: {
|
props: {
|
||||||
|
|
|
@ -1,5 +1,29 @@
|
||||||
## -*- coding: utf-8; -*-
|
## -*- coding: utf-8; -*-
|
||||||
|
|
||||||
|
<script type="text/x-template" id="grid-filter-numeric-value-template">
|
||||||
|
<div class="level">
|
||||||
|
<div class="level-left">
|
||||||
|
<div class="level-item">
|
||||||
|
<b-input v-model="startValue"
|
||||||
|
ref="startValue"
|
||||||
|
@input="startValueChanged">
|
||||||
|
</b-input>
|
||||||
|
</div>
|
||||||
|
<div v-show="wantsRange"
|
||||||
|
class="level-item">
|
||||||
|
and
|
||||||
|
</div>
|
||||||
|
<div v-show="wantsRange"
|
||||||
|
class="level-item">
|
||||||
|
<b-input v-model="endValue"
|
||||||
|
ref="endValue"
|
||||||
|
@input="endValueChanged">
|
||||||
|
</b-input>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</script>
|
||||||
|
|
||||||
<script type="text/x-template" id="grid-filter-date-value-template">
|
<script type="text/x-template" id="grid-filter-date-value-template">
|
||||||
<div class="level">
|
<div class="level">
|
||||||
<div class="level-left">
|
<div class="level-left">
|
||||||
|
@ -75,6 +99,13 @@
|
||||||
</option>
|
</option>
|
||||||
</b-select>
|
</b-select>
|
||||||
|
|
||||||
|
<grid-filter-numeric-value v-if="filter.data_type == 'number'"
|
||||||
|
v-model="filter.value"
|
||||||
|
v-show="valuedVerb()"
|
||||||
|
:wants-range="filter.verb == 'between'"
|
||||||
|
ref="valueInput">
|
||||||
|
</grid-filter-numeric-value>
|
||||||
|
|
||||||
<b-input v-if="filter.data_type == 'string' && !multiValuedVerb()"
|
<b-input v-if="filter.data_type == 'string' && !multiValuedVerb()"
|
||||||
v-model="filter.value"
|
v-model="filter.value"
|
||||||
v-show="valuedVerb()"
|
v-show="valuedVerb()"
|
||||||
|
|
Loading…
Reference in a new issue