feat: convert structure assets to use common base/mixin

This commit is contained in:
Lance Edgar 2026-02-15 13:38:11 -06:00
parent 7b6280b6dc
commit 3435b4714e
10 changed files with 385 additions and 339 deletions

View file

@ -0,0 +1,236 @@
"""use shared base for Structure Assets
Revision ID: 34ec51d80f52
Revises: d882682c82f9
Create Date: 2026-02-15 13:19:18.814523
"""
from typing import Sequence, Union
from alembic import op
import sqlalchemy as sa
import wuttjamaican.db.util
# revision identifiers, used by Alembic.
revision: str = "34ec51d80f52"
down_revision: Union[str, None] = "d882682c82f9"
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None
def upgrade() -> None:
# asset_structure
op.create_table(
"asset_structure",
sa.Column("structure_type_uuid", wuttjamaican.db.util.UUID(), nullable=False),
sa.Column("uuid", wuttjamaican.db.util.UUID(), nullable=False),
sa.ForeignKeyConstraint(
["structure_type_uuid"],
["structure_type.uuid"],
name=op.f("fk_asset_structure_structure_type_uuid_structure_type"),
),
sa.ForeignKeyConstraint(
["uuid"], ["asset.uuid"], name=op.f("fk_asset_structure_uuid_asset")
),
sa.PrimaryKeyConstraint("uuid", name=op.f("pk_asset_structure")),
)
op.create_table(
"asset_structure_version",
sa.Column(
"structure_type_uuid",
wuttjamaican.db.util.UUID(),
autoincrement=False,
nullable=True,
),
sa.Column(
"uuid", wuttjamaican.db.util.UUID(), autoincrement=False, nullable=False
),
sa.Column(
"transaction_id", sa.BigInteger(), autoincrement=False, nullable=False
),
sa.Column("end_transaction_id", sa.BigInteger(), nullable=True),
sa.Column("operation_type", sa.SmallInteger(), nullable=False),
sa.PrimaryKeyConstraint(
"uuid", "transaction_id", name=op.f("pk_asset_structure_version")
),
)
op.create_index(
op.f("ix_asset_structure_version_end_transaction_id"),
"asset_structure_version",
["end_transaction_id"],
unique=False,
)
op.create_index(
op.f("ix_asset_structure_version_operation_type"),
"asset_structure_version",
["operation_type"],
unique=False,
)
op.create_index(
"ix_asset_structure_version_pk_transaction_id",
"asset_structure_version",
["uuid", sa.literal_column("transaction_id DESC")],
unique=False,
)
op.create_index(
"ix_asset_structure_version_pk_validity",
"asset_structure_version",
["uuid", "transaction_id", "end_transaction_id"],
unique=False,
)
op.create_index(
op.f("ix_asset_structure_version_transaction_id"),
"asset_structure_version",
["transaction_id"],
unique=False,
)
# structure
op.drop_index(
op.f("ix_structure_version_end_transaction_id"), table_name="structure_version"
)
op.drop_index(
op.f("ix_structure_version_operation_type"), table_name="structure_version"
)
op.drop_index(
op.f("ix_structure_version_pk_transaction_id"), table_name="structure_version"
)
op.drop_index(
op.f("ix_structure_version_pk_validity"), table_name="structure_version"
)
op.drop_index(
op.f("ix_structure_version_transaction_id"), table_name="structure_version"
)
op.drop_table("structure_version")
op.drop_table("structure")
def downgrade() -> None:
# structure
op.create_table(
"structure",
sa.Column("uuid", sa.UUID(), autoincrement=False, nullable=False),
sa.Column("name", sa.VARCHAR(length=100), autoincrement=False, nullable=False),
sa.Column("archived", sa.BOOLEAN(), autoincrement=False, nullable=False),
sa.Column(
"structure_type_uuid", sa.UUID(), autoincrement=False, nullable=False
),
sa.Column("is_location", sa.BOOLEAN(), autoincrement=False, nullable=False),
sa.Column("is_fixed", sa.BOOLEAN(), autoincrement=False, nullable=False),
sa.Column("notes", sa.TEXT(), autoincrement=False, nullable=True),
sa.Column(
"image_url", sa.VARCHAR(length=255), autoincrement=False, nullable=True
),
sa.Column("farmos_uuid", sa.UUID(), autoincrement=False, nullable=True),
sa.Column("drupal_id", sa.INTEGER(), autoincrement=False, nullable=True),
sa.Column(
"thumbnail_url", sa.VARCHAR(length=255), autoincrement=False, nullable=True
),
sa.ForeignKeyConstraint(
["structure_type_uuid"],
["structure_type.uuid"],
name=op.f("fk_structure_structure_type_uuid_structure_type"),
),
sa.PrimaryKeyConstraint("uuid", name=op.f("pk_structure")),
sa.UniqueConstraint(
"drupal_id",
name=op.f("uq_structure_drupal_id"),
postgresql_include=[],
postgresql_nulls_not_distinct=False,
),
sa.UniqueConstraint(
"farmos_uuid",
name=op.f("uq_structure_farmos_uuid"),
postgresql_include=[],
postgresql_nulls_not_distinct=False,
),
sa.UniqueConstraint(
"name",
name=op.f("uq_structure_name"),
postgresql_include=[],
postgresql_nulls_not_distinct=False,
),
)
op.create_table(
"structure_version",
sa.Column("uuid", sa.UUID(), autoincrement=False, nullable=False),
sa.Column("name", sa.VARCHAR(length=100), autoincrement=False, nullable=True),
sa.Column("archived", sa.BOOLEAN(), autoincrement=False, nullable=True),
sa.Column("structure_type_uuid", sa.UUID(), autoincrement=False, nullable=True),
sa.Column("is_location", sa.BOOLEAN(), autoincrement=False, nullable=True),
sa.Column("is_fixed", sa.BOOLEAN(), autoincrement=False, nullable=True),
sa.Column("notes", sa.TEXT(), autoincrement=False, nullable=True),
sa.Column(
"image_url", sa.VARCHAR(length=255), autoincrement=False, nullable=True
),
sa.Column("farmos_uuid", sa.UUID(), autoincrement=False, nullable=True),
sa.Column("drupal_id", sa.INTEGER(), autoincrement=False, nullable=True),
sa.Column("transaction_id", sa.BIGINT(), autoincrement=False, nullable=False),
sa.Column(
"end_transaction_id", sa.BIGINT(), autoincrement=False, nullable=True
),
sa.Column("operation_type", sa.SMALLINT(), autoincrement=False, nullable=False),
sa.Column(
"thumbnail_url", sa.VARCHAR(length=255), autoincrement=False, nullable=True
),
sa.PrimaryKeyConstraint(
"uuid", "transaction_id", name=op.f("pk_structure_version")
),
)
op.create_index(
op.f("ix_structure_version_transaction_id"),
"structure_version",
["transaction_id"],
unique=False,
)
op.create_index(
op.f("ix_structure_version_pk_validity"),
"structure_version",
["uuid", "transaction_id", "end_transaction_id"],
unique=False,
)
op.create_index(
op.f("ix_structure_version_pk_transaction_id"),
"structure_version",
["uuid", sa.literal_column("transaction_id DESC")],
unique=False,
)
op.create_index(
op.f("ix_structure_version_operation_type"),
"structure_version",
["operation_type"],
unique=False,
)
op.create_index(
op.f("ix_structure_version_end_transaction_id"),
"structure_version",
["end_transaction_id"],
unique=False,
)
# asset_structure
op.drop_index(
op.f("ix_asset_structure_version_transaction_id"),
table_name="asset_structure_version",
)
op.drop_index(
"ix_asset_structure_version_pk_validity", table_name="asset_structure_version"
)
op.drop_index(
"ix_asset_structure_version_pk_transaction_id",
table_name="asset_structure_version",
)
op.drop_index(
op.f("ix_asset_structure_version_operation_type"),
table_name="asset_structure_version",
)
op.drop_index(
op.f("ix_asset_structure_version_end_transaction_id"),
table_name="asset_structure_version",
)
op.drop_table("asset_structure_version")
op.drop_table("asset_structure")

View file

@ -32,7 +32,7 @@ from .users import WuttaFarmUser
# wuttafarm proper models # wuttafarm proper models
from .assets import AssetType, Asset, AssetParent from .assets import AssetType, Asset, AssetParent
from .land import LandType, LandAsset from .land import LandType, LandAsset
from .structures import StructureType, Structure from .structures import StructureType, StructureAsset
from .animals import AnimalType, AnimalAsset from .animals import AnimalType, AnimalAsset
from .groups import Group from .groups import Group
from .logs import LogType, ActivityLog from .logs import LogType, ActivityLog

View file

@ -28,6 +28,8 @@ from sqlalchemy import orm
from wuttjamaican.db import model from wuttjamaican.db import model
from wuttafarm.db.model.assets import AssetMixin, add_asset_proxies
class StructureType(model.Base): class StructureType(model.Base):
""" """
@ -74,38 +76,19 @@ class StructureType(model.Base):
return self.name or "" return self.name or ""
class Structure(model.Base): class StructureAsset(AssetMixin, model.Base):
""" """
Represents a structure from farmOS Represents a structure from farmOS
""" """
__tablename__ = "structure" __tablename__ = "asset_structure"
__versioned__ = {} __versioned__ = {}
__wutta_hint__ = { __wutta_hint__ = {
"model_title": "Structure", "model_title": "Structure Asset",
"model_title_plural": "Structures", "model_title_plural": "Structure Assets",
"farmos_asset_type": "structure",
} }
uuid = model.uuid_column()
name = sa.Column(
sa.String(length=100),
nullable=False,
unique=True,
doc="""
Name for the structure.
""",
)
archived = sa.Column(
sa.Boolean(),
nullable=False,
default=False,
doc="""
Whether the structure is archived.
""",
)
structure_type_uuid = model.uuid_fk_column("structure_type.uuid", nullable=False) structure_type_uuid = model.uuid_fk_column("structure_type.uuid", nullable=False)
structure_type = orm.relationship( structure_type = orm.relationship(
"StructureType", "StructureType",
@ -114,63 +97,5 @@ class Structure(model.Base):
""", """,
) )
is_location = sa.Column(
sa.Boolean(),
nullable=False,
doc="""
Whether the structure is considered a location.
""",
)
is_fixed = sa.Column( add_asset_proxies(StructureAsset)
sa.Boolean(),
nullable=False,
doc="""
Whether the structure location is fixed.
""",
)
notes = sa.Column(
sa.Text(),
nullable=True,
doc="""
Arbitrary notes for the structure.
""",
)
image_url = sa.Column(
sa.String(length=255),
nullable=True,
doc="""
Optional image URL for the structure.
""",
)
thumbnail_url = sa.Column(
sa.String(length=255),
nullable=True,
doc="""
Optional thumbnail URL for the structure.
""",
)
farmos_uuid = sa.Column(
model.UUID(),
nullable=True,
unique=True,
doc="""
UUID for the structure within farmOS.
""",
)
drupal_id = sa.Column(
sa.Integer(),
nullable=True,
unique=True,
doc="""
Drupal internal ID for the structure.
""",
)
def __str__(self):
return self.name or ""

View file

@ -100,7 +100,7 @@ class FromFarmOSToWuttaFarm(FromFarmOSHandler, ToWuttaFarmHandler):
importers["LandType"] = LandTypeImporter importers["LandType"] = LandTypeImporter
importers["LandAsset"] = LandAssetImporter importers["LandAsset"] = LandAssetImporter
importers["StructureType"] = StructureTypeImporter importers["StructureType"] = StructureTypeImporter
importers["Structure"] = StructureImporter importers["StructureAsset"] = StructureAssetImporter
importers["AnimalType"] = AnimalTypeImporter importers["AnimalType"] = AnimalTypeImporter
importers["AnimalAsset"] = AnimalAssetImporter importers["AnimalAsset"] = AnimalAssetImporter
importers["Group"] = GroupImporter importers["Group"] = GroupImporter
@ -613,17 +613,18 @@ class LogTypeImporter(FromFarmOS, ToWutta):
} }
class StructureImporter(FromFarmOS, ToWutta): class StructureAssetImporter(AssetImporterBase):
""" """
farmOS API WuttaFarm importer for Structures farmOS API WuttaFarm importer for Structure Assets
""" """
model_class = model.Structure model_class = model.StructureAsset
supported_fields = [ supported_fields = [
"farmos_uuid", "farmos_uuid",
"drupal_id", "drupal_id",
"name", "asset_type",
"asset_name",
"structure_type_uuid", "structure_type_uuid",
"is_location", "is_location",
"is_fixed", "is_fixed",
@ -631,6 +632,7 @@ class StructureImporter(FromFarmOS, ToWutta):
"archived", "archived",
"image_url", "image_url",
"thumbnail_url", "thumbnail_url",
"parents",
] ]
def setup(self): def setup(self):
@ -652,46 +654,20 @@ class StructureImporter(FromFarmOS, ToWutta):
structure_type = self.structure_types_by_id.get(structure_type_id) structure_type = self.structure_types_by_id.get(structure_type_id)
if not structure_type: if not structure_type:
log.warning( log.warning(
"invalid structure_type '%s' for farmOS Structure: %s", "invalid structure_type '%s' for farmOS Structure Asset: %s",
structure_type_id, structure_type_id,
structure, structure,
) )
return None return None
if notes := structure["attributes"]["notes"]: data = self.normalize_asset(structure)
notes = notes["value"] data.update(
{
image_url = None "asset_type": "structure",
thumbnail_url = None
if relationships := structure.get("relationships"):
if image := relationships.get("image"):
if image["data"]:
image = self.farmos_client.resource.get_id(
"file", "file", image["data"][0]["id"]
)
if image_style := image["data"]["attributes"].get(
"image_style_uri"
):
image_url = image_style["large"]
thumbnail_url = image_style["thumbnail"]
if self.farmos_4x:
archived = structure["attributes"]["archived"]
else:
archived = structure["attributes"]["status"] == "archived"
return {
"farmos_uuid": UUID(structure["id"]),
"drupal_id": structure["attributes"]["drupal_internal__id"],
"name": structure["attributes"]["name"],
"structure_type_uuid": structure_type.uuid, "structure_type_uuid": structure_type.uuid,
"is_location": structure["attributes"]["is_location"],
"is_fixed": structure["attributes"]["is_fixed"],
"archived": archived,
"notes": notes,
"image_url": image_url,
"thumbnail_url": thumbnail_url,
} }
)
return data
class StructureTypeImporter(FromFarmOS, ToWutta): class StructureTypeImporter(FromFarmOS, ToWutta):

View file

@ -59,17 +59,17 @@ class WuttaFarmMenuHandler(base.MenuHandler):
"route": "land_assets", "route": "land_assets",
"perm": "land_assets.list", "perm": "land_assets.list",
}, },
{
"title": "Structure",
"route": "structure_assets",
"perm": "structure_assets.list",
},
{"type": "sep"}, {"type": "sep"},
{ {
"title": "Groups", "title": "Groups",
"route": "groups", "route": "groups",
"perm": "groups.list", "perm": "groups.list",
}, },
{
"title": "Structures",
"route": "structures",
"perm": "structures.list",
},
{"type": "sep"}, {"type": "sep"},
{ {
"title": "Animal Types", "title": "Animal Types",

View file

@ -44,7 +44,6 @@ def includeme(config):
config.include("wuttafarm.web.views.asset_types") config.include("wuttafarm.web.views.asset_types")
config.include("wuttafarm.web.views.assets") config.include("wuttafarm.web.views.assets")
config.include("wuttafarm.web.views.land") config.include("wuttafarm.web.views.land")
config.include("wuttafarm.web.views.structure_types")
config.include("wuttafarm.web.views.structures") config.include("wuttafarm.web.views.structures")
config.include("wuttafarm.web.views.animals") config.include("wuttafarm.web.views.animals")
config.include("wuttafarm.web.views.groups") config.include("wuttafarm.web.views.groups")

View file

@ -241,6 +241,8 @@ class AssetMasterView(WuttaFarmMasterView):
route = "farmos_animals.view" route = "farmos_animals.view"
elif asset.asset_type == "land": elif asset.asset_type == "land":
route = "farmos_land_assets.view" route = "farmos_land_assets.view"
elif asset.asset_type == "structure":
route = "farmos_structures.view"
if route: if route:
buttons.append( buttons.append(

View file

@ -211,8 +211,8 @@ class StructureView(FarmOSMasterView):
] ]
if wf_structure := ( if wf_structure := (
session.query(model.Structure) session.query(model.StructureAsset)
.filter(model.Structure.farmos_uuid == structure["uuid"]) .filter(model.StructureAsset.farmos_uuid == structure["uuid"])
.first() .first()
): ):
buttons.append( buttons.append(
@ -220,7 +220,7 @@ class StructureView(FarmOSMasterView):
f"View {self.app.get_title()} record", f"View {self.app.get_title()} record",
primary=True, primary=True,
url=self.request.route_url( url=self.request.route_url(
"structures.view", uuid=wf_structure.uuid "structure_assets.view", uuid=wf_structure.uuid
), ),
icon_left="eye", icon_left="eye",
) )

View file

@ -1,118 +0,0 @@
# -*- coding: utf-8; -*-
################################################################################
#
# WuttaFarm --Web app to integrate with and extend farmOS
# Copyright © 2026 Lance Edgar
#
# This file is part of WuttaFarm.
#
# WuttaFarm is free software: you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation, either version 3 of the License, or (at your option) any later
# version.
#
# WuttaFarm is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with
# WuttaFarm. If not, see <http://www.gnu.org/licenses/>.
#
################################################################################
"""
Master view for Structure Types
"""
from wuttafarm.db.model.structures import StructureType, Structure
from wuttafarm.web.views import WuttaFarmMasterView
class StructureTypeView(WuttaFarmMasterView):
"""
Master view for Structure Types
"""
model_class = StructureType
route_prefix = "structure_types"
url_prefix = "/structure-types"
grid_columns = [
"name",
]
sort_defaults = "name"
filter_defaults = {
"name": {"active": True, "verb": "contains"},
}
form_fields = [
"name",
"farmos_uuid",
"drupal_id",
]
has_rows = True
row_model_class = Structure
rows_viewable = True
row_grid_columns = [
"name",
"is_location",
"is_fixed",
"archived",
]
rows_sort_defaults = "name"
def configure_grid(self, grid):
g = grid
super().configure_grid(g)
# name
g.set_link("name")
def get_xref_buttons(self, structure_type):
buttons = super().get_xref_buttons(structure_type)
if structure_type.farmos_uuid:
buttons.append(
self.make_button(
"View farmOS record",
primary=True,
url=self.request.route_url(
"farmos_structure_types.view", uuid=structure_type.farmos_uuid
),
icon_left="eye",
)
)
return buttons
def get_row_grid_data(self, structure_type):
model = self.app.model
session = self.Session()
return session.query(model.Structure).filter(
model.Structure.structure_type == structure_type
)
def configure_row_grid(self, grid):
g = grid
super().configure_row_grid(g)
# name
g.set_link("name")
def get_row_action_url_view(self, structure, i):
return self.request.route_url("structures.view", uuid=structure.uuid)
def defaults(config, **kwargs):
base = globals()
StructureTypeView = kwargs.get("StructureTypeView", base["StructureTypeView"])
StructureTypeView.defaults(config)
def includeme(config):
defaults(config)

View file

@ -23,44 +23,136 @@
Master view for Structures Master view for Structures
""" """
from wuttafarm.db.model.structures import Structure
from wuttafarm.web.views import WuttaFarmMasterView from wuttafarm.web.views import WuttaFarmMasterView
from wuttafarm.web.views.assets import AssetMasterView
from wuttafarm.db.model import StructureType, StructureAsset
from wuttafarm.web.forms.schema import StructureTypeRef from wuttafarm.web.forms.schema import StructureTypeRef
from wuttafarm.web.forms.widgets import ImageWidget from wuttafarm.web.forms.widgets import ImageWidget
class StructureView(WuttaFarmMasterView): class StructureTypeView(WuttaFarmMasterView):
""" """
Master view for Structures Master view for Structure Types
""" """
model_class = Structure model_class = StructureType
route_prefix = "structures" route_prefix = "structure_types"
url_prefix = "/structures" url_prefix = "/structure-types"
farmos_refurl_path = "/assets/structure"
labels = {
"name": "Asset Name",
}
grid_columns = [ grid_columns = [
"thumbnail",
"drupal_id",
"name", "name",
"structure_type",
"archived",
] ]
sort_defaults = "name" sort_defaults = "name"
filter_defaults = { filter_defaults = {
"name": {"active": True, "verb": "contains"}, "name": {"active": True, "verb": "contains"},
"archived": {"active": True, "verb": "is_false"},
} }
form_fields = [ form_fields = [
"name", "name",
"farmos_uuid",
"drupal_id",
]
has_rows = True
row_model_class = StructureAsset
rows_viewable = True
row_grid_columns = [
"asset_name",
"is_location",
"is_fixed",
"archived",
]
rows_sort_defaults = "asset_name"
def configure_grid(self, grid):
g = grid
super().configure_grid(g)
# name
g.set_link("name")
def get_xref_buttons(self, structure_type):
buttons = super().get_xref_buttons(structure_type)
if structure_type.farmos_uuid:
buttons.append(
self.make_button(
"View farmOS record",
primary=True,
url=self.request.route_url(
"farmos_structure_types.view", uuid=structure_type.farmos_uuid
),
icon_left="eye",
)
)
return buttons
def get_row_grid_data(self, structure_type):
model = self.app.model
session = self.Session()
return (
session.query(model.StructureAsset)
.join(model.Asset)
.filter(model.StructureAsset.structure_type == structure_type)
)
def configure_row_grid(self, grid):
g = grid
super().configure_row_grid(g)
model = self.app.model
# asset_name
g.set_link("asset_name")
g.set_sorter("asset_name", model.Asset.asset_name)
g.set_filter("asset_name", model.Asset.asset_name)
# is_location
g.set_renderer("is_location", "boolean")
g.set_sorter("is_location", model.Asset.is_location)
g.set_filter("is_location", model.Asset.is_location)
# is_fixed
g.set_renderer("is_fixed", "boolean")
g.set_sorter("is_fixed", model.Asset.is_fixed)
g.set_filter("is_fixed", model.Asset.is_fixed)
# archived
g.set_renderer("archived", "boolean")
g.set_sorter("archived", model.Asset.archived)
g.set_filter("archived", model.Asset.archived)
def get_row_action_url_view(self, structure, i):
return self.request.route_url("structure_assets.view", uuid=structure.uuid)
class StructureAssetView(AssetMasterView):
"""
Master view for Structures
"""
model_class = StructureAsset
route_prefix = "structure_assets"
url_prefix = "/asset/structures"
farmos_refurl_path = "/assets/structure"
grid_columns = [
"thumbnail",
"drupal_id",
"asset_name",
"structure_type",
"parents",
"archived",
]
form_fields = [
"asset_name",
"parents",
"notes", "notes",
"asset_type", "asset_type",
"structure_type", "structure_type",
@ -80,17 +172,6 @@ class StructureView(WuttaFarmMasterView):
super().configure_grid(g) super().configure_grid(g)
model = self.app.model model = self.app.model
# thumbnail
g.set_renderer("thumbnail", self.render_grid_thumbnail)
g.set_label("thumbnail", "", column_only=True)
g.set_centered("thumbnail")
# drupal_id
g.set_label("drupal_id", "ID", column_only=True)
# name
g.set_link("name")
# structure_type # structure_type
g.set_joiner("structure_type", lambda q: q.join(model.StructureType)) g.set_joiner("structure_type", lambda q: q.join(model.StructureType))
g.set_sorter("structure_type", model.StructureType.name) g.set_sorter("structure_type", model.StructureType.name)
@ -98,78 +179,23 @@ class StructureView(WuttaFarmMasterView):
"structure_type", model.StructureType.name, label="Structure Type Name" "structure_type", model.StructureType.name, label="Structure Type Name"
) )
def grid_row_class(self, structure, data, i):
""" """
if structure.archived:
return "has-background-warning"
return None
def configure_form(self, form): def configure_form(self, form):
f = form f = form
super().configure_form(f) super().configure_form(f)
structure = form.model_instance structure = form.model_instance
# notes
f.set_widget("notes", "notes")
# asset_type
if self.creating:
f.remove("asset_type")
else:
f.set_default("asset_type", "Structure")
f.set_readonly("asset_type")
# structure_type # structure_type
f.set_node("structure_type", StructureTypeRef(self.request)) f.set_node("structure_type", StructureTypeRef(self.request))
# 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 structure.thumbnail_url:
f.set_widget("thumbnail", ImageWidget("structure thumbnail"))
f.set_default("thumbnail", structure.thumbnail_url)
# image
if self.creating or self.editing:
f.remove("image")
elif structure.image_url:
f.set_widget("image", ImageWidget("structure image"))
f.set_default("image", structure.image_url)
def get_farmos_url(self, structure):
return self.app.get_farmos_url(f"/asset/{structure.drupal_id}")
def get_xref_buttons(self, structure):
buttons = super().get_xref_buttons(structure)
if structure.farmos_uuid:
buttons.append(
self.make_button(
"View farmOS record",
primary=True,
url=self.request.route_url(
"farmos_structures.view", uuid=structure.farmos_uuid
),
icon_left="eye",
)
)
return buttons
def defaults(config, **kwargs): def defaults(config, **kwargs):
base = globals() base = globals()
StructureView = kwargs.get("StructureView", base["StructureView"]) StructureTypeView = kwargs.get("StructureTypeView", base["StructureTypeView"])
StructureView.defaults(config) StructureTypeView.defaults(config)
StructureAssetView = kwargs.get("StructureAssetView", base["StructureAssetView"])
StructureAssetView.defaults(config)
def includeme(config): def includeme(config):