diff --git a/src/wuttafarm/web/app.py b/src/wuttafarm/web/app.py index 2fcb48d..161a876 100644 --- a/src/wuttafarm/web/app.py +++ b/src/wuttafarm/web/app.py @@ -40,6 +40,15 @@ def main(global_config, **settings): "wuttaweb:templates", ], ) + settings.setdefault( + "pyramid_deform.template_search_path", + " ".join( + [ + "wuttafarm.web:templates/deform", + "wuttaweb:templates/deform", + ] + ), + ) # make config objects wutta_config = base.make_wutta_config(settings) diff --git a/src/wuttafarm/web/forms/schema.py b/src/wuttafarm/web/forms/schema.py index 075c36c..c6095ff 100644 --- a/src/wuttafarm/web/forms/schema.py +++ b/src/wuttafarm/web/forms/schema.py @@ -55,6 +55,12 @@ class AnimalTypeRef(ObjectRef): animal_type = obj return self.request.route_url("animal_types.view", uuid=animal_type.uuid) + def widget_maker(self, **kwargs): + from wuttafarm.web.forms.widgets import AnimalTypeRefWidget + + kwargs["factory"] = AnimalTypeRefWidget + return super().widget_maker(**kwargs) + class LogQuick(WuttaSet): @@ -185,25 +191,6 @@ class FarmOSQuantityRefs(WuttaSet): return FarmOSQuantityRefsWidget(**kwargs) -class AnimalTypeType(colander.SchemaType): - - def __init__(self, request, *args, **kwargs): - super().__init__(*args, **kwargs) - self.request = request - - def serialize(self, node, appstruct): - if appstruct is colander.null: - return colander.null - - return json.dumps(appstruct) - - def widget_maker(self, **kwargs): # pylint: disable=empty-docstring - """ """ - from wuttafarm.web.forms.widgets import AnimalTypeWidget - - return AnimalTypeWidget(self.request, **kwargs) - - class FarmOSPlantTypes(colander.SchemaType): def __init__(self, request, *args, **kwargs): diff --git a/src/wuttafarm/web/forms/widgets.py b/src/wuttafarm/web/forms/widgets.py index 9dcc51f..7f5808f 100644 --- a/src/wuttafarm/web/forms/widgets.py +++ b/src/wuttafarm/web/forms/widgets.py @@ -29,7 +29,7 @@ import colander from deform.widget import Widget, SelectWidget from webhelpers2.html import HTML, tags -from wuttaweb.forms.widgets import WuttaCheckboxChoiceWidget +from wuttaweb.forms.widgets import WuttaCheckboxChoiceWidget, ObjectRefWidget from wuttaweb.db import Session from wuttafarm.web.util import render_quantity_objects @@ -228,33 +228,6 @@ class FarmOSUnitRefWidget(Widget): return super().serialize(field, cstruct, **kw) -class AnimalTypeWidget(Widget): - """ - Widget to display an "animal type" field. - """ - - 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") - - animal_type = json.loads(cstruct) - return tags.link_to( - animal_type["name"], - self.request.route_url( - "farmos_animal_types.view", uuid=animal_type["uuid"] - ), - ) - - return super().serialize(field, cstruct, **kw) - - class FarmOSPlantTypesWidget(Widget): """ Widget to display a farmOS "plant types" field. @@ -372,6 +345,11 @@ class UsersWidget(Widget): return super().serialize(field, cstruct, **kw) +############################## +# native data widgets +############################## + + class AssetParentRefsWidget(WuttaCheckboxChoiceWidget): """ Widget for Parents field which references assets. @@ -432,3 +410,22 @@ class LogAssetRefsWidget(WuttaCheckboxChoiceWidget): return HTML.tag("ul", c=assets) return super().serialize(field, cstruct, **kw) + + +class AnimalTypeRefWidget(ObjectRefWidget): + """ + Custom widget which uses the ```` component. + """ + + template = "animaltyperef" + + def get_template_values(self, field, cstruct, kw): + """ """ + values = super().get_template_values(field, cstruct, kw) + + values["js_values"] = json.dumps(values["values"]) + + if self.request.has_perm("animal_types.create"): + values["can_create"] = True + + return values diff --git a/src/wuttafarm/web/templates/base.mako b/src/wuttafarm/web/templates/base.mako index 3e5d544..b28b52f 100644 --- a/src/wuttafarm/web/templates/base.mako +++ b/src/wuttafarm/web/templates/base.mako @@ -1,4 +1,5 @@ <%inherit file="wuttaweb:templates/base.mako" /> +<%namespace file="/wuttafarm-components.mako" import="make_wuttafarm_components" /> <%def name="index_title_controls()"> ${parent.index_title_controls()} @@ -14,3 +15,8 @@ % endif + +<%def name="render_vue_templates()"> + ${parent.render_vue_templates()} + ${make_wuttafarm_components()} + 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 @@ +
+ + + +
diff --git a/src/wuttafarm/web/templates/wuttafarm-components.mako b/src/wuttafarm/web/templates/wuttafarm-components.mako new file mode 100644 index 0000000..b973cb1 --- /dev/null +++ b/src/wuttafarm/web/templates/wuttafarm-components.mako @@ -0,0 +1,128 @@ + +<%def name="make_wuttafarm_components()"> + ${self.make_animal_type_picker_component()} + + +<%def name="make_animal_type_picker_component()"> + + + diff --git a/src/wuttafarm/web/views/animals.py b/src/wuttafarm/web/views/animals.py index 734763b..1c9fdfe 100644 --- a/src/wuttafarm/web/views/animals.py +++ b/src/wuttafarm/web/views/animals.py @@ -26,6 +26,7 @@ Master view for Animals from webhelpers2.html import tags from wuttaweb.forms.schema import WuttaDictEnum +from wuttaweb.util import get_form_data from wuttafarm.db.model import AnimalType, AnimalAsset from wuttafarm.web.views.assets import AssetTypeMasterView, AssetMasterView @@ -137,6 +138,55 @@ class AnimalTypeView(AssetTypeMasterView): def get_row_action_url_view(self, animal, i): return self.request.route_url("animal_assets.view", uuid=animal.uuid) + def ajax_create(self): + """ + AJAX view to create a new animal type. + """ + model = self.app.model + session = self.Session() + data = get_form_data(self.request) + + name = data.get("name") + if not name: + return {"error": "Name is required"} + + animal_type = model.AnimalType(name=name) + session.add(animal_type) + session.flush() + + if self.app.is_farmos_mirror(): + token = self.request.session.get("farmos.oauth2.token") + self.app.auto_sync_to_farmos(animal_type, token=token) + + return { + "uuid": animal_type.uuid.hex, + "name": animal_type.name, + "farmos_uuid": animal_type.farmos_uuid.hex, + "drupal_id": animal_type.drupal_id, + } + + @classmethod + def defaults(cls, config): + """ """ + cls._defaults(config) + cls._animal_type_defaults(config) + + @classmethod + def _animal_type_defaults(cls, config): + route_prefix = cls.get_route_prefix() + permission_prefix = cls.get_permission_prefix() + url_prefix = cls.get_url_prefix() + + # ajax_create + config.add_route(f"{route_prefix}.ajax_create", f"{url_prefix}/ajax/new") + config.add_view( + cls, + attr="ajax_create", + route_name=f"{route_prefix}.ajax_create", + permission=f"{permission_prefix}.create", + renderer="json", + ) + class AnimalAssetView(AssetMasterView): """