feat: add basic CRUD for direct API views: animal types, animal assets
This commit is contained in:
parent
c976d94bdd
commit
ad6ac13d50
6 changed files with 351 additions and 97 deletions
|
|
@ -58,10 +58,50 @@ class AnimalTypeRef(ObjectRef):
|
|||
class FarmOSRef(colander.SchemaType):
|
||||
|
||||
def __init__(self, request, route_prefix, *args, **kwargs):
|
||||
self.values = kwargs.pop("values", None)
|
||||
super().__init__(*args, **kwargs)
|
||||
self.request = request
|
||||
self.route_prefix = route_prefix
|
||||
|
||||
def get_values(self):
|
||||
if callable(self.values):
|
||||
self.values = self.values()
|
||||
return self.values
|
||||
|
||||
def serialize(self, node, appstruct):
|
||||
if appstruct is colander.null:
|
||||
return colander.null
|
||||
|
||||
# nb. keep a ref to this for later use
|
||||
node.model_instance = appstruct
|
||||
|
||||
# serialize to PK as string
|
||||
return appstruct["uuid"]
|
||||
|
||||
def deserialize(self, node, cstruct):
|
||||
if not cstruct:
|
||||
return colander.null
|
||||
|
||||
# nb. deserialize to PK string, not dict
|
||||
return cstruct
|
||||
|
||||
def widget_maker(self, **kwargs):
|
||||
from wuttafarm.web.forms.widgets import FarmOSRefWidget
|
||||
|
||||
if not kwargs.get("readonly"):
|
||||
if "values" not in kwargs:
|
||||
if values := self.get_values():
|
||||
kwargs["values"] = values
|
||||
|
||||
return FarmOSRefWidget(self.request, self.route_prefix, **kwargs)
|
||||
|
||||
|
||||
class FarmOSRefs(WuttaSet):
|
||||
|
||||
def __init__(self, request, route_prefix, *args, **kwargs):
|
||||
super().__init__(request, *args, **kwargs)
|
||||
self.route_prefix = route_prefix
|
||||
|
||||
def serialize(self, node, appstruct):
|
||||
if appstruct is colander.null:
|
||||
return colander.null
|
||||
|
|
@ -69,10 +109,23 @@ class FarmOSRef(colander.SchemaType):
|
|||
return json.dumps(appstruct)
|
||||
|
||||
def widget_maker(self, **kwargs):
|
||||
""" """
|
||||
from wuttafarm.web.forms.widgets import FarmOSRefWidget
|
||||
from wuttafarm.web.forms.widgets import FarmOSRefsWidget
|
||||
|
||||
return FarmOSRefWidget(self.request, self.route_prefix, **kwargs)
|
||||
return FarmOSRefsWidget(self.request, self.route_prefix, **kwargs)
|
||||
|
||||
|
||||
class FarmOSLocationRefs(WuttaSet):
|
||||
|
||||
def serialize(self, node, appstruct):
|
||||
if appstruct is colander.null:
|
||||
return colander.null
|
||||
|
||||
return json.dumps(appstruct)
|
||||
|
||||
def widget_maker(self, **kwargs):
|
||||
from wuttafarm.web.forms.widgets import FarmOSLocationRefsWidget
|
||||
|
||||
return FarmOSLocationRefsWidget(self.request, **kwargs)
|
||||
|
||||
|
||||
class AnimalTypeType(colander.SchemaType):
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ Custom form widgets for WuttaFarm
|
|||
import json
|
||||
|
||||
import colander
|
||||
from deform.widget import Widget
|
||||
from deform.widget import Widget, SelectWidget
|
||||
from webhelpers2.html import HTML, tags
|
||||
|
||||
from wuttaweb.forms.widgets import WuttaCheckboxChoiceWidget
|
||||
|
|
@ -54,7 +54,7 @@ class ImageWidget(Widget):
|
|||
return super().serialize(field, cstruct, **kw)
|
||||
|
||||
|
||||
class FarmOSRefWidget(Widget):
|
||||
class FarmOSRefWidget(SelectWidget):
|
||||
"""
|
||||
Generic widget to display "any reference field" - as a link to
|
||||
view the farmOS record it references. Only used by the farmOS
|
||||
|
|
@ -72,7 +72,12 @@ class FarmOSRefWidget(Widget):
|
|||
if cstruct in (colander.null, None):
|
||||
return HTML.tag("span")
|
||||
|
||||
try:
|
||||
obj = json.loads(cstruct)
|
||||
except json.JSONDecodeError:
|
||||
name = dict(self.values)[cstruct]
|
||||
obj = {"uuid": cstruct, "name": name}
|
||||
|
||||
return tags.link_to(
|
||||
obj["name"],
|
||||
self.request.route_url(f"{self.route_prefix}.view", uuid=obj["uuid"]),
|
||||
|
|
@ -81,6 +86,59 @@ class FarmOSRefWidget(Widget):
|
|||
return super().serialize(field, cstruct, **kw)
|
||||
|
||||
|
||||
class FarmOSRefsWidget(Widget):
|
||||
|
||||
def __init__(self, request, route_prefix, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.request = request
|
||||
self.route_prefix = route_prefix
|
||||
|
||||
def serialize(self, field, cstruct, **kw):
|
||||
readonly = kw.get("readonly", self.readonly)
|
||||
if readonly:
|
||||
if cstruct in (colander.null, None):
|
||||
return HTML.tag("span")
|
||||
|
||||
links = []
|
||||
for obj in json.loads(cstruct):
|
||||
url = self.request.route_url(
|
||||
f"{self.route_prefix}.view", uuid=obj["uuid"]
|
||||
)
|
||||
links.append(HTML.tag("li", c=tags.link_to(obj["name"], url)))
|
||||
|
||||
return HTML.tag("ul", c=links)
|
||||
|
||||
return super().serialize(field, cstruct, **kw)
|
||||
|
||||
|
||||
class FarmOSLocationRefsWidget(Widget):
|
||||
"""
|
||||
Widget to display a "Locations" field for an asset.
|
||||
"""
|
||||
|
||||
def __init__(self, request, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.request = request
|
||||
|
||||
def serialize(self, field, cstruct, **kw):
|
||||
readonly = kw.get("readonly", self.readonly)
|
||||
if readonly:
|
||||
if cstruct in (colander.null, None):
|
||||
return HTML.tag("span")
|
||||
|
||||
locations = []
|
||||
for location in json.loads(cstruct):
|
||||
asset_type = location["type"].split("--")[1]
|
||||
url = self.request.route_url(
|
||||
f"farmos_{asset_type}_assets.view", uuid=location["uuid"]
|
||||
)
|
||||
locations.append(HTML.tag("li", c=tags.link_to(location["name"], url)))
|
||||
|
||||
return HTML.tag("ul", c=locations)
|
||||
|
||||
return super().serialize(field, cstruct, **kw)
|
||||
|
||||
|
||||
class AnimalTypeWidget(Widget):
|
||||
"""
|
||||
Widget to display an "animal type" field.
|
||||
|
|
|
|||
|
|
@ -167,9 +167,9 @@ class AnimalAssetView(AssetMasterView):
|
|||
"asset_name",
|
||||
"animal_type",
|
||||
"birthdate",
|
||||
"produces_eggs",
|
||||
"sex",
|
||||
"is_sterile",
|
||||
"produces_eggs",
|
||||
"notes",
|
||||
"asset_type",
|
||||
"archived",
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ import datetime
|
|||
import colander
|
||||
from webhelpers2.html import tags
|
||||
|
||||
from wuttaweb.forms.schema import WuttaDateTime
|
||||
from wuttaweb.forms.schema import WuttaDateTime, WuttaDictEnum
|
||||
from wuttaweb.forms.widgets import WuttaDateTimeWidget
|
||||
|
||||
from wuttafarm.web.views.farmos.assets import AssetMasterView
|
||||
|
|
@ -39,7 +39,7 @@ from wuttafarm.web.grids import (
|
|||
NullableBooleanFilter,
|
||||
DateTimeFilter,
|
||||
)
|
||||
from wuttafarm.web.forms.schema import AnimalTypeType
|
||||
from wuttafarm.web.forms.schema import FarmOSRef
|
||||
|
||||
|
||||
class AnimalView(AssetMasterView):
|
||||
|
|
@ -85,20 +85,23 @@ class AnimalView(AssetMasterView):
|
|||
"produces_eggs",
|
||||
"sex",
|
||||
"is_sterile",
|
||||
"archived",
|
||||
"notes",
|
||||
"asset_type_name",
|
||||
"groups",
|
||||
"owners",
|
||||
"location",
|
||||
"notes",
|
||||
"raw_image_url",
|
||||
"large_image_url",
|
||||
"thumbnail_image_url",
|
||||
"locations",
|
||||
"archived",
|
||||
"thumbnail_url",
|
||||
"image_url",
|
||||
"thumbnail",
|
||||
"image",
|
||||
]
|
||||
|
||||
def get_grid_data(self, **kwargs):
|
||||
kwargs.setdefault("include", "image,animal_type,group,owner,location")
|
||||
return super().get_grid_data(**kwargs)
|
||||
def get_farmos_api_includes(self):
|
||||
includes = super().get_farmos_api_includes()
|
||||
includes.add("animal_type")
|
||||
includes.add("group")
|
||||
return includes
|
||||
|
||||
def configure_grid(self, grid):
|
||||
g = grid
|
||||
|
|
@ -188,19 +191,17 @@ class AnimalView(AssetMasterView):
|
|||
else:
|
||||
sterile = animal["attributes"]["is_castrated"]
|
||||
|
||||
animal_type = None
|
||||
animal_type_name = None
|
||||
animal_type_object = None
|
||||
group_objects = []
|
||||
group_names = []
|
||||
if relationships := animal.get("relationships"):
|
||||
|
||||
if animal_type := relationships.get("animal_type"):
|
||||
if animal_type := included.get(animal_type["data"]["id"]):
|
||||
animal_type = {
|
||||
animal_type_object = {
|
||||
"uuid": animal_type["id"],
|
||||
"name": animal_type["attributes"]["name"],
|
||||
}
|
||||
animal_type_name = animal_type["name"]
|
||||
|
||||
if groups := relationships.get("group"):
|
||||
for group in groups["data"]:
|
||||
|
|
@ -214,8 +215,9 @@ class AnimalView(AssetMasterView):
|
|||
|
||||
normal.update(
|
||||
{
|
||||
"animal_type": animal_type,
|
||||
"animal_type_name": animal_type_name,
|
||||
"animal_type": animal_type_object,
|
||||
"animal_type_uuid": animal_type_object["uuid"],
|
||||
"animal_type_name": animal_type_object["name"],
|
||||
"group_objects": group_objects,
|
||||
"group_names": group_names,
|
||||
"birthdate": birthdate,
|
||||
|
|
@ -227,23 +229,78 @@ class AnimalView(AssetMasterView):
|
|||
|
||||
return normal
|
||||
|
||||
def get_animal_types(self):
|
||||
animal_types = []
|
||||
result = self.farmos_client.resource.get(
|
||||
"taxonomy_term", "animal_type", params={"sort": "name"}
|
||||
)
|
||||
for animal_type in result["data"]:
|
||||
animal_types.append((animal_type["id"], animal_type["attributes"]["name"]))
|
||||
return animal_types
|
||||
|
||||
def configure_form(self, form):
|
||||
f = form
|
||||
super().configure_form(f)
|
||||
enum = self.app.enum
|
||||
animal = f.model_instance
|
||||
|
||||
# animal_type
|
||||
f.set_node("animal_type", AnimalTypeType(self.request))
|
||||
|
||||
# birthdate
|
||||
f.set_node("birthdate", WuttaDateTime())
|
||||
f.set_widget("birthdate", WuttaDateTimeWidget(self.request))
|
||||
f.set_node(
|
||||
"animal_type",
|
||||
FarmOSRef(
|
||||
self.request, "farmos_animal_types", values=self.get_animal_types
|
||||
),
|
||||
)
|
||||
|
||||
# produces_eggs
|
||||
f.set_node("produces_eggs", colander.Boolean())
|
||||
|
||||
# birthdate
|
||||
f.set_node("birthdate", WuttaDateTime())
|
||||
f.set_widget("birthdate", WuttaDateTimeWidget(self.request))
|
||||
f.set_required("birthdate", False)
|
||||
|
||||
# sex
|
||||
if not (self.creating or self.editing) and not animal["sex"]:
|
||||
pass # TODO: dict enum widget does not handle null values well
|
||||
else:
|
||||
f.set_node("sex", WuttaDictEnum(self.request, enum.ANIMAL_SEX))
|
||||
f.set_required("sex", False)
|
||||
|
||||
# is_sterile
|
||||
f.set_node("is_sterile", colander.Boolean())
|
||||
|
||||
# groups
|
||||
if self.creating or self.editing:
|
||||
f.remove("groups") # TODO
|
||||
|
||||
def get_api_payload(self, animal):
|
||||
payload = super().get_api_payload(animal)
|
||||
|
||||
birthdate = None
|
||||
if animal["birthdate"]:
|
||||
birthdate = self.app.localtime(animal["birthdate"]).timestamp()
|
||||
|
||||
attrs = {
|
||||
"sex": animal["sex"] or None,
|
||||
"is_sterile": animal["is_sterile"],
|
||||
"produces_eggs": animal["produces_eggs"],
|
||||
"birthdate": birthdate,
|
||||
}
|
||||
|
||||
rels = {
|
||||
"animal_type": {
|
||||
"data": {
|
||||
"id": animal["animal_type"],
|
||||
"type": "taxonomy_term--animal_type",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
payload["attributes"].update(attrs)
|
||||
payload.setdefault("relationships", {}).update(rels)
|
||||
return payload
|
||||
|
||||
def get_xref_buttons(self, animal):
|
||||
buttons = super().get_xref_buttons(animal)
|
||||
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ import colander
|
|||
from webhelpers2.html import tags
|
||||
|
||||
from wuttafarm.web.views.farmos import FarmOSMasterView
|
||||
from wuttafarm.web.forms.schema import UsersType, StructureType
|
||||
from wuttafarm.web.forms.schema import FarmOSRefs, FarmOSLocationRefs
|
||||
from wuttafarm.web.forms.widgets import ImageWidget
|
||||
from wuttafarm.web.grids import (
|
||||
ResourceData,
|
||||
|
|
@ -44,13 +44,19 @@ class AssetMasterView(FarmOSMasterView):
|
|||
"""
|
||||
|
||||
farmos_asset_type = None
|
||||
creatable = True
|
||||
editable = True
|
||||
deletable = True
|
||||
filterable = True
|
||||
sort_on_backend = True
|
||||
|
||||
labels = {
|
||||
"name": "Asset Name",
|
||||
"asset_type_name": "Asset Type",
|
||||
"owners": "Owner",
|
||||
"locations": "Location",
|
||||
"thumbnail_url": "Thumbnail URL",
|
||||
"image_url": "Image URL",
|
||||
}
|
||||
|
||||
grid_columns = [
|
||||
|
|
@ -69,14 +75,13 @@ class AssetMasterView(FarmOSMasterView):
|
|||
"archived": {"active": True, "verb": "is_false"},
|
||||
}
|
||||
|
||||
def get_grid_data(self, columns=None, session=None, **kwargs):
|
||||
kwargs.setdefault("include", "image,owner,location")
|
||||
kwargs.setdefault("normalizer", self.normalize_asset)
|
||||
def get_grid_data(self, **kwargs):
|
||||
return ResourceData(
|
||||
self.config,
|
||||
self.farmos_client,
|
||||
f"asset--{self.farmos_asset_type}",
|
||||
**kwargs,
|
||||
include=",".join(self.get_farmos_api_includes()),
|
||||
normalizer=self.normalize_asset,
|
||||
)
|
||||
|
||||
def configure_grid(self, grid):
|
||||
|
|
@ -142,60 +147,19 @@ class AssetMasterView(FarmOSMasterView):
|
|||
return "has-background-warning"
|
||||
return None
|
||||
|
||||
def get_farmos_api_includes(self):
|
||||
return {"asset_type", "location", "owner", "image"}
|
||||
|
||||
def get_instance(self):
|
||||
asset = self.farmos_client.resource.get_id(
|
||||
"asset", self.farmos_asset_type, self.request.matchdict["uuid"]
|
||||
"asset",
|
||||
self.farmos_asset_type,
|
||||
self.request.matchdict["uuid"],
|
||||
params={"include": ",".join(self.get_farmos_api_includes())},
|
||||
)
|
||||
self.raw_json = asset
|
||||
|
||||
# instance data
|
||||
data = self.normalize_asset(asset["data"], {})
|
||||
|
||||
if relationships := asset["data"].get("relationships"):
|
||||
|
||||
# add location
|
||||
if location := relationships.get("location"):
|
||||
if location["data"]:
|
||||
location = self.farmos_client.resource.get_id(
|
||||
"asset", "structure", location["data"][0]["id"]
|
||||
)
|
||||
data["location"] = {
|
||||
"uuid": location["data"]["id"],
|
||||
"name": location["data"]["attributes"]["name"],
|
||||
}
|
||||
|
||||
# add owners
|
||||
if owner := relationships.get("owner"):
|
||||
data["owners"] = []
|
||||
for owner_data in owner["data"]:
|
||||
owner = self.farmos_client.resource.get_id(
|
||||
"user", "user", owner_data["id"]
|
||||
)
|
||||
data["owners"].append(
|
||||
{
|
||||
"uuid": owner["data"]["id"],
|
||||
"display_name": owner["data"]["attributes"]["display_name"],
|
||||
}
|
||||
)
|
||||
|
||||
# add image urls
|
||||
if image := relationships.get("image"):
|
||||
if image["data"]:
|
||||
image = self.farmos_client.resource.get_id(
|
||||
"file", "file", image["data"][0]["id"]
|
||||
)
|
||||
data["raw_image_url"] = self.app.get_farmos_url(
|
||||
image["data"]["attributes"]["uri"]["url"]
|
||||
)
|
||||
# nb. other styles available: medium, wide
|
||||
data["large_image_url"] = image["data"]["attributes"][
|
||||
"image_style_uri"
|
||||
]["large"]
|
||||
data["thumbnail_image_url"] = image["data"]["attributes"][
|
||||
"image_style_uri"
|
||||
]["thumbnail"]
|
||||
|
||||
return data
|
||||
included = {obj["id"]: obj for obj in asset.get("included", [])}
|
||||
return self.normalize_asset(asset["data"], included)
|
||||
|
||||
def get_instance_title(self, asset):
|
||||
return asset["name"]
|
||||
|
|
@ -210,13 +174,24 @@ class AssetMasterView(FarmOSMasterView):
|
|||
else:
|
||||
archived = asset["attributes"]["status"] == "archived"
|
||||
|
||||
asset_type_object = {}
|
||||
asset_type_name = None
|
||||
owner_objects = []
|
||||
owner_names = []
|
||||
location_objects = []
|
||||
location_names = []
|
||||
thumbnail_url = None
|
||||
image_url = None
|
||||
if relationships := asset.get("relationships"):
|
||||
|
||||
if asset_type := relationships.get("asset_type"):
|
||||
if asset_type := included.get(asset_type["data"]["id"]):
|
||||
asset_type_object = {
|
||||
"uuid": asset_type["id"],
|
||||
"name": asset_type["attributes"]["label"],
|
||||
}
|
||||
asset_type_name = asset_type_object["name"]
|
||||
|
||||
if owners := relationships.get("owner"):
|
||||
for user in owners["data"]:
|
||||
if user := included.get(user["id"]):
|
||||
|
|
@ -244,42 +219,102 @@ class AssetMasterView(FarmOSMasterView):
|
|||
thumbnail_url = image["attributes"]["image_style_uri"][
|
||||
"thumbnail"
|
||||
]
|
||||
image_url = image["attributes"]["image_style_uri"]["large"]
|
||||
|
||||
return {
|
||||
"uuid": asset["id"],
|
||||
"drupal_id": asset["attributes"]["drupal_internal__id"],
|
||||
"name": asset["attributes"]["name"],
|
||||
"location": colander.null, # TODO
|
||||
"asset_type": asset_type_object,
|
||||
"asset_type_name": asset_type_name,
|
||||
"notes": notes or colander.null,
|
||||
"owners": owner_objects,
|
||||
"owner_names": owner_names,
|
||||
"locations": location_objects,
|
||||
"location_names": location_names,
|
||||
"archived": archived,
|
||||
"thumbnail_url": thumbnail_url,
|
||||
"thumbnail_url": thumbnail_url or colander.null,
|
||||
"image_url": image_url or colander.null,
|
||||
}
|
||||
|
||||
def configure_form(self, form):
|
||||
f = form
|
||||
super().configure_form(f)
|
||||
animal = f.model_instance
|
||||
asset = f.model_instance
|
||||
|
||||
# location
|
||||
f.set_node("location", StructureType(self.request))
|
||||
# asset_type_name
|
||||
if self.creating or self.editing:
|
||||
f.remove("asset_type_name")
|
||||
|
||||
# locations
|
||||
if self.creating or self.editing:
|
||||
f.remove("locations")
|
||||
else:
|
||||
f.set_node("locations", FarmOSLocationRefs(self.request))
|
||||
|
||||
# owners
|
||||
f.set_node("owners", UsersType(self.request))
|
||||
if self.creating or self.editing:
|
||||
f.remove("owners") # TODO
|
||||
else:
|
||||
f.set_node("owners", FarmOSRefs(self.request, "farmos_users"))
|
||||
|
||||
# notes
|
||||
f.set_widget("notes", "notes")
|
||||
f.set_required("notes", False)
|
||||
|
||||
# archived
|
||||
f.set_node("archived", colander.Boolean())
|
||||
|
||||
# thumbnail_url
|
||||
if self.creating or self.editing:
|
||||
f.remove("thumbnail_url")
|
||||
|
||||
# image_url
|
||||
if self.creating or self.editing:
|
||||
f.remove("image_url")
|
||||
|
||||
# thumbnail
|
||||
if self.creating or self.editing:
|
||||
f.remove("thumbnail")
|
||||
elif asset.get("thumbnail_url"):
|
||||
f.set_widget("thumbnail", ImageWidget("asset thumbnail"))
|
||||
f.set_default("thumbnail", asset["thumbnail_url"])
|
||||
|
||||
# image
|
||||
if url := animal.get("large_image_url"):
|
||||
f.set_widget("image", ImageWidget("animal image"))
|
||||
f.set_default("image", url)
|
||||
if self.creating or self.editing:
|
||||
f.remove("image")
|
||||
elif asset.get("image_url"):
|
||||
f.set_widget("image", ImageWidget("asset image"))
|
||||
f.set_default("image", asset["image_url"])
|
||||
|
||||
def persist(self, asset, session=None):
|
||||
payload = self.get_api_payload(asset)
|
||||
if self.editing:
|
||||
payload["id"] = asset["uuid"]
|
||||
|
||||
result = self.farmos_client.asset.send(self.farmos_asset_type, payload)
|
||||
|
||||
if self.creating:
|
||||
asset["uuid"] = result["data"]["id"]
|
||||
|
||||
def get_api_payload(self, asset):
|
||||
|
||||
attrs = {
|
||||
"name": asset["name"],
|
||||
"notes": {"value": asset["notes"] or None},
|
||||
"archived": asset["archived"],
|
||||
}
|
||||
|
||||
if "is_location" in asset:
|
||||
attrs["is_location"] = asset["is_location"]
|
||||
|
||||
if "is_fixed" in asset:
|
||||
attrs["is_fixed"] = asset["is_fixed"]
|
||||
|
||||
return {"attributes": attrs}
|
||||
|
||||
def delete_instance(self, asset):
|
||||
self.farmos_client.asset.delete(self.farmos_asset_type, asset["uuid"])
|
||||
|
||||
def get_xref_buttons(self, asset):
|
||||
return [
|
||||
|
|
|
|||
|
|
@ -31,9 +31,16 @@ import markdown
|
|||
|
||||
from wuttaweb.views import MasterView
|
||||
from wuttaweb.forms.schema import WuttaDateTime
|
||||
from wuttaweb.forms.widgets import WuttaDateTimeWidget
|
||||
|
||||
from wuttafarm.web.util import save_farmos_oauth2_token, use_farmos_style_grid_links
|
||||
from wuttafarm.web.grids import ResourceData, StringFilter, SimpleSorter
|
||||
from wuttafarm.web.grids import (
|
||||
ResourceData,
|
||||
StringFilter,
|
||||
NullableStringFilter,
|
||||
DateTimeFilter,
|
||||
SimpleSorter,
|
||||
)
|
||||
|
||||
|
||||
class FarmOSMasterView(MasterView):
|
||||
|
|
@ -114,6 +121,9 @@ class TaxonomyMasterView(FarmOSMasterView):
|
|||
"""
|
||||
|
||||
farmos_taxonomy_type = None
|
||||
creatable = True
|
||||
editable = True
|
||||
deletable = True
|
||||
filterable = True
|
||||
sort_on_backend = True
|
||||
|
||||
|
|
@ -143,7 +153,7 @@ class TaxonomyMasterView(FarmOSMasterView):
|
|||
normalizer=self.normalize_taxonomy_term,
|
||||
)
|
||||
|
||||
def normalize_taxonomy_term(self, term):
|
||||
def normalize_taxonomy_term(self, term, included):
|
||||
|
||||
if changed := term["attributes"]["changed"]:
|
||||
changed = datetime.datetime.fromisoformat(changed)
|
||||
|
|
@ -169,15 +179,21 @@ class TaxonomyMasterView(FarmOSMasterView):
|
|||
g.set_sorter("name", SimpleSorter("name"))
|
||||
g.set_filter("name", StringFilter)
|
||||
|
||||
# description
|
||||
g.set_sorter("description", SimpleSorter("description.value"))
|
||||
g.set_filter("description", NullableStringFilter, path="description.value")
|
||||
|
||||
# changed
|
||||
g.set_renderer("changed", "datetime")
|
||||
g.set_sorter("changed", SimpleSorter("changed"))
|
||||
g.set_filter("changed", DateTimeFilter)
|
||||
|
||||
def get_instance(self):
|
||||
result = self.farmos_client.resource.get_id(
|
||||
"taxonomy_term", self.farmos_taxonomy_type, self.request.matchdict["uuid"]
|
||||
)
|
||||
self.raw_json = result
|
||||
return self.normalize_taxonomy_term(result["data"])
|
||||
return self.normalize_taxonomy_term(result["data"], {})
|
||||
|
||||
def get_instance_title(self, term):
|
||||
return term["name"]
|
||||
|
|
@ -188,9 +204,44 @@ class TaxonomyMasterView(FarmOSMasterView):
|
|||
|
||||
# description
|
||||
f.set_widget("description", "notes")
|
||||
f.set_required("description", False)
|
||||
|
||||
# changed
|
||||
if self.creating or self.editing:
|
||||
f.remove("changed")
|
||||
else:
|
||||
f.set_node("changed", WuttaDateTime())
|
||||
f.set_widget("changed", WuttaDateTimeWidget(self.request))
|
||||
|
||||
def get_api_payload(self, term):
|
||||
|
||||
attrs = {
|
||||
"name": term["name"],
|
||||
}
|
||||
|
||||
if description := term["description"]:
|
||||
attrs["description"] = {"value": description}
|
||||
else:
|
||||
attrs["description"] = None
|
||||
|
||||
return {"attributes": attrs}
|
||||
|
||||
def persist(self, term, session=None):
|
||||
payload = self.get_api_payload(term)
|
||||
if self.editing:
|
||||
payload["id"] = term["uuid"]
|
||||
|
||||
result = self.farmos_client.resource.send(
|
||||
"taxonomy_term", self.farmos_taxonomy_type, payload
|
||||
)
|
||||
|
||||
if self.creating:
|
||||
term["uuid"] = result["data"]["id"]
|
||||
|
||||
def delete_instance(self, term):
|
||||
self.farmos_client.resource.delete(
|
||||
"taxonomy_term", self.farmos_taxonomy_type, term["uuid"]
|
||||
)
|
||||
|
||||
def get_xref_buttons(self, term):
|
||||
return [
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue