Add basic support for "between" verb, for date range grid filter
this seems to be complete, but we'll see in practice if i forgot something..
This commit is contained in:
parent
14778757d9
commit
d97f95fb92
|
@ -553,6 +553,7 @@ class AlchemyDateFilter(AlchemyGridFilter):
|
|||
'greater_equal': "on or after",
|
||||
'less_than': "before",
|
||||
'less_equal': "on or before",
|
||||
'between': "between",
|
||||
'is_null': "is null",
|
||||
'is_not_null': "is not null",
|
||||
'is_any': "is any",
|
||||
|
@ -562,8 +563,18 @@ class AlchemyDateFilter(AlchemyGridFilter):
|
|||
"""
|
||||
Expose greater-than / less-than verbs in addition to core.
|
||||
"""
|
||||
return ['equal', 'not_equal', 'greater_than', 'greater_equal',
|
||||
'less_than', 'less_equal', 'is_null', 'is_not_null', 'is_any']
|
||||
return [
|
||||
'equal',
|
||||
'not_equal',
|
||||
'greater_than',
|
||||
'greater_equal',
|
||||
'less_than',
|
||||
'less_equal',
|
||||
'between',
|
||||
'is_null',
|
||||
'is_not_null',
|
||||
'is_any',
|
||||
]
|
||||
|
||||
def make_date(self, value):
|
||||
"""
|
||||
|
@ -577,6 +588,44 @@ class AlchemyDateFilter(AlchemyGridFilter):
|
|||
else:
|
||||
return dt.date()
|
||||
|
||||
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_date, end_date = values
|
||||
if start_date:
|
||||
start_date = self.make_date(start_date)
|
||||
if end_date:
|
||||
end_date = self.make_date(end_date)
|
||||
|
||||
# we'll only filter if we have start and/or end date
|
||||
if not start_date and not end_date:
|
||||
return query
|
||||
|
||||
return self.filter_date_range(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
|
||||
the given date range. Subclasses may override this logic.
|
||||
"""
|
||||
if start_date:
|
||||
query = query.filter(self.column >= start_date)
|
||||
if end_date:
|
||||
query = query.filter(self.column <= end_date)
|
||||
return query
|
||||
|
||||
|
||||
class AlchemyDateTimeFilter(AlchemyDateFilter):
|
||||
"""
|
||||
|
@ -666,6 +715,17 @@ class AlchemyDateTimeFilter(AlchemyDateFilter):
|
|||
time = make_utc(localtime(self.config, time))
|
||||
return query.filter(self.column < time)
|
||||
|
||||
def filter_date_range(self, query, start_date, end_date):
|
||||
if start_date:
|
||||
start_time = datetime.datetime.combine(start_date, datetime.time(0))
|
||||
start_time = localtime(self.config, start_time)
|
||||
query = query.filter(self.column >= make_utc(start_time))
|
||||
if end_date:
|
||||
end_time = datetime.datetime.combine(end_date + datetime.timedelta(days=1), datetime.time(0))
|
||||
end_time = localtime(self.config, end_time)
|
||||
query = query.filter(self.column <= make_utc(end_time))
|
||||
return query
|
||||
|
||||
|
||||
class AlchemyLocalDateTimeFilter(AlchemyDateTimeFilter):
|
||||
"""
|
||||
|
@ -756,6 +816,17 @@ class AlchemyLocalDateTimeFilter(AlchemyDateTimeFilter):
|
|||
time = localtime(self.config, time, tzinfo=False)
|
||||
return query.filter(self.column < time)
|
||||
|
||||
def filter_date_range(self, query, start_date, end_date):
|
||||
if start_date:
|
||||
start_time = datetime.datetime.combine(start_date, datetime.time(0))
|
||||
start_time = localtime(self.config, start_time, tzinfo=False)
|
||||
query = query.filter(self.column >= start_time)
|
||||
if end_date:
|
||||
end_time = datetime.datetime.combine(end_date + datetime.timedelta(days=1), datetime.time(0))
|
||||
end_time = localtime(self.config, end_time, tzinfo=False)
|
||||
query = query.filter(self.column <= end_time)
|
||||
return query
|
||||
|
||||
|
||||
class AlchemyGPCFilter(AlchemyGridFilter):
|
||||
"""
|
||||
|
|
|
@ -14,6 +14,7 @@ const TailboneDatepicker = {
|
|||
':value="value ? parseDate(value) : null"',
|
||||
'@input="dateChanged"',
|
||||
':disabled="disabled"',
|
||||
'ref="trueDatePicker"',
|
||||
'>',
|
||||
'</b-datepicker>'
|
||||
].join(' '),
|
||||
|
@ -49,7 +50,11 @@ const TailboneDatepicker = {
|
|||
|
||||
dateChanged(date) {
|
||||
this.$emit('input', this.formatDate(date))
|
||||
}
|
||||
},
|
||||
|
||||
focus() {
|
||||
this.$refs.trueDatePicker.focus()
|
||||
},
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,4 +1,53 @@
|
|||
|
||||
const GridFilterDateValue = {
|
||||
template: '#grid-filter-date-value-template',
|
||||
props: {
|
||||
value: String,
|
||||
dateRange: Boolean,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
startDate: null,
|
||||
endDate: null,
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
if (this.dateRange) {
|
||||
if (this.value.includes('|')) {
|
||||
let values = this.value.split('|')
|
||||
if (values.length == 2) {
|
||||
this.startDate = values[0]
|
||||
this.endDate = values[1]
|
||||
} else {
|
||||
this.startDate = this.value
|
||||
}
|
||||
} else {
|
||||
this.startDate = this.value
|
||||
}
|
||||
} else {
|
||||
this.startDate = this.value
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
focus() {
|
||||
this.$refs.startDate.focus()
|
||||
},
|
||||
startDateChanged(value) {
|
||||
if (this.dateRange) {
|
||||
value += '|' + this.endDate
|
||||
}
|
||||
this.$emit('input', value)
|
||||
},
|
||||
endDateChanged(value) {
|
||||
value = this.startDate + '|' + value
|
||||
this.$emit('input', value)
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
Vue.component('grid-filter-date-value', GridFilterDateValue)
|
||||
|
||||
|
||||
const GridFilter = {
|
||||
template: '#grid-filter-template',
|
||||
props: {
|
||||
|
@ -14,6 +63,23 @@ const GridFilter = {
|
|||
})
|
||||
},
|
||||
|
||||
valuedVerb() {
|
||||
/* this returns true if the filter's current verb should expose value input(s) */
|
||||
|
||||
// if filter has no "valueless" verbs, then all verbs should expose value inputs
|
||||
if (!this.filter.valueless_verbs) {
|
||||
return true
|
||||
}
|
||||
|
||||
// if filter *does* have valueless verbs, check if "current" verb is valueless
|
||||
if (this.filter.valueless_verbs.includes(this.filter.verb)) {
|
||||
return false
|
||||
}
|
||||
|
||||
// current verb is *not* valueless
|
||||
return true
|
||||
},
|
||||
|
||||
focusValue: function() {
|
||||
this.$refs.valueInput.focus()
|
||||
// this.$refs.valueInput.select()
|
||||
|
|
|
@ -1,5 +1,29 @@
|
|||
## -*- coding: utf-8; -*-
|
||||
|
||||
<script type="text/x-template" id="grid-filter-date-value-template">
|
||||
<div class="level">
|
||||
<div class="level-left">
|
||||
<div class="level-item">
|
||||
<tailbone-datepicker v-model="startDate"
|
||||
ref="startDate"
|
||||
@input="startDateChanged">
|
||||
</tailbone-datepicker>
|
||||
</div>
|
||||
<div v-show="dateRange"
|
||||
class="level-item">
|
||||
and
|
||||
</div>
|
||||
<div v-show="dateRange"
|
||||
class="level-item">
|
||||
<tailbone-datepicker v-model="endDate"
|
||||
ref="endDate"
|
||||
@input="endDateChanged">
|
||||
</tailbone-datepicker>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/x-template" id="grid-filter-template">
|
||||
|
||||
<div class="level filter" v-show="filter.visible">
|
||||
|
@ -30,15 +54,16 @@
|
|||
|
||||
## only one of the following "value input" elements will be rendered
|
||||
|
||||
<tailbone-datepicker v-if="filter.data_type == 'date'"
|
||||
<grid-filter-date-value v-if="filter.data_type == 'date'"
|
||||
v-model="filter.value"
|
||||
v-show="! (filter.valueless_verbs && filter.valueless_verbs.includes(filter.verb))"
|
||||
v-show="valuedVerb()"
|
||||
:date-range="filter.verb == 'between'"
|
||||
ref="valueInput">
|
||||
</tailbone-datepicker>
|
||||
</grid-filter-date-value>
|
||||
|
||||
<b-select v-if="filter.data_type == 'choice'"
|
||||
v-model="filter.value"
|
||||
v-show="! (filter.valueless_verbs && filter.valueless_verbs.includes(filter.verb))"
|
||||
v-show="valuedVerb()"
|
||||
ref="valueInput">
|
||||
<option v-for="choice in filter.choices"
|
||||
:key="choice"
|
||||
|
@ -49,7 +74,7 @@
|
|||
|
||||
<b-input v-if="filter.data_type == 'string'"
|
||||
v-model="filter.value"
|
||||
v-show="! (filter.valueless_verbs && filter.valueless_verbs.includes(filter.verb))"
|
||||
v-show="valuedVerb()"
|
||||
ref="valueInput">
|
||||
</b-input>
|
||||
|
||||
|
|
Loading…
Reference in a new issue