Add basic support for editing field help info

This commit is contained in:
Lance Edgar 2022-12-24 21:46:02 -06:00
parent 9fe9983bf9
commit 3befdc09e3
6 changed files with 218 additions and 7 deletions

View file

@ -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 <b-field> (*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('&nbsp; &nbsp;'))
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 <template #content> as final result
tooltip_template = HTML.tag('template', c=[tooltip],
**{'#content': 1})
tooltip_template = tooltip_template.replace(
HTML.literal('<template #content="1"'),
HTML.literal('<template #content'))
tooltip = HTML.tag('b-tooltip',
type='is-white',
size='is-large',
multilined='multilined',
c=[icon, tooltip_template])
label_contents.append(HTML.literal('&nbsp; &nbsp;'))
label_contents.append(tooltip)
# nb. must apply hack to get <template #label> as final result
label_template = HTML.tag('template', c=label_contents,
**{'#label': 1})
label_template = label_template.replace(
HTML.literal('<template #label="1"'),
HTML.literal('<template #label'))
# and finally wrap it all in a <b-field>
return HTML.tag('b-field', c=[html], **attrs)
return HTML.tag('b-field', c=[label_template, html], **attrs)
else: # hidden field