Source code for wuttafarm.web.views.farmos.master

# -*- 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/>.
#
################################################################################
"""
Base class for farmOS master views
"""

import datetime
import json

import colander
import markdown
from webhelpers2.html import tags

from wuttaweb.views import MasterView
from wuttaweb.forms.schema import WuttaDateTime
from wuttaweb.forms.widgets import WuttaDateTimeWidget

from wuttafarm.web.util import get_farmos_client_for_user, use_farmos_style_grid_links
from wuttafarm.web.grids import (
    ResourceData,
    StringFilter,
    NullableStringFilter,
    DateTimeFilter,
    SimpleSorter,
)


[docs] class FarmOSMasterView(MasterView): """ Base class for farmOS master views """ model_key = "uuid" creatable = False editable = False deletable = False filterable = False sort_on_backend = False paginate_on_backend = False farmos_refurl_path = None labels = { "drupal_id": "Drupal ID", "raw_image_url": "Raw Image URL", "large_image_url": "Large Image URL", "thumbnail_image_url": "Thumbnail Image URL", } def __init__(self, request, context=None): super().__init__(request, context=context) self.farmos_client = get_farmos_client_for_user(self.request) self.farmos_4x = self.app.is_farmos_4x(self.farmos_client) self.normal = self.app.get_normalizer(self.farmos_client) self.raw_json = None self.farmos_style_grid_links = use_farmos_style_grid_links(self.config) def get_fallback_templates(self, template): """ """ templates = super().get_fallback_templates(template) if template == "view": templates.insert(0, "/farmos/master/view.mako") return templates def render_owners_for_grid(self, obj, field, value): owners = [] for user in value: if self.farmos_style_grid_links: url = self.request.route_url("farmos_users.view", uuid=user["uuid"]) owners.append(tags.link_to(user["name"], url)) else: owners.append(user["name"]) return ", ".join(owners)
[docs] def get_template_context(self, context): if self.listing and self.farmos_refurl_path: context["farmos_refurl"] = self.app.get_farmos_url(self.farmos_refurl_path) if self.viewing and self.raw_json: context["raw_json"] = self.raw_json code = "```json\n" + json.dumps(self.raw_json, indent=2) + "\n```" # TODO: this does not seem to be adding syntax highlight context["rendered_json"] = markdown.markdown( code, extensions=["fenced_code", "codehilite"] ) return context
[docs] class TaxonomyMasterView(FarmOSMasterView): """ Base class for farmOS "taxonomy term" views """ farmos_taxonomy_type = None creatable = True editable = True deletable = True filterable = True sort_on_backend = True grid_columns = [ "name", "description", "changed", ] sort_defaults = "name" filter_defaults = { "name": {"active": True, "verb": "contains"}, } form_fields = [ "name", "description", "changed", ]
[docs] def get_grid_data(self, columns=None, session=None): return ResourceData( self.config, self.farmos_client, f"taxonomy_term--{self.farmos_taxonomy_type}", normalizer=self.normalize_taxonomy_term, )
def normalize_taxonomy_term(self, term, included): if changed := term["attributes"]["changed"]: changed = datetime.datetime.fromisoformat(changed) changed = self.app.localtime(changed) if description := term["attributes"]["description"]: description = description["value"] return { "uuid": term["id"], "drupal_id": term["attributes"]["drupal_internal__tid"], "name": term["attributes"]["name"], "description": description or colander.null, "changed": changed, }
[docs] def configure_grid(self, grid): g = grid super().configure_grid(g) # name g.set_link("name") 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)
[docs] 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"], {})
[docs] def get_instance_title(self, term): return term["name"]
[docs] def configure_form(self, form): f = form super().configure_form(f) # 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}
[docs] 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"]
[docs] def delete_instance(self, term): self.farmos_client.resource.delete( "taxonomy_term", self.farmos_taxonomy_type, term["uuid"] )
[docs] def get_xref_buttons(self, term): return [ self.make_button( "View in farmOS", primary=True, url=self.app.get_farmos_url(f"/taxonomy/term/{term['drupal_id']}"), target="_blank", icon_left="external-link-alt", ) ]