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",
|
'greater_equal': "on or after",
|
||||||
'less_than': "before",
|
'less_than': "before",
|
||||||
'less_equal': "on or before",
|
'less_equal': "on or before",
|
||||||
|
'between': "between",
|
||||||
'is_null': "is null",
|
'is_null': "is null",
|
||||||
'is_not_null': "is not null",
|
'is_not_null': "is not null",
|
||||||
'is_any': "is any",
|
'is_any': "is any",
|
||||||
|
@ -562,8 +563,18 @@ class AlchemyDateFilter(AlchemyGridFilter):
|
||||||
"""
|
"""
|
||||||
Expose greater-than / less-than verbs in addition to core.
|
Expose greater-than / less-than verbs in addition to core.
|
||||||
"""
|
"""
|
||||||
return ['equal', 'not_equal', 'greater_than', 'greater_equal',
|
return [
|
||||||
'less_than', 'less_equal', 'is_null', 'is_not_null', 'is_any']
|
'equal',
|
||||||
|
'not_equal',
|
||||||
|
'greater_than',
|
||||||
|
'greater_equal',
|
||||||
|
'less_than',
|
||||||
|
'less_equal',
|
||||||
|
'between',
|
||||||
|
'is_null',
|
||||||
|
'is_not_null',
|
||||||
|
'is_any',
|
||||||
|
]
|
||||||
|
|
||||||
def make_date(self, value):
|
def make_date(self, value):
|
||||||
"""
|
"""
|
||||||
|
@ -577,6 +588,44 @@ class AlchemyDateFilter(AlchemyGridFilter):
|
||||||
else:
|
else:
|
||||||
return dt.date()
|
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):
|
class AlchemyDateTimeFilter(AlchemyDateFilter):
|
||||||
"""
|
"""
|
||||||
|
@ -666,6 +715,17 @@ class AlchemyDateTimeFilter(AlchemyDateFilter):
|
||||||
time = make_utc(localtime(self.config, time))
|
time = make_utc(localtime(self.config, time))
|
||||||
return query.filter(self.column < 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):
|
class AlchemyLocalDateTimeFilter(AlchemyDateTimeFilter):
|
||||||
"""
|
"""
|
||||||
|
@ -756,6 +816,17 @@ class AlchemyLocalDateTimeFilter(AlchemyDateTimeFilter):
|
||||||
time = localtime(self.config, time, tzinfo=False)
|
time = localtime(self.config, time, tzinfo=False)
|
||||||
return query.filter(self.column < 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, 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):
|
class AlchemyGPCFilter(AlchemyGridFilter):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -14,6 +14,7 @@ const TailboneDatepicker = {
|
||||||
':value="value ? parseDate(value) : null"',
|
':value="value ? parseDate(value) : null"',
|
||||||
'@input="dateChanged"',
|
'@input="dateChanged"',
|
||||||
':disabled="disabled"',
|
':disabled="disabled"',
|
||||||
|
'ref="trueDatePicker"',
|
||||||
'>',
|
'>',
|
||||||
'</b-datepicker>'
|
'</b-datepicker>'
|
||||||
].join(' '),
|
].join(' '),
|
||||||
|
@ -49,7 +50,11 @@ const TailboneDatepicker = {
|
||||||
|
|
||||||
dateChanged(date) {
|
dateChanged(date) {
|
||||||
this.$emit('input', this.formatDate(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 = {
|
const GridFilter = {
|
||||||
template: '#grid-filter-template',
|
template: '#grid-filter-template',
|
||||||
props: {
|
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() {
|
focusValue: function() {
|
||||||
this.$refs.valueInput.focus()
|
this.$refs.valueInput.focus()
|
||||||
// this.$refs.valueInput.select()
|
// this.$refs.valueInput.select()
|
||||||
|
|
|
@ -1,5 +1,29 @@
|
||||||
## -*- coding: utf-8; -*-
|
## -*- 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">
|
<script type="text/x-template" id="grid-filter-template">
|
||||||
|
|
||||||
<div class="level filter" v-show="filter.visible">
|
<div class="level filter" v-show="filter.visible">
|
||||||
|
@ -30,15 +54,16 @@
|
||||||
|
|
||||||
## only one of the following "value input" elements will be rendered
|
## 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-model="filter.value"
|
||||||
v-show="! (filter.valueless_verbs && filter.valueless_verbs.includes(filter.verb))"
|
v-show="valuedVerb()"
|
||||||
ref="valueInput">
|
:date-range="filter.verb == 'between'"
|
||||||
</tailbone-datepicker>
|
ref="valueInput">
|
||||||
|
</grid-filter-date-value>
|
||||||
|
|
||||||
<b-select v-if="filter.data_type == 'choice'"
|
<b-select v-if="filter.data_type == 'choice'"
|
||||||
v-model="filter.value"
|
v-model="filter.value"
|
||||||
v-show="! (filter.valueless_verbs && filter.valueless_verbs.includes(filter.verb))"
|
v-show="valuedVerb()"
|
||||||
ref="valueInput">
|
ref="valueInput">
|
||||||
<option v-for="choice in filter.choices"
|
<option v-for="choice in filter.choices"
|
||||||
:key="choice"
|
:key="choice"
|
||||||
|
@ -49,7 +74,7 @@
|
||||||
|
|
||||||
<b-input v-if="filter.data_type == 'string'"
|
<b-input v-if="filter.data_type == 'string'"
|
||||||
v-model="filter.value"
|
v-model="filter.value"
|
||||||
v-show="! (filter.valueless_verbs && filter.valueless_verbs.includes(filter.verb))"
|
v-show="valuedVerb()"
|
||||||
ref="valueInput">
|
ref="valueInput">
|
||||||
</b-input>
|
</b-input>
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue