fix: add grid filter for animal birthdate
This commit is contained in:
parent
5d7dea5a84
commit
c976d94bdd
2 changed files with 99 additions and 10 deletions
|
|
@ -23,6 +23,8 @@
|
||||||
Custom grid stuff for use with farmOS / JSONAPI
|
Custom grid stuff for use with farmOS / JSONAPI
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import datetime
|
||||||
|
|
||||||
from wuttaweb.grids.filters import GridFilter
|
from wuttaweb.grids.filters import GridFilter
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -35,12 +37,12 @@ class SimpleFilter(GridFilter):
|
||||||
self.path = path or key
|
self.path = path or key
|
||||||
|
|
||||||
def filter_equal(self, data, value):
|
def filter_equal(self, data, value):
|
||||||
if value:
|
if value := self.coerce_value(value):
|
||||||
data.add_filter(self.path, "=", value)
|
data.add_filter(self.path, "=", value)
|
||||||
return data
|
return data
|
||||||
|
|
||||||
def filter_not_equal(self, data, value):
|
def filter_not_equal(self, data, value):
|
||||||
if value:
|
if value := self.coerce_value(value):
|
||||||
data.add_filter(self.path, "<>", value)
|
data.add_filter(self.path, "<>", value)
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
|
@ -58,7 +60,7 @@ class StringFilter(SimpleFilter):
|
||||||
default_verbs = ["contains", "equal", "not_equal"]
|
default_verbs = ["contains", "equal", "not_equal"]
|
||||||
|
|
||||||
def filter_contains(self, data, value):
|
def filter_contains(self, data, value):
|
||||||
if value:
|
if value := self.coerce_value(value):
|
||||||
data.add_filter(self.path, "CONTAINS", value)
|
data.add_filter(self.path, "CONTAINS", value)
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
|
@ -80,22 +82,22 @@ class IntegerFilter(SimpleFilter):
|
||||||
]
|
]
|
||||||
|
|
||||||
def filter_less_than(self, data, value):
|
def filter_less_than(self, data, value):
|
||||||
if value:
|
if value := self.coerce_value(value):
|
||||||
data.add_filter(self.path, "<", value)
|
data.add_filter(self.path, "<", value)
|
||||||
return data
|
return data
|
||||||
|
|
||||||
def filter_less_equal(self, data, value):
|
def filter_less_equal(self, data, value):
|
||||||
if value:
|
if value := self.coerce_value(value):
|
||||||
data.add_filter(self.path, "<=", value)
|
data.add_filter(self.path, "<=", value)
|
||||||
return data
|
return data
|
||||||
|
|
||||||
def filter_greater_than(self, data, value):
|
def filter_greater_than(self, data, value):
|
||||||
if value:
|
if value := self.coerce_value(value):
|
||||||
data.add_filter(self.path, ">", value)
|
data.add_filter(self.path, ">", value)
|
||||||
return data
|
return data
|
||||||
|
|
||||||
def filter_greater_equal(self, data, value):
|
def filter_greater_equal(self, data, value):
|
||||||
if value:
|
if value := self.coerce_value(value):
|
||||||
data.add_filter(self.path, ">=", value)
|
data.add_filter(self.path, ">=", value)
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
|
@ -123,6 +125,88 @@ class NullableBooleanFilter(BooleanFilter):
|
||||||
default_verbs = ["is_true", "is_false", "is_null", "is_not_null"]
|
default_verbs = ["is_true", "is_false", "is_null", "is_not_null"]
|
||||||
|
|
||||||
|
|
||||||
|
# TODO: this may not work, it's not used anywhere yet
|
||||||
|
class DateFilter(SimpleFilter):
|
||||||
|
|
||||||
|
data_type = "date"
|
||||||
|
|
||||||
|
default_verbs = [
|
||||||
|
"equal",
|
||||||
|
"not_equal",
|
||||||
|
"greater_than",
|
||||||
|
"greater_equal",
|
||||||
|
"less_than",
|
||||||
|
"less_equal",
|
||||||
|
# 'between',
|
||||||
|
]
|
||||||
|
|
||||||
|
default_verb_labels = {
|
||||||
|
"equal": "on",
|
||||||
|
"not_equal": "not on",
|
||||||
|
"greater_than": "after",
|
||||||
|
"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",
|
||||||
|
}
|
||||||
|
|
||||||
|
def coerce_value(self, value):
|
||||||
|
if value:
|
||||||
|
if isinstance(value, datetime.date):
|
||||||
|
return value
|
||||||
|
|
||||||
|
try:
|
||||||
|
dt = datetime.datetime.strptime(value, "%Y-%m-%d")
|
||||||
|
except ValueError:
|
||||||
|
log.warning("invalid date value: %s", value)
|
||||||
|
else:
|
||||||
|
return dt.date()
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
# TODO: this is not very complete yet, so far used only for animal birthdate
|
||||||
|
class DateTimeFilter(DateFilter):
|
||||||
|
|
||||||
|
default_verbs = ["equal", "is_null", "is_not_null"]
|
||||||
|
|
||||||
|
def coerce_value(self, value):
|
||||||
|
"""
|
||||||
|
Convert user input to a proper ``datetime.date`` object.
|
||||||
|
"""
|
||||||
|
if value:
|
||||||
|
if isinstance(value, datetime.date):
|
||||||
|
return value
|
||||||
|
|
||||||
|
try:
|
||||||
|
dt = datetime.datetime.strptime(value, "%Y-%m-%d")
|
||||||
|
except ValueError:
|
||||||
|
log.warning("invalid date value: %s", value)
|
||||||
|
else:
|
||||||
|
return dt.date()
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
def filter_equal(self, data, value):
|
||||||
|
if value := self.coerce_value(value):
|
||||||
|
|
||||||
|
start = datetime.datetime.combine(value, datetime.time(0))
|
||||||
|
start = self.app.localtime(start, from_utc=False)
|
||||||
|
|
||||||
|
stop = datetime.datetime.combine(
|
||||||
|
value + datetime.timedelta(days=1), datetime.time(0)
|
||||||
|
)
|
||||||
|
stop = self.app.localtime(stop, from_utc=False)
|
||||||
|
|
||||||
|
data.add_filter(self.path, ">=", int(start.timestamp()))
|
||||||
|
data.add_filter(self.path, "<", int(stop.timestamp()))
|
||||||
|
|
||||||
|
return data
|
||||||
|
|
||||||
|
|
||||||
class SimpleSorter:
|
class SimpleSorter:
|
||||||
|
|
||||||
def __init__(self, key):
|
def __init__(self, key):
|
||||||
|
|
@ -171,10 +255,13 @@ class ResourceData:
|
||||||
if self._data is None:
|
if self._data is None:
|
||||||
params = {}
|
params = {}
|
||||||
|
|
||||||
|
i = 0
|
||||||
for path, operator, value in self.filters:
|
for path, operator, value in self.filters:
|
||||||
params[f"filter[{path}][condition][path]"] = path
|
i += 1
|
||||||
params[f"filter[{path}][condition][operator]"] = operator
|
key = f"{i:03d}"
|
||||||
params[f"filter[{path}][condition][value]"] = value
|
params[f"filter[{key}][condition][path]"] = path
|
||||||
|
params[f"filter[{key}][condition][operator]"] = operator
|
||||||
|
params[f"filter[{key}][condition][value]"] = value
|
||||||
|
|
||||||
sorters = []
|
sorters = []
|
||||||
for path, sortdir in self.sorters:
|
for path, sortdir in self.sorters:
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,7 @@ from wuttafarm.web.grids import (
|
||||||
StringFilter,
|
StringFilter,
|
||||||
BooleanFilter,
|
BooleanFilter,
|
||||||
NullableBooleanFilter,
|
NullableBooleanFilter,
|
||||||
|
DateTimeFilter,
|
||||||
)
|
)
|
||||||
from wuttafarm.web.forms.schema import AnimalTypeType
|
from wuttafarm.web.forms.schema import AnimalTypeType
|
||||||
|
|
||||||
|
|
@ -120,6 +121,7 @@ class AnimalView(AssetMasterView):
|
||||||
# birthdate
|
# birthdate
|
||||||
g.set_renderer("birthdate", "date")
|
g.set_renderer("birthdate", "date")
|
||||||
g.set_sorter("birthdate", SimpleSorter("birthdate"))
|
g.set_sorter("birthdate", SimpleSorter("birthdate"))
|
||||||
|
g.set_filter("birthdate", DateTimeFilter)
|
||||||
|
|
||||||
# sex
|
# sex
|
||||||
g.set_enum("sex", enum.ANIMAL_SEX)
|
g.set_enum("sex", enum.ANIMAL_SEX)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue