+ RESTART IS REQUIRED + if you change the integration mode. +
+ + ${b}-tooltip> ++ If set, certain column values in a grid may link + to related + records. +
++ If not set, column values will only link to view the + current record. +
+ + ${b}-tooltip> + ++ powered by + ${h.link_to("WuttaWeb", 'https://wuttaproject.org/', target='_blank')} + and + ${h.link_to("farmOS", 'https://farmos.org/', target='_blank')} +
%def> diff --git a/src/wuttafarm/web/templates/deform/animaltyperef.pt b/src/wuttafarm/web/templates/deform/animaltyperef.pt new file mode 100644 index 0000000..61dd770 --- /dev/null +++ b/src/wuttafarm/web/templates/deform/animaltyperef.pt @@ -0,0 +1,13 @@ ++ ${help_text} +
+ + ${parent.render_form_tag()} +%def> diff --git a/src/wuttafarm/web/templates/wuttafarm-components.mako b/src/wuttafarm/web/templates/wuttafarm-components.mako new file mode 100644 index 0000000..37b176e --- /dev/null +++ b/src/wuttafarm/web/templates/wuttafarm-components.mako @@ -0,0 +1,324 @@ + +<%def name="make_wuttafarm_components()"> + ${self.make_animal_type_picker_component()} + ${self.make_plant_types_picker_component()} +%def> + +<%def name="make_animal_type_picker_component()"> + + +%def> + +<%def name="make_plant_types_picker_component()"> + + +%def> diff --git a/src/wuttafarm/web/util.py b/src/wuttafarm/web/util.py index 65d637d..977550a 100644 --- a/src/wuttafarm/web/util.py +++ b/src/wuttafarm/web/util.py @@ -23,6 +23,28 @@ Misc. utilities for web app """ +from pyramid import httpexceptions +from webhelpers2.html import HTML + + +def get_farmos_client_for_user(request): + token = request.session.get("farmos.oauth2.token") + if not token: + raise httpexceptions.HTTPForbidden() + + # nb. must give a *copy* of the token to farmOS client, since it + # will mutate it in-place and we don't want that to happen for our + # original copy in the user session. (otherwise the auto-refresh + # will not work correctly for subsequent calls.) + token = dict(token) + + def token_updater(token): + save_farmos_oauth2_token(request, token) + + config = request.wutta_config + app = config.get_app() + return app.get_farmos_client(token=token, token_updater=token_updater) + def save_farmos_oauth2_token(request, token): """ @@ -38,3 +60,22 @@ def save_farmos_oauth2_token(request, token): # save token to user session request.session["farmos.oauth2.token"] = token + + +def use_farmos_style_grid_links(config): + return config.get_bool(f"{config.appname}.farmos_style_grid_links", default=True) + + +def render_quantity_objects(quantities): + items = [] + for quantity in quantities: + text = render_quantity_object(quantity) + items.append(HTML.tag("li", c=text)) + return HTML.tag("ul", c=items) + + +def render_quantity_object(quantity): + measure = quantity["measure_name"] + value = quantity["value_decimal"] + unit = quantity["unit_name"] + return f"( {measure} ) {value} {unit}" diff --git a/src/wuttafarm/web/views/__init__.py b/src/wuttafarm/web/views/__init__.py index 63ce536..0d58a72 100644 --- a/src/wuttafarm/web/views/__init__.py +++ b/src/wuttafarm/web/views/__init__.py @@ -25,8 +25,14 @@ WuttaFarm Views from wuttaweb.views import essential +from .master import WuttaFarmMasterView + def includeme(config): + wutta_config = config.registry.settings.get("wutta_config") + app = wutta_config.get_app() + enum = app.enum + mode = app.get_farmos_integration_mode() # wuttaweb core essential.defaults( @@ -34,8 +40,32 @@ def includeme(config): **{ "wuttaweb.views.auth": "wuttafarm.web.views.auth", "wuttaweb.views.common": "wuttafarm.web.views.common", + "wuttaweb.views.settings": "wuttafarm.web.views.settings", + "wuttaweb.views.users": "wuttafarm.web.views.users", } ) + # native table views + if mode != enum.FARMOS_INTEGRATION_MODE_WRAPPER: + config.include("wuttafarm.web.views.units") + config.include("wuttafarm.web.views.quantities") + config.include("wuttafarm.web.views.asset_types") + config.include("wuttafarm.web.views.assets") + config.include("wuttafarm.web.views.land") + config.include("wuttafarm.web.views.structures") + config.include("wuttafarm.web.views.animals") + config.include("wuttafarm.web.views.groups") + config.include("wuttafarm.web.views.plants") + config.include("wuttafarm.web.views.logs") + config.include("wuttafarm.web.views.logs_activity") + config.include("wuttafarm.web.views.logs_harvest") + config.include("wuttafarm.web.views.logs_medical") + config.include("wuttafarm.web.views.logs_observation") + + # quick form views + # (nb. these work with all integration modes) + config.include("wuttafarm.web.views.quick") + # views for farmOS - config.include("wuttafarm.web.views.farmos") + if mode != enum.FARMOS_INTEGRATION_MODE_NONE: + config.include("wuttafarm.web.views.farmos") diff --git a/src/wuttafarm/web/views/animals.py b/src/wuttafarm/web/views/animals.py new file mode 100644 index 0000000..f4c97e2 --- /dev/null +++ b/src/wuttafarm/web/views/animals.py @@ -0,0 +1,312 @@ +# -*- 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