feat: use 'include' API param for better Animal Assets grid data
this commit also renames all farmOS asset routes, for some reason. at least now they are consistent
This commit is contained in:
parent
bbb1207b27
commit
1af2b695dc
10 changed files with 188 additions and 71 deletions
|
|
@ -189,7 +189,7 @@ class StructureWidget(Widget):
|
|||
return tags.link_to(
|
||||
structure["name"],
|
||||
self.request.route_url(
|
||||
"farmos_structures.view", uuid=structure["uuid"]
|
||||
"farmos_structure_assets.view", uuid=structure["uuid"]
|
||||
),
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -135,12 +135,20 @@ class SimpleSorter:
|
|||
|
||||
class ResourceData:
|
||||
|
||||
def __init__(self, config, farmos_client, content_type, normalizer=None):
|
||||
def __init__(
|
||||
self,
|
||||
config,
|
||||
farmos_client,
|
||||
content_type,
|
||||
include=None,
|
||||
normalizer=None,
|
||||
):
|
||||
self.config = config
|
||||
self.farmos_client = farmos_client
|
||||
self.entity, self.bundle = content_type.split("--")
|
||||
self.filters = []
|
||||
self.sorters = []
|
||||
self.include = include
|
||||
self.normalizer = normalizer
|
||||
self._data = None
|
||||
|
||||
|
|
@ -189,12 +197,17 @@ class ResourceData:
|
|||
# params["page[offset]"] = start
|
||||
# params["page[limit]"] = stop - start
|
||||
|
||||
if self.include:
|
||||
params["include"] = self.include
|
||||
|
||||
result = self.farmos_client.resource.get(
|
||||
self.entity, self.bundle, params=params
|
||||
)
|
||||
data = result["data"]
|
||||
included = {obj["id"]: obj for obj in result.get("included", [])}
|
||||
|
||||
if self.normalizer:
|
||||
data = [self.normalizer(d) for d in data]
|
||||
data = [self.normalizer(d, included) for d in data]
|
||||
|
||||
self._data = data
|
||||
return self._data
|
||||
|
|
|
|||
|
|
@ -202,13 +202,13 @@ class WuttaFarmMenuHandler(base.MenuHandler):
|
|||
{"type": "sep"},
|
||||
{
|
||||
"title": "Animal Assets",
|
||||
"route": "farmos_assets_animal",
|
||||
"perm": "farmos_assets_animal.list",
|
||||
"route": "farmos_animal_assets",
|
||||
"perm": "farmos_animal_assets.list",
|
||||
},
|
||||
{
|
||||
"title": "Group Assets",
|
||||
"route": "farmos_groups",
|
||||
"perm": "farmos_groups.list",
|
||||
"route": "farmos_group_assets",
|
||||
"perm": "farmos_group_assets.list",
|
||||
},
|
||||
{
|
||||
"title": "Land Assets",
|
||||
|
|
@ -217,13 +217,13 @@ class WuttaFarmMenuHandler(base.MenuHandler):
|
|||
},
|
||||
{
|
||||
"title": "Plant Assets",
|
||||
"route": "farmos_asset_plant",
|
||||
"perm": "farmos_asset_plant.list",
|
||||
"route": "farmos_plant_assets",
|
||||
"perm": "farmos_plant_assets.list",
|
||||
},
|
||||
{
|
||||
"title": "Structure Assets",
|
||||
"route": "farmos_structures",
|
||||
"perm": "farmos_structures.list",
|
||||
"route": "farmos_structure_assets",
|
||||
"perm": "farmos_structure_assets.list",
|
||||
},
|
||||
{"type": "sep"},
|
||||
{
|
||||
|
|
@ -311,13 +311,13 @@ class WuttaFarmMenuHandler(base.MenuHandler):
|
|||
"items": [
|
||||
{
|
||||
"title": "Animal",
|
||||
"route": "farmos_assets_animal",
|
||||
"perm": "farmos_assets_animal.list",
|
||||
"route": "farmos_animal_assets",
|
||||
"perm": "farmos_animal_assets.list",
|
||||
},
|
||||
{
|
||||
"title": "Group",
|
||||
"route": "farmos_groups",
|
||||
"perm": "farmos_groups.list",
|
||||
"route": "farmos_group_assets",
|
||||
"perm": "farmos_group_assets.list",
|
||||
},
|
||||
{
|
||||
"title": "Land",
|
||||
|
|
@ -326,13 +326,13 @@ class WuttaFarmMenuHandler(base.MenuHandler):
|
|||
},
|
||||
{
|
||||
"title": "Plant",
|
||||
"route": "farmos_asset_plant",
|
||||
"perm": "farmos_asset_plant.list",
|
||||
"route": "farmos_plant_assets",
|
||||
"perm": "farmos_plant_assets.list",
|
||||
},
|
||||
{
|
||||
"title": "Structure",
|
||||
"route": "farmos_structures",
|
||||
"perm": "farmos_structures.list",
|
||||
"route": "farmos_structure_assets",
|
||||
"perm": "farmos_structure_assets.list",
|
||||
},
|
||||
{"type": "sep"},
|
||||
{
|
||||
|
|
|
|||
|
|
@ -278,29 +278,14 @@ class AssetMasterView(WuttaFarmMasterView):
|
|||
buttons = super().get_xref_buttons(asset)
|
||||
|
||||
if asset.farmos_uuid:
|
||||
|
||||
# TODO
|
||||
route = None
|
||||
if asset.asset_type == "animal":
|
||||
route = "farmos_assets_animal.view"
|
||||
elif asset.asset_type == "group":
|
||||
route = "farmos_groups.view"
|
||||
elif asset.asset_type == "land":
|
||||
route = "farmos_land_assets.view"
|
||||
elif asset.asset_type == "plant":
|
||||
route = "farmos_asset_plant.view"
|
||||
elif asset.asset_type == "structure":
|
||||
route = "farmos_structures.view"
|
||||
|
||||
if route:
|
||||
buttons.append(
|
||||
self.make_button(
|
||||
"View farmOS record",
|
||||
primary=True,
|
||||
url=self.request.route_url(route, uuid=asset.farmos_uuid),
|
||||
icon_left="eye",
|
||||
)
|
||||
asset_type = self.get_model_class().__wutta_hint__["farmos_asset_type"]
|
||||
route = f"farmos_{asset_type}_assets.view"
|
||||
url = self.request.route_url(route, uuid=asset.farmos_uuid)
|
||||
buttons.append(
|
||||
self.make_button(
|
||||
"View farmOS record", primary=True, url=url, icon_left="eye"
|
||||
)
|
||||
)
|
||||
|
||||
return buttons
|
||||
|
||||
|
|
|
|||
|
|
@ -65,14 +65,14 @@ class CommonView(base.CommonView):
|
|||
"asset_types.list",
|
||||
"asset_types.view",
|
||||
"asset_types.versions",
|
||||
"farmos_animal_assets.list",
|
||||
"farmos_animal_assets.view",
|
||||
"farmos_animal_types.list",
|
||||
"farmos_animal_types.view",
|
||||
"farmos_assets_animal.list",
|
||||
"farmos_assets_animal.view",
|
||||
"farmos_asset_types.list",
|
||||
"farmos_asset_types.view",
|
||||
"farmos_groups.list",
|
||||
"farmos_groups.view",
|
||||
"farmos_group_assets.list",
|
||||
"farmos_group_assets.view",
|
||||
"farmos_land_assets.list",
|
||||
"farmos_land_assets.view",
|
||||
"farmos_land_types.list",
|
||||
|
|
@ -87,10 +87,10 @@ class CommonView(base.CommonView):
|
|||
"farmos_logs_medical.view",
|
||||
"farmos_logs_observation.list",
|
||||
"farmos_logs_observation.view",
|
||||
"farmos_structure_assets.list",
|
||||
"farmos_structure_assets.view",
|
||||
"farmos_structure_types.list",
|
||||
"farmos_structure_types.view",
|
||||
"farmos_structures.list",
|
||||
"farmos_structures.view",
|
||||
"farmos_users.list",
|
||||
"farmos_users.view",
|
||||
"group_assets.create",
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ Master view for Farm Animals
|
|||
import datetime
|
||||
|
||||
import colander
|
||||
from webhelpers2.html import tags
|
||||
|
||||
from wuttaweb.forms.schema import WuttaDateTime
|
||||
from wuttaweb.forms.widgets import WuttaDateTimeWidget
|
||||
|
|
@ -45,11 +46,11 @@ class AnimalView(AssetMasterView):
|
|||
Master view for Farm Animals
|
||||
"""
|
||||
|
||||
model_name = "farmos_animal_asset"
|
||||
model_name = "farmos_animal_assets"
|
||||
model_title = "farmOS Animal Asset"
|
||||
model_title_plural = "farmOS Animal Assets"
|
||||
|
||||
route_prefix = "farmos_assets_animal"
|
||||
route_prefix = "farmos_animal_assets"
|
||||
url_prefix = "/farmOS/assets/animal"
|
||||
|
||||
farmos_asset_type = "animal"
|
||||
|
|
@ -57,6 +58,7 @@ class AnimalView(AssetMasterView):
|
|||
|
||||
labels = {
|
||||
"animal_type": "Species / Breed",
|
||||
"animal_type_name": "Species / Breed",
|
||||
"is_sterile": "Sterile",
|
||||
}
|
||||
|
||||
|
|
@ -64,9 +66,13 @@ class AnimalView(AssetMasterView):
|
|||
"drupal_id",
|
||||
"name",
|
||||
"produces_eggs",
|
||||
"animal_type_name",
|
||||
"birthdate",
|
||||
"is_sterile",
|
||||
"sex",
|
||||
"groups",
|
||||
"owners",
|
||||
"locations",
|
||||
"archived",
|
||||
]
|
||||
|
||||
|
|
@ -78,6 +84,7 @@ class AnimalView(AssetMasterView):
|
|||
"sex",
|
||||
"is_sterile",
|
||||
"archived",
|
||||
"groups",
|
||||
"owners",
|
||||
"location",
|
||||
"notes",
|
||||
|
|
@ -87,6 +94,10 @@ class AnimalView(AssetMasterView):
|
|||
"image",
|
||||
]
|
||||
|
||||
def get_grid_data(self, **kwargs):
|
||||
kwargs.setdefault("include", "animal_type,group,owner,location")
|
||||
return super().get_grid_data(**kwargs)
|
||||
|
||||
def configure_grid(self, grid):
|
||||
g = grid
|
||||
super().configure_grid(g)
|
||||
|
|
@ -97,6 +108,11 @@ class AnimalView(AssetMasterView):
|
|||
g.set_sorter("produces_eggs", SimpleSorter("produces_eggs"))
|
||||
g.set_filter("produces_eggs", NullableBooleanFilter)
|
||||
|
||||
# animal_type_name
|
||||
g.set_renderer("animal_type_name", self.render_animal_type_for_grid)
|
||||
g.set_sorter("animal_type_name", SimpleSorter("animal_type.name"))
|
||||
g.set_filter("animal_type_name", StringFilter, path="animal_type.name")
|
||||
|
||||
# birthdate
|
||||
g.set_renderer("birthdate", "date")
|
||||
g.set_sorter("birthdate", SimpleSorter("birthdate"))
|
||||
|
|
@ -106,11 +122,27 @@ class AnimalView(AssetMasterView):
|
|||
g.set_sorter("sex", SimpleSorter("sex"))
|
||||
g.set_filter("sex", StringFilter)
|
||||
|
||||
# groups
|
||||
g.set_label("groups", "Group Membership")
|
||||
g.set_renderer("groups", self.render_groups_for_grid)
|
||||
|
||||
# is_sterile
|
||||
g.set_renderer("is_sterile", "boolean")
|
||||
g.set_sorter("is_sterile", SimpleSorter("is_sterile"))
|
||||
g.set_filter("is_sterile", BooleanFilter)
|
||||
|
||||
def render_animal_type_for_grid(self, animal, field, value):
|
||||
uuid = animal["animal_type"]["uuid"]
|
||||
url = self.request.route_url("farmos_animal_types.view", uuid=uuid)
|
||||
return tags.link_to(value, url)
|
||||
|
||||
def render_groups_for_grid(self, animal, field, value):
|
||||
links = []
|
||||
for group in animal["group_objects"]:
|
||||
url = self.request.route_url("farmos_group_assets.view", uuid=group["uuid"])
|
||||
links.append(tags.link_to(group["name"], url))
|
||||
return ", ".join(links)
|
||||
|
||||
def get_instance(self):
|
||||
|
||||
data = super().get_instance()
|
||||
|
|
@ -118,21 +150,21 @@ class AnimalView(AssetMasterView):
|
|||
if relationships := self.raw_json["data"].get("relationships"):
|
||||
|
||||
# add animal type
|
||||
if animal_type := relationships.get("animal_type"):
|
||||
if animal_type["data"]:
|
||||
animal_type = self.farmos_client.resource.get_id(
|
||||
"taxonomy_term", "animal_type", animal_type["data"]["id"]
|
||||
)
|
||||
data["animal_type"] = {
|
||||
"uuid": animal_type["data"]["id"],
|
||||
"name": animal_type["data"]["attributes"]["name"],
|
||||
}
|
||||
if not data.get("animal_type"):
|
||||
if animal_type := relationships.get("animal_type"):
|
||||
if animal_type["data"]:
|
||||
animal_type = self.farmos_client.resource.get_id(
|
||||
"taxonomy_term", "animal_type", animal_type["data"]["id"]
|
||||
)
|
||||
data["animal_type"] = {
|
||||
"uuid": animal_type["data"]["id"],
|
||||
"name": animal_type["data"]["attributes"]["name"],
|
||||
}
|
||||
|
||||
return data
|
||||
|
||||
def normalize_asset(self, animal):
|
||||
|
||||
normal = super().normalize_asset(animal)
|
||||
def normalize_asset(self, animal, included):
|
||||
normal = super().normalize_asset(animal, included)
|
||||
|
||||
birthdate = animal["attributes"]["birthdate"]
|
||||
if birthdate:
|
||||
|
|
@ -145,8 +177,36 @@ class AnimalView(AssetMasterView):
|
|||
else:
|
||||
sterile = animal["attributes"]["is_castrated"]
|
||||
|
||||
animal_type = None
|
||||
animal_type_name = 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 = {
|
||||
"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"]:
|
||||
if group := included.get(group["id"]):
|
||||
group = {
|
||||
"uuid": group["id"],
|
||||
"name": group["attributes"]["name"],
|
||||
}
|
||||
group_objects.append(group)
|
||||
group_names.append(group["name"])
|
||||
|
||||
normal.update(
|
||||
{
|
||||
"animal_type": animal_type,
|
||||
"animal_type_name": animal_type_name,
|
||||
"group_objects": group_objects,
|
||||
"group_names": group_names,
|
||||
"birthdate": birthdate,
|
||||
"sex": animal["attributes"]["sex"] or colander.null,
|
||||
"is_sterile": sterile,
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ Base class for Asset master views
|
|||
"""
|
||||
|
||||
import colander
|
||||
from webhelpers2.html import tags
|
||||
|
||||
from wuttafarm.web.views.farmos import FarmOSMasterView
|
||||
from wuttafarm.web.forms.schema import UsersType, StructureType
|
||||
|
|
@ -48,12 +49,15 @@ class AssetMasterView(FarmOSMasterView):
|
|||
|
||||
labels = {
|
||||
"name": "Asset Name",
|
||||
"location": "Current Location",
|
||||
"owners": "Owner",
|
||||
"locations": "Location",
|
||||
}
|
||||
|
||||
grid_columns = [
|
||||
"drupal_id",
|
||||
"name",
|
||||
"owners",
|
||||
"locations",
|
||||
"archived",
|
||||
]
|
||||
|
||||
|
|
@ -64,12 +68,14 @@ class AssetMasterView(FarmOSMasterView):
|
|||
"archived": {"active": True, "verb": "is_false"},
|
||||
}
|
||||
|
||||
def get_grid_data(self, columns=None, session=None):
|
||||
def get_grid_data(self, columns=None, session=None, **kwargs):
|
||||
kwargs.setdefault("include", "owner,location")
|
||||
kwargs.setdefault("normalizer", self.normalize_asset)
|
||||
return ResourceData(
|
||||
self.config,
|
||||
self.farmos_client,
|
||||
f"asset--{self.farmos_asset_type}",
|
||||
normalizer=self.normalize_asset,
|
||||
**kwargs,
|
||||
)
|
||||
|
||||
def configure_grid(self, grid):
|
||||
|
|
@ -86,11 +92,33 @@ class AssetMasterView(FarmOSMasterView):
|
|||
g.set_sorter("name", SimpleSorter("name"))
|
||||
g.set_filter("name", StringFilter)
|
||||
|
||||
# owners
|
||||
g.set_renderer("owners", self.render_owners_for_grid)
|
||||
|
||||
# locations
|
||||
g.set_renderer("locations", self.render_locations_for_grid)
|
||||
|
||||
# archived
|
||||
g.set_renderer("archived", "boolean")
|
||||
g.set_sorter("archived", SimpleSorter("archived"))
|
||||
g.set_filter("archived", BooleanFilter)
|
||||
|
||||
def render_owners_for_grid(self, asset, field, value):
|
||||
links = []
|
||||
for user in value:
|
||||
url = self.request.route_url("farmos_users.view", uuid=user["uuid"])
|
||||
links.append(tags.link_to(user["name"], url))
|
||||
return ", ".join(links)
|
||||
|
||||
def render_locations_for_grid(self, asset, field, value):
|
||||
links = []
|
||||
for location in value:
|
||||
asset_type = location["type"].split("--")[1]
|
||||
route = f"farmos_{asset_type}_assets.view"
|
||||
url = self.request.route_url(route, uuid=location["uuid"])
|
||||
links.append(tags.link_to(location["name"], url))
|
||||
return ", ".join(links)
|
||||
|
||||
def grid_row_class(self, asset, data, i):
|
||||
""" """
|
||||
if asset["archived"]:
|
||||
|
|
@ -104,7 +132,7 @@ class AssetMasterView(FarmOSMasterView):
|
|||
self.raw_json = asset
|
||||
|
||||
# instance data
|
||||
data = self.normalize_asset(asset["data"])
|
||||
data = self.normalize_asset(asset["data"], {})
|
||||
|
||||
if relationships := asset["data"].get("relationships"):
|
||||
|
||||
|
|
@ -155,7 +183,7 @@ class AssetMasterView(FarmOSMasterView):
|
|||
def get_instance_title(self, asset):
|
||||
return asset["name"]
|
||||
|
||||
def normalize_asset(self, asset):
|
||||
def normalize_asset(self, asset, included):
|
||||
|
||||
if notes := asset["attributes"]["notes"]:
|
||||
notes = notes["value"]
|
||||
|
|
@ -165,12 +193,43 @@ class AssetMasterView(FarmOSMasterView):
|
|||
else:
|
||||
archived = asset["attributes"]["status"] == "archived"
|
||||
|
||||
owner_objects = []
|
||||
owner_names = []
|
||||
location_objects = []
|
||||
location_names = []
|
||||
if relationships := asset.get("relationships"):
|
||||
|
||||
if owners := relationships.get("owner"):
|
||||
for user in owners["data"]:
|
||||
if user := included.get(user["id"]):
|
||||
user = {
|
||||
"uuid": user["id"],
|
||||
"name": user["attributes"]["name"],
|
||||
}
|
||||
owner_objects.append(user)
|
||||
owner_names.append(user["name"])
|
||||
|
||||
if locations := relationships.get("location"):
|
||||
for location in locations["data"]:
|
||||
if location := included.get(location["id"]):
|
||||
location = {
|
||||
"uuid": location["id"],
|
||||
"type": location["type"],
|
||||
"name": location["attributes"]["name"],
|
||||
}
|
||||
location_objects.append(location)
|
||||
location_names.append(location["name"])
|
||||
|
||||
return {
|
||||
"uuid": asset["id"],
|
||||
"drupal_id": asset["attributes"]["drupal_internal__id"],
|
||||
"name": asset["attributes"]["name"],
|
||||
"location": colander.null, # TODO
|
||||
"notes": notes or colander.null,
|
||||
"owners": owner_objects,
|
||||
"owner_names": owner_names,
|
||||
"locations": location_objects,
|
||||
"location_names": location_names,
|
||||
"archived": archived,
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ class GroupView(FarmOSMasterView):
|
|||
model_title = "farmOS Group"
|
||||
model_title_plural = "farmOS Groups"
|
||||
|
||||
route_prefix = "farmos_groups"
|
||||
route_prefix = "farmos_group_assets"
|
||||
url_prefix = "/farmOS/groups"
|
||||
|
||||
farmos_refurl_path = "/assets/group"
|
||||
|
|
|
|||
|
|
@ -80,11 +80,11 @@ class PlantAssetView(FarmOSMasterView):
|
|||
Master view for farmOS Plant Assets
|
||||
"""
|
||||
|
||||
model_name = "farmos_asset_plant"
|
||||
model_name = "farmos_plant_assets"
|
||||
model_title = "farmOS Plant Asset"
|
||||
model_title_plural = "farmOS Plant Assets"
|
||||
|
||||
route_prefix = "farmos_asset_plant"
|
||||
route_prefix = "farmos_plant_assets"
|
||||
url_prefix = "/farmOS/assets/plant"
|
||||
|
||||
farmos_refurl_path = "/assets/plant"
|
||||
|
|
|
|||
|
|
@ -39,11 +39,11 @@ class StructureView(FarmOSMasterView):
|
|||
View for farmOS Structures
|
||||
"""
|
||||
|
||||
model_name = "farmos_structure"
|
||||
model_name = "farmos_structure_asset"
|
||||
model_title = "farmOS Structure"
|
||||
model_title_plural = "farmOS Structures"
|
||||
|
||||
route_prefix = "farmos_structures"
|
||||
route_prefix = "farmos_structure_assets"
|
||||
url_prefix = "/farmOS/structures"
|
||||
|
||||
farmos_refurl_path = "/assets/structure"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue