From 3befdc09e377b6ec80c5588183bc5a4729099993 Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Sat, 24 Dec 2022 21:46:02 -0600 Subject: [PATCH] Add basic support for editing field help info --- tailbone/forms/core.py | 75 ++++++++++++++++++++-- tailbone/templates/form.mako | 19 ++++++ tailbone/templates/forms/deform_buefy.mako | 75 +++++++++++++++++++++- tailbone/templates/page_help.mako | 2 +- tailbone/util.py | 4 +- tailbone/views/master.py | 50 +++++++++++++++ 6 files changed, 218 insertions(+), 7 deletions(-) diff --git a/tailbone/forms/core.py b/tailbone/forms/core.py index bf508a6f..f4d5f14f 100644 --- a/tailbone/forms/core.py +++ b/tailbone/forms/core.py @@ -48,7 +48,8 @@ from pyramid_deform import SessionFileUploadTempStore from pyramid.renderers import render from webhelpers2.html import tags, HTML -from tailbone.util import raw_datetime, get_form_data +from tailbone.db import Session +from tailbone.util import raw_datetime, get_form_data, render_markdown from . import types from .widgets import ReadonlyWidget, PlainDateWidget, JQueryDateWidget, JQueryTimeWidget from tailbone.exceptions import TailboneJSONFieldError @@ -337,6 +338,8 @@ class Form(object): hidden={}, widgets={}, defaults={}, validators={}, required={}, helptext={}, focus_spec=None, action_url=None, cancel_url=None, use_buefy=None, component='tailbone-form', vuejs_field_converters={}, + # TODO: ugh this is getting out hand! + can_edit_help=False, edit_help_url=None, route_prefix=None, ): self.fields = None if fields is not None: @@ -375,6 +378,9 @@ class Form(object): self.use_buefy = use_buefy self.component = component self.vuejs_field_converters = vuejs_field_converters or {} + self.can_edit_help = can_edit_help + self.edit_help_url = edit_help_url + self.route_prefix = route_prefix def __iter__(self): return iter(self.fields) @@ -800,6 +806,11 @@ class Form(object): context = kwargs context['form'] = self context['dform'] = dform + context.setdefault('can_edit_help', self.can_edit_help) + if context['can_edit_help']: + context.setdefault('edit_help_url', self.edit_help_url) + context['field_labels'] = self.get_field_labels() + context['field_markdowns'] = self.get_field_markdowns() context.setdefault('form_kwargs', {}) # TODO: deprecate / remove the latter option here if self.auto_disable_save or self.auto_disable: @@ -815,6 +826,22 @@ class Form(object): context['render_field_readonly'] = self.render_field_readonly return render(template, context) + def get_field_labels(self): + return dict([(field, self.get_label(field)) + for field in self]) + + def get_field_markdowns(self): + model = self.request.rattail_config.get_model() + + if not hasattr(self, 'field_markdowns'): + infos = Session.query(model.TailboneFieldInfo)\ + .filter(model.TailboneFieldInfo.route_prefix == self.route_prefix)\ + .all() + self.field_markdowns = dict([(info.field_name, info.markdown_text) + for info in infos]) + + return self.field_markdowns + def get_vuejs_model_value(self, field): """ This method must return "raw" JS which will be assigned as the initial @@ -874,13 +901,14 @@ class Form(object): """ dform = self.make_deform_form() field = dform[fieldname] + label = self.get_label(fieldname) + markdowns = self.get_field_markdowns() if self.field_visible(fieldname): # these attrs will be for the (*not* the widget) attrs = { ':horizontal': 'true', - 'label': self.get_label(fieldname), } # add some magic for file input fields @@ -915,11 +943,50 @@ class Form(object): # render the field widget or whatever html = field.serialize(use_buefy=True, **self.get_renderer_kwargs(fieldname)) - # TODO: why do we not get HTML literal from serialize() ? html = HTML.literal(html) + # may need a complex label + label_contents = [label] + + # add 'configure' icon if allowed + if self.can_edit_help: + icon = HTML.tag('b-icon', size='is-small', pack='fas', + icon='cog') + icon = HTML.tag('a', title="Configure field", c=[icon], + **{'@click.prevent': "configureFieldInit('{}')".format(fieldname)}) + label_contents.append(HTML.literal('   ')) + label_contents.append(icon) + + # add 'help' icon/tooltip if defined + if markdowns.get(fieldname): + icon = HTML.tag('b-icon', size='is-small', pack='fas', + icon='question-circle') + tooltip = render_markdown(markdowns[fieldname]) + + # nb. must apply hack to get