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.
|
||||
"""
|
||||
# TODO
|
||||
# data_type = 'number'
|
||||
data_type = 'number'
|
||||
|
||||
def render(self, value=None, **kwargs):
|
||||
kwargs.setdefault('step', '0.001')
|
||||
|
@ -137,6 +136,7 @@ class GridFilter(object):
|
|||
'less_equal': "less than or equal to",
|
||||
'is_empty': "is empty",
|
||||
'is_not_empty': "is not empty",
|
||||
'between': "between",
|
||||
'is_null': "is null",
|
||||
'is_not_null': "is not null",
|
||||
'is_true': "is true",
|
||||
|
@ -378,6 +378,47 @@ class AlchemyGridFilter(GridFilter):
|
|||
return query
|
||||
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):
|
||||
"""
|
||||
|
@ -532,7 +573,8 @@ class AlchemyNumericFilter(AlchemyGridFilter):
|
|||
|
||||
# expose greater-than / less-than verbs in addition to core
|
||||
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
|
||||
# user's perspective it still fails silently...need to improve on front-end
|
||||
|
@ -541,6 +583,13 @@ class AlchemyNumericFilter(AlchemyGridFilter):
|
|||
# term for integer field...
|
||||
|
||||
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)
|
||||
|
||||
def filter_equal(self, query, value):
|
||||
|
@ -726,6 +775,7 @@ class AlchemyDateFilter(AlchemyGridFilter):
|
|||
return query
|
||||
return query.filter(self.column <= self.encode_value(date))
|
||||
|
||||
# TODO: this should be merged into parent class
|
||||
def filter_between(self, query, value):
|
||||
"""
|
||||
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)
|
||||
|
||||
# TODO: this should be merged into parent class
|
||||
def filter_date_range(self, query, start_date, end_date):
|
||||
"""
|
||||
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 = {
|
||||
template: '#grid-filter-date-value-template',
|
||||
props: {
|
||||
|
|
|
@ -1,5 +1,29 @@
|
|||
## -*- 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">
|
||||
<div class="level">
|
||||
<div class="level-left">
|
||||
|
@ -75,6 +99,13 @@
|
|||
</option>
|
||||
</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()"
|
||||
v-model="filter.value"
|
||||
v-show="valuedVerb()"
|
||||
|
|
Loading…
Reference in a new issue