backoffice: add an inspect view to forms/card models (#30381)
This commit is contained in:
parent
9a21305a78
commit
1476f6ab7e
|
@ -16,7 +16,7 @@ from wcs.data_sources import NamedDataSource
|
|||
from wcs.formdef import FormDef
|
||||
from wcs.qommon.errors import ConnectionError
|
||||
from wcs.qommon.http_request import HTTPRequest
|
||||
from wcs.workflows import Workflow, WorkflowBackofficeFieldsFormDef
|
||||
from wcs.workflows import Workflow, WorkflowBackofficeFieldsFormDef, WorkflowVariablesFieldsFormDef
|
||||
from wcs.wscalls import NamedWsCall
|
||||
|
||||
from ..utilities import clean_temporary_pub, create_temporary_pub, get_app, login
|
||||
|
@ -895,8 +895,6 @@ def test_form_workflow_variables(pub):
|
|||
|
||||
Workflow.wipe()
|
||||
workflow = Workflow(name='Workflow One')
|
||||
from wcs.workflows import WorkflowVariablesFieldsFormDef
|
||||
|
||||
workflow.variables_formdef = WorkflowVariablesFieldsFormDef(workflow=workflow)
|
||||
workflow.variables_formdef.fields.append(
|
||||
fields.StringField(id='1', varname='test', label='Test', type='string')
|
||||
|
@ -947,8 +945,6 @@ def test_form_workflow_table_variables(pub):
|
|||
|
||||
Workflow.wipe()
|
||||
workflow = Workflow(name='Workflow One')
|
||||
from wcs.workflows import WorkflowVariablesFieldsFormDef
|
||||
|
||||
workflow.variables_formdef = WorkflowVariablesFieldsFormDef(workflow=workflow)
|
||||
workflow.variables_formdef.fields.append(
|
||||
fields.TableRowsField(id='1', varname='test', label='Test2', type='tablerows', columns=['a'])
|
||||
|
@ -996,8 +992,6 @@ def test_form_workflow_invalid_file_variable(pub):
|
|||
Workflow.wipe()
|
||||
|
||||
workflow = Workflow(name='Workflow One')
|
||||
from wcs.workflows import WorkflowVariablesFieldsFormDef
|
||||
|
||||
workflow.variables_formdef = WorkflowVariablesFieldsFormDef(workflow=workflow)
|
||||
workflow.variables_formdef.fields = [
|
||||
fields.StringField(id='1', varname='test', label='Test', type='string')
|
||||
|
@ -3421,3 +3415,117 @@ def test_field_display_locations_statistics_choice(pub):
|
|||
resp.form['varname'] = 'var_%s' % i
|
||||
resp = resp.form.submit('submit')
|
||||
assert 'statistics' in FormDef.get(formdef.id).fields[i].display_locations
|
||||
|
||||
|
||||
def test_admin_form_inspect(pub):
|
||||
create_superuser(pub)
|
||||
create_role(pub)
|
||||
|
||||
NamedDataSource.wipe()
|
||||
data_source = NamedDataSource(name='Foobar')
|
||||
data_source.data_source = {'type': 'json', 'value': 'http://remote.example.net/404'}
|
||||
data_source.store()
|
||||
|
||||
CardDef.wipe()
|
||||
carddef = CardDef()
|
||||
carddef.name = 'Baz'
|
||||
carddef.digest_templates = {'default': 'plop'}
|
||||
carddef.store()
|
||||
|
||||
Workflow.wipe()
|
||||
workflow = Workflow(name='Workflow One')
|
||||
workflow.variables_formdef = WorkflowVariablesFieldsFormDef(workflow=workflow)
|
||||
workflow.variables_formdef.fields.append(
|
||||
fields.StringField(id='1', varname='test', label='Test', type='string')
|
||||
)
|
||||
workflow.store()
|
||||
|
||||
FormDef.wipe()
|
||||
formdef = FormDef()
|
||||
formdef.name = 'form title'
|
||||
formdef.workflow_id = workflow.id
|
||||
formdef.fields = [
|
||||
fields.PageField(
|
||||
id='0',
|
||||
label='1st page',
|
||||
type='page',
|
||||
post_conditions=[
|
||||
{'condition': {'type': 'django', 'value': 'false'}, 'error_message': 'You shall not pass.'}
|
||||
],
|
||||
),
|
||||
fields.StringField(
|
||||
id='1', label='String field', varname='var_1', condition={'type': 'django', 'value': 'true'}
|
||||
),
|
||||
fields.StringField(id='2', label='String field digits', validation={'type': 'digits'}),
|
||||
fields.StringField(id='3', label='String field regex', validation={'type': 'regex', 'value': r'\d+'}),
|
||||
fields.ItemField(
|
||||
id='4',
|
||||
label='Date field',
|
||||
type='date',
|
||||
),
|
||||
fields.ItemField(id='5', label='Item field', type='item', items=['One', 'Two', 'Three']),
|
||||
fields.ItemField(
|
||||
id='6', label='Item field named data source', type='item', data_source={'type': 'foobar'}
|
||||
),
|
||||
fields.ItemField(
|
||||
id='7', label='Item field carddef data source', type='item', data_source={'type': 'carddef:baz'}
|
||||
),
|
||||
fields.ItemField(
|
||||
id='8',
|
||||
label='Item field json data source',
|
||||
type='item',
|
||||
data_source={'type': 'json', 'value': 'http://test'},
|
||||
),
|
||||
fields.ItemsField(id='9', label='Items field', type='items', items=['One', 'Two', 'Three']),
|
||||
fields.StringField(id='10', label='prefill', prefill={'type': 'user', 'value': 'email'}),
|
||||
fields.StringField(
|
||||
id='11', label='prefill2', prefill={'type': 'string', 'value': '{{plop}}', 'locked': True}
|
||||
),
|
||||
fields.FileField(
|
||||
id='12', label='file', automatic_image_resize=True, display_locations=['validation']
|
||||
),
|
||||
]
|
||||
formdef.workflow_options = {'test': 'plop'}
|
||||
formdef.store()
|
||||
|
||||
app = login(get_app(pub))
|
||||
resp = app.get('/backoffice/forms/%s/inspect' % formdef.id)
|
||||
|
||||
assert 'Test → plop' in resp.text # workflow option
|
||||
assert (
|
||||
resp.pyquery('[data-field-id="0"] .parameter-post_conditions').text()
|
||||
== 'Post Conditions:\nfalse - You shall not pass.'
|
||||
)
|
||||
assert (
|
||||
resp.pyquery('[data-field-id="1"] .parameter-condition').text() == 'Display Condition: true (Django)'
|
||||
)
|
||||
assert resp.pyquery('[data-field-id="2"] .parameter-validation').text() == 'Validation: Digits'
|
||||
assert (
|
||||
resp.pyquery('[data-field-id="3"] .parameter-validation').text()
|
||||
== 'Validation: Regular Expression - \\d+'
|
||||
)
|
||||
assert resp.pyquery('[data-field-id="5"] .parameter-items').text() == 'Choices: One, Two, Three'
|
||||
assert resp.pyquery('[data-field-id="6"] .parameter-data_source').text() == 'Data source: Foobar'
|
||||
assert (
|
||||
resp.pyquery('[data-field-id="7"] .parameter-data_source').text() == 'Data source: card model - Baz'
|
||||
)
|
||||
assert (
|
||||
resp.pyquery('[data-field-id="8"] .parameter-data_source').text()
|
||||
== 'Data source: JSON URL - http://test'
|
||||
)
|
||||
assert (
|
||||
resp.pyquery('[data-field-id="10"] .parameter-prefill').text()
|
||||
== 'Prefill:\nType: User Field\nValue: Email (builtin)'
|
||||
)
|
||||
assert (
|
||||
resp.pyquery('[data-field-id="11"] .parameter-prefill').text()
|
||||
== 'Prefill:\nType: String / Template\nValue: {{plop}}\nLocked'
|
||||
)
|
||||
assert (
|
||||
resp.pyquery('[data-field-id="12"] .parameter-automatic_image_resize').text()
|
||||
== 'Automatically resize uploaded images: Yes'
|
||||
)
|
||||
assert (
|
||||
resp.pyquery('[data-field-id="12"] .parameter-display_locations').text()
|
||||
== 'Display Locations: Validation Page'
|
||||
)
|
||||
|
|
|
@ -596,6 +596,7 @@ class WorkflowRoleDirectory(Directory):
|
|||
|
||||
|
||||
class FormDefPage(Directory):
|
||||
do_not_call_in_templates = True
|
||||
_q_exports = [
|
||||
'',
|
||||
'fields',
|
||||
|
@ -616,6 +617,7 @@ class FormDefPage(Directory):
|
|||
'overwrite',
|
||||
'qrcode',
|
||||
'information',
|
||||
'inspect',
|
||||
('public-url', 'public_url'),
|
||||
('backoffice-submission-roles', 'backoffice_submission_roles'),
|
||||
('logged-errors', 'logged_errors_dir'),
|
||||
|
@ -640,6 +642,7 @@ class FormDefPage(Directory):
|
|||
)
|
||||
readonly_message = _('This form is readonly.')
|
||||
management_view_label = _('Management view')
|
||||
inspect_template_name = 'wcs/backoffice/formdef-inspect.html'
|
||||
|
||||
def __init__(self, component, instance=None):
|
||||
try:
|
||||
|
@ -758,24 +761,10 @@ class FormDefPage(Directory):
|
|||
r += self.add_option_line('workflow-options', _('Options'), '')
|
||||
|
||||
if self.formdef.workflow.roles:
|
||||
if not self.formdef.workflow_roles:
|
||||
self.formdef.workflow_roles = {}
|
||||
workflow_roles = list((self.formdef.workflow.roles or {}).items())
|
||||
workflow_roles.sort(key=lambda x: '' if x[0] == '_receiver' else misc.simplify(x[1]))
|
||||
for (wf_role_id, wf_role_label) in workflow_roles:
|
||||
role_id = self.formdef.workflow_roles.get(wf_role_id)
|
||||
if role_id:
|
||||
try:
|
||||
role = get_publisher().role_class.get(role_id)
|
||||
role_label = role.name
|
||||
except KeyError:
|
||||
# removed role ?
|
||||
role_label = _('Unknown role (%s)') % role_id
|
||||
else:
|
||||
role_label = '-'
|
||||
for (wf_role_id, wf_role_label, role_label) in self.get_workflow_roles_elements():
|
||||
r += self.add_option_line('role/%s' % wf_role_id, wf_role_label, role_label)
|
||||
|
||||
r += self.add_option_line('roles', _('User Roles'), self._get_roles_label_and_auth_context('roles'))
|
||||
r += self.add_option_line('roles', _('User Roles'), self.get_roles_label_and_auth_context())
|
||||
r += self.add_option_line(
|
||||
'backoffice-submission-roles',
|
||||
_('Backoffice Submission Role'),
|
||||
|
@ -880,6 +869,24 @@ class FormDefPage(Directory):
|
|||
r += htmltext('</div>')
|
||||
return r.getvalue()
|
||||
|
||||
def get_workflow_roles_elements(self):
|
||||
if not self.formdef.workflow_roles:
|
||||
self.formdef.workflow_roles = {}
|
||||
workflow_roles = list((self.formdef.workflow.roles or {}).items())
|
||||
workflow_roles.sort(key=lambda x: '' if x[0] == '_receiver' else misc.simplify(x[1]))
|
||||
for (wf_role_id, wf_role_label) in workflow_roles:
|
||||
role_id = self.formdef.workflow_roles.get(wf_role_id)
|
||||
if role_id:
|
||||
try:
|
||||
role = get_publisher().role_class.get(role_id)
|
||||
role_label = role.name
|
||||
except KeyError:
|
||||
# removed role ?
|
||||
role_label = _('Unknown role (%s)') % role_id
|
||||
else:
|
||||
role_label = '-'
|
||||
yield (wf_role_id, wf_role_label, role_label)
|
||||
|
||||
def _get_roles_label(self, attribute):
|
||||
if getattr(self.formdef, attribute):
|
||||
roles = []
|
||||
|
@ -897,8 +904,8 @@ class FormDefPage(Directory):
|
|||
value = C_('roles|None')
|
||||
return value
|
||||
|
||||
def _get_roles_label_and_auth_context(self, attribute):
|
||||
value = self._get_roles_label(attribute)
|
||||
def get_roles_label_and_auth_context(self):
|
||||
value = self._get_roles_label('roles')
|
||||
if self.formdef.required_authentication_contexts:
|
||||
auth_contexts = get_publisher().get_supported_authentication_contexts()
|
||||
value += ' (%s)' % ', '.join(
|
||||
|
@ -924,6 +931,7 @@ class FormDefPage(Directory):
|
|||
if get_publisher().snapshot_class:
|
||||
r += htmltext('<li><a rel="popup" href="history/save">%s</a></li>') % _('Save snapshot')
|
||||
r += htmltext('<li><a href="history/">%s</a></li>') % _('History')
|
||||
r += htmltext('<li><a href="inspect">%s</a></li>') % _('Inspector')
|
||||
if not get_publisher().is_using_postgresql() and self.formdef_class == FormDef:
|
||||
r += htmltext('<li><a href="archive">%s</a></li>') % _('Archive')
|
||||
r += htmltext('</ul>')
|
||||
|
@ -1742,6 +1750,29 @@ class FormDefPage(Directory):
|
|||
self.formdef.workflow_options[widget.name] = widget.parse()
|
||||
self.formdef.store(comment=_('Change in workflow options'))
|
||||
|
||||
def inspect(self):
|
||||
self.html_top(self.formdef.name)
|
||||
get_response().breadcrumb.append(('inspect', _('Inspector')))
|
||||
context = {'formdef': self.formdef, 'view': self}
|
||||
if self.formdef.workflow.variables_formdef:
|
||||
context['workflow_options'] = {}
|
||||
variables_form_data = self.formdef.get_variable_options_for_form()
|
||||
for field in self.formdef.workflow.variables_formdef.fields:
|
||||
context['workflow_options'][field.label] = htmltext('%s') % field.get_view_value(
|
||||
variables_form_data.get(field.id)
|
||||
)
|
||||
context['workflow_roles'] = list(self.get_workflow_roles_elements())
|
||||
context['backoffice_submission_roles'] = self._get_roles_label('backoffice_submission_roles')
|
||||
if self.formdef.tracking_code_verify_fields:
|
||||
context['tracking_code_verify_fields_labels'] = ', '.join(
|
||||
[
|
||||
x.label
|
||||
for x in self.formdef.fields
|
||||
if str(x.id) in self.formdef.tracking_code_verify_fields
|
||||
]
|
||||
)
|
||||
return template.QommonTemplateResponse(templates=[self.inspect_template_name], context=context)
|
||||
|
||||
|
||||
class NamedDataSourcesDirectoryInForms(NamedDataSourcesDirectory):
|
||||
pass
|
||||
|
|
|
@ -30,6 +30,7 @@ class Category(XmlStorableObject):
|
|||
_names = 'categories'
|
||||
xml_root_node = 'category'
|
||||
backoffice_class = 'wcs.admin.categories.CategoryPage'
|
||||
backoffice_base_url = 'forms/categories/'
|
||||
|
||||
name = None
|
||||
url_name = None
|
||||
|
@ -92,6 +93,9 @@ class Category(XmlStorableObject):
|
|||
return True
|
||||
return False
|
||||
|
||||
def get_admin_url(self):
|
||||
return '%s/%s%s/' % (get_publisher().get_backoffice_url(), self.backoffice_base_url, self.id)
|
||||
|
||||
def store(self, *args, comment=None, snapshot_store_user=True, **kwargs):
|
||||
if not self.url_name:
|
||||
existing_slugs = {
|
||||
|
@ -214,6 +218,7 @@ class CardDefCategory(Category):
|
|||
_names = 'carddef_categories'
|
||||
xml_root_node = 'carddef_category'
|
||||
backoffice_class = 'wcs.admin.categories.CardDefCategoryPage'
|
||||
backoffice_base_url = 'cards/categories/'
|
||||
|
||||
# declarations for serialization
|
||||
XML_NODES = [
|
||||
|
@ -236,6 +241,7 @@ class WorkflowCategory(Category):
|
|||
_names = 'workflow_categories'
|
||||
xml_root_node = 'workflow_category'
|
||||
backoffice_class = 'wcs.admin.categories.WorkflowCategoryPage'
|
||||
backoffice_base_url = 'workflows/categories/'
|
||||
|
||||
# declarations for serialization
|
||||
XML_NODES = [
|
||||
|
@ -257,6 +263,7 @@ class BlockCategory(Category):
|
|||
_names = 'block_categories'
|
||||
xml_root_node = 'block_category'
|
||||
backoffice_class = 'wcs.admin.categories.BlockCategoryPage'
|
||||
backoffice_base_url = 'forms/blocks/categories/'
|
||||
|
||||
# declarations for serialization
|
||||
XML_NODES = [
|
||||
|
@ -277,6 +284,7 @@ class MailTemplateCategory(Category):
|
|||
_names = 'mail_template_categories'
|
||||
xml_root_node = 'mail_template_category'
|
||||
backoffice_class = 'wcs.admin.categories.MailTemplateCategoryPage'
|
||||
backoffice_base_url = 'workflows/mail-templates/categories/'
|
||||
|
||||
# declarations for serialization
|
||||
XML_NODES = [
|
||||
|
@ -297,6 +305,7 @@ class DataSourceCategory(Category):
|
|||
_names = 'data_source_categories'
|
||||
xml_root_node = 'data_source_category'
|
||||
backoffice_class = 'wcs.admin.categories.DataSourceCategoryPage'
|
||||
backoffice_base_url = 'forms/data-sources/categories/'
|
||||
|
||||
# declarations for serialization
|
||||
XML_NODES = [
|
||||
|
|
159
wcs/fields.py
159
wcs/fields.py
|
@ -48,6 +48,7 @@ from .qommon.form import (
|
|||
EmailWidget,
|
||||
FileSizeWidget,
|
||||
FileWithPreviewWidget,
|
||||
Form,
|
||||
HiddenWidget,
|
||||
HtmlWidget,
|
||||
IntWidget,
|
||||
|
@ -137,7 +138,7 @@ class PrefillSelectionWidget(CompositeWidget):
|
|||
if not self.value or self.value.get('type') == 'none':
|
||||
self.value = {}
|
||||
|
||||
prefill_types = collections.OrderedDict(options)
|
||||
self.prefill_types = prefill_types = collections.OrderedDict(options)
|
||||
self.add(
|
||||
StringWidget,
|
||||
'value_string',
|
||||
|
@ -690,6 +691,129 @@ class Field:
|
|||
|
||||
yield NamedDataSource.get_by_slug(data_source_type, ignore_errors=True)
|
||||
|
||||
def get_parameters_view(self):
|
||||
r = TemplateIO(html=True)
|
||||
form = Form()
|
||||
self.fill_admin_form(form)
|
||||
parameters = [x for x in self.get_admin_attributes() if getattr(self, x, None) is not None]
|
||||
r += htmltext('<ul>')
|
||||
for parameter in parameters:
|
||||
widget = form.get_widget(parameter)
|
||||
if not widget:
|
||||
continue
|
||||
label = self.get_parameter_view_label(widget, parameter)
|
||||
if not label:
|
||||
continue
|
||||
value = getattr(self, parameter, Ellipsis)
|
||||
if value is None or value == getattr(self.__class__, parameter, Ellipsis):
|
||||
continue
|
||||
parameter_view_value = self.get_parameter_view_value(widget, parameter)
|
||||
if parameter_view_value:
|
||||
r += htmltext('<li class="parameter-%s">' % parameter)
|
||||
r += htmltext('<span class="parameter">%s</span> ') % _('%s:') % label
|
||||
r += parameter_view_value
|
||||
r += htmltext('</li>')
|
||||
r += htmltext('</ul>')
|
||||
return r.getvalue()
|
||||
|
||||
def get_parameter_view_label(self, widget, parameter):
|
||||
if hasattr(self, 'get_%s_parameter_view_label' % parameter):
|
||||
return getattr(self, 'get_%s_parameter_view_label' % parameter)()
|
||||
return widget.get_title()
|
||||
|
||||
def get_parameter_view_value(self, widget, parameter):
|
||||
if hasattr(self, 'get_%s_parameter_view_value' % parameter):
|
||||
return getattr(self, 'get_%s_parameter_view_value' % parameter)(widget)
|
||||
value = getattr(self, parameter)
|
||||
if isinstance(value, bool):
|
||||
return str(_('Yes') if value else _('No'))
|
||||
elif hasattr(widget, 'options') and value:
|
||||
if not isinstance(widget, CheckboxesWidget):
|
||||
value = [value]
|
||||
value_labels = []
|
||||
for option in widget.options:
|
||||
if isinstance(option, tuple):
|
||||
if option[0] in value:
|
||||
value_labels.append(str(option[1]))
|
||||
else:
|
||||
if option in value:
|
||||
value_labels.append(str(option))
|
||||
return ', '.join(value_labels) if value_labels else '-'
|
||||
elif isinstance(value, list):
|
||||
return ', '.join(value)
|
||||
else:
|
||||
return str(value)
|
||||
|
||||
def get_prefill_parameter_view_value(self, widget):
|
||||
value = getattr(self, 'prefill', None)
|
||||
if not value or value.get('type') == 'none':
|
||||
return
|
||||
r = TemplateIO(html=True)
|
||||
r += htmltext('<ul>')
|
||||
r += htmltext('<li><span class="parameter">%s%s</span> %s</li>') % (
|
||||
_('Type'),
|
||||
_(':'),
|
||||
widget.prefill_types.get(value.get('type')),
|
||||
)
|
||||
if value.get('type') in ('user', 'geolocation'):
|
||||
select_widget = widget.get_widget('value_%s' % value['type'])
|
||||
labels = {x[0]: x[1] for x in select_widget.options}
|
||||
r += htmltext('<li><span class="parameter">%s%s</span> %s</li>') % (
|
||||
_('Value'),
|
||||
_(':'),
|
||||
labels.get(value.get('value'), '-'),
|
||||
)
|
||||
else:
|
||||
r += htmltext('<li><span class="parameter">%s%s</span> %s</li>') % (
|
||||
_('Value'),
|
||||
_(':'),
|
||||
value.get('value'),
|
||||
)
|
||||
if value.get('locked'):
|
||||
r += htmltext('<li>%s</li>') % _('Locked')
|
||||
r += htmltext('</ul>')
|
||||
return r.getvalue()
|
||||
|
||||
def get_data_source_parameter_view_value(self, widget):
|
||||
value = getattr(self, 'data_source', None)
|
||||
if not value or value.get('type') == 'none':
|
||||
return
|
||||
|
||||
if value.get('type').startswith('carddef:'):
|
||||
from wcs.carddef import CardDef
|
||||
|
||||
parts = value['type'].split(':')
|
||||
try:
|
||||
carddef = CardDef.get_by_urlname(parts[1])
|
||||
except KeyError:
|
||||
return _('deleted card model')
|
||||
custom_view = CardDef.get_data_source_custom_view(value['type'], carddef=carddef)
|
||||
if custom_view:
|
||||
return _('card model: %s, custom view: %s') % (carddef.name, custom_view.title)
|
||||
return '%s - %s' % (_('card model'), carddef.name)
|
||||
|
||||
data_source_types = {
|
||||
'json': _('JSON URL'),
|
||||
'jsonp': _('JSONP URL'),
|
||||
'geojson': _('GeoJSON URL'),
|
||||
'formula': _('Python Expression'),
|
||||
}
|
||||
if value.get('type') in data_source_types:
|
||||
return '%s - %s' % (data_source_types[value.get('type')], value.get('value'))
|
||||
|
||||
from wcs.data_sources import NamedDataSource
|
||||
|
||||
data_source = NamedDataSource.get_by_slug(value['type'])
|
||||
return data_source.name
|
||||
|
||||
def get_condition_parameter_view_value(self, widget):
|
||||
if not self.condition or self.condition.get('type') == 'none':
|
||||
return
|
||||
return htmltext('<tt class="condition">%s</tt> <span class="condition-type">(%s)</span>') % (
|
||||
self.condition['value'],
|
||||
{'django': 'Django', 'python': 'Python'}.get(self.condition['type']),
|
||||
)
|
||||
|
||||
def __repr__(self):
|
||||
return '<%s %s %r>' % (self.__class__.__name__, self.id, self.label and self.label[:64])
|
||||
|
||||
|
@ -1168,6 +1292,15 @@ class StringField(WidgetField):
|
|||
super().init_with_xml(elem, charset, include_id=include_id)
|
||||
self.migrate()
|
||||
|
||||
def get_validation_parameter_view_value(self, widget):
|
||||
if not self.validation:
|
||||
return
|
||||
validation_type = self.validation['type']
|
||||
validation_types = {x: y['title'] for x, y in ValidationWidget.validation_methods.items()}
|
||||
if validation_type in ('regex', 'django'):
|
||||
return '%s - %s' % (validation_types.get(validation_type), self.validation['value'])
|
||||
return str(validation_types.get(validation_type))
|
||||
|
||||
|
||||
register_field_class(StringField)
|
||||
|
||||
|
@ -1905,6 +2038,15 @@ class ItemFieldMixin:
|
|||
data_source_type.set_value(None)
|
||||
data_source_type.transfer_form_value(get_request())
|
||||
|
||||
def get_items_parameter_view_label(self):
|
||||
if self.data_source:
|
||||
# skip field if there's a data source
|
||||
return None
|
||||
return str(_('Choices'))
|
||||
|
||||
def get_data_source_parameter_view_label(self):
|
||||
return str(_('Data source'))
|
||||
|
||||
|
||||
class ItemField(WidgetField, MapOptionsMixin, ItemFieldMixin):
|
||||
key = 'item'
|
||||
|
@ -2225,8 +2367,8 @@ class ItemField(WidgetField, MapOptionsMixin, ItemFieldMixin):
|
|||
|
||||
def get_admin_attributes(self):
|
||||
return WidgetField.get_admin_attributes(self) + [
|
||||
'items',
|
||||
'display_mode',
|
||||
'items',
|
||||
'data_source',
|
||||
'in_filters',
|
||||
'anonymise',
|
||||
|
@ -2741,6 +2883,19 @@ class PageField(Field):
|
|||
for post_condition in self.post_conditions or []:
|
||||
yield post_condition.get('condition')
|
||||
|
||||
def get_post_conditions_parameter_view_value(self, widget):
|
||||
if not self.post_conditions:
|
||||
return
|
||||
r = TemplateIO(html=True)
|
||||
r += htmltext('<ul>')
|
||||
for post_condition in self.post_conditions:
|
||||
r += htmltext('<li>%s - %s</li>') % (
|
||||
post_condition.get('condition').get('value'),
|
||||
post_condition.get('error_message'),
|
||||
)
|
||||
r += htmltext('</ul>')
|
||||
return r.getvalue()
|
||||
|
||||
|
||||
register_field_class(PageField)
|
||||
|
||||
|
|
|
@ -873,6 +873,9 @@ class FormDef(StorableObject):
|
|||
def get_page(self, page_no):
|
||||
return [x for x in self.fields if x.type == 'page'][page_no]
|
||||
|
||||
def page_count(self):
|
||||
return len([x for x in self.fields if x.type == 'page']) or 1
|
||||
|
||||
def create_view_form(self, dict=None, use_tokens=True, visible=True):
|
||||
dict = dict or {}
|
||||
form = Form(enctype='multipart/form-data', use_tokens=use_tokens)
|
||||
|
|
|
@ -1662,8 +1662,38 @@ div.expanded-statuses div.status h4::before {
|
|||
font-size: 90%;
|
||||
}
|
||||
|
||||
div.expanded-statuses div.status ul span.parameter {
|
||||
color: #666;
|
||||
div.inspect-form-tabs,
|
||||
div.inspect-field,
|
||||
div.expanded-statuses div.status {
|
||||
ul span.parameter {
|
||||
color: #666;
|
||||
}
|
||||
}
|
||||
|
||||
.inspect-field {
|
||||
margin: 0.5em 0 1em 0;
|
||||
h4 {
|
||||
margin: 0.5em 0;
|
||||
&:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
&.inspect-field--page:not(.inspect-field--first) {
|
||||
border-top: 1px solid #ccc;
|
||||
padding-top: 0.5em;
|
||||
}
|
||||
}
|
||||
|
||||
[role=tabpanel] {
|
||||
> .pk-information:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.condition-type,
|
||||
.inspect-field-type {
|
||||
font-weight: normal;
|
||||
font-size: 90%;
|
||||
}
|
||||
|
||||
pre.wrapping-pre {
|
||||
|
@ -1702,6 +1732,19 @@ form div.page > div {
|
|||
}
|
||||
}
|
||||
|
||||
.inspect-tabs {
|
||||
ul {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
li {
|
||||
margin-left: 1em;
|
||||
&::marker {
|
||||
color: #666;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ul.biglist.form-inspector {
|
||||
padding-top: 0;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,86 @@
|
|||
{% extends "wcs/backoffice/base.html" %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block appbar %}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<div class="pk-tabs inspect-tabs inspect-form-tabs">
|
||||
<div class="pk-tabs--tab-list" role="tablist">
|
||||
<button role="tab" aria-selected="true" aria-controls="inspect-infos" id="tab-infos" tabindex="0">{% trans "Information" %}</button>
|
||||
<button role="tab" aria-selected="false" aria-controls="inspect-workflow" id="tab-workflow" tabindex="-1">{% trans "Workflow" %}</button>
|
||||
<button role="tab" aria-selected="false" aria-controls="inspect-options" id="tab-options" tabindex="-1">{% trans "Options" %}</button>
|
||||
<button role="tab" aria-selected="false" aria-controls="inspect-fields" id="tab-fields" tabindex="-1">{% trans "Fields" %}</button>
|
||||
</div>
|
||||
<div class="pk-tabs--container">
|
||||
|
||||
<div id="inspect-infos" role="tabpanel" tabindex="0" aria-labelledby="tab-info">
|
||||
<ul>
|
||||
<li><span class="parameter">{% trans "Title" %}{% trans ":" %}</span> {{ formdef.name|default:"-" }}</li>
|
||||
<li><span class="parameter">{% trans "Description" %}{% trans ":" %}</span> {{ formdef.description|default:"-"|safe }}</li>
|
||||
<li><span class="parameter">{% trans "Keywords" %}{% trans ":" %}</span> {{ formdef.keywords|default:"-" }}</li>
|
||||
<li><span class="parameter">{% trans "Category" %}{% trans ":" %}</span> {% if formdef.category %}<a href="{{ formdef.category.get_admin_url }}">{{ formdef.category.name }}</a>{% else %}-{% endif %}</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div id="inspect-workflow" role="tabpanel" tabindex="0" aria-labelledby="tab-workflow" hidden>
|
||||
<ul>
|
||||
<li><span class="parameter">{% trans "Workflow" %}{% trans ":" %}</span> <a href="{{ formdef.workflow.get_admin_url }}">{{ formdef.workflow.name }}</a></li>
|
||||
<li><span class="parameter">{% trans "Options" %}{% trans ":" %}</span> {% if not workflow_options %}-{% else %}<ul>
|
||||
{% for label, value in workflow_options.items %}
|
||||
<li>{{ label }} → {{ value|safe|default:"-" }}</li>
|
||||
{% endfor %}
|
||||
</ul>{% endif %}</li>
|
||||
{% for wf_role_id, wf_role_label, role_label in workflow_roles %}
|
||||
<li><span class="parameter">{{ wf_role_label }}{% trans ":" %}</span> {{ role_label|default:"-" }}</li>
|
||||
{% endfor %}
|
||||
<li><span class="parameter">{% trans "User Roles" %}{% trans ":" %}</span> {{ view.get_roles_label_and_auth_context|default:"-" }}</li>
|
||||
<li><span class="parameter">{% trans "Backoffice Submission Role" %}{% trans ":" %}</span> {{ backoffice_submission_roles|default:"-" }}</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div id="inspect-options" role="tabpanel" tabindex="0" aria-labelledby="tab-options" hidden>
|
||||
<ul>
|
||||
<li><span class="parameter">{% trans "Confirmation Page" %}{% trans ":" %}</span> {{ formdef.confirmation|yesno }}</li>
|
||||
<li><span class="parameter">{% trans "Limit to one form" %}{% trans ":" %}</span> {{ formdef.only_allow_one|yesno }}</li>
|
||||
{% if formdef.roles %}
|
||||
<li><span class="parameter">{% trans "Display to unlogged users" %}{% trans ":" %}</span> {{ formdef.always_advertise|yesno }}</li>
|
||||
{% endif %}
|
||||
<li><span class="parameter">{% trans "Include button to download all files" %}{% trans ":" %}</span> {{ formdef.include_download_all_button|yesno }}</li>
|
||||
<li><span class="parameter">{% trans "Skip from per user view" %}{% trans ":" %}</span> {{ formdef.skip_from_360_view|yesno }}</li>
|
||||
<li><span class="parameter">{% trans "Tracking codes" %}{% trans ":" %}</span> {{ formdef.enable_tracking_codes|yesno }}</li>
|
||||
{% if formdef.enable_tracking_codes %}
|
||||
<li><span class="parameter">{% trans "Fields to check after entering the tracking code" %}{% trans ":" %}</span> {{ tracking_code_verify_fields_labels|default:"-" }}</li>
|
||||
{% endif %}
|
||||
<li><span class="parameter">{% trans "Lifespan of drafts (in days)" %}{% trans ":" %}</span> {{ formdef.drafts_lifespan|default_if_none:_('default value') }}</li>
|
||||
<li><span class="parameter">{% trans "Templates" %}</span>
|
||||
<ul>
|
||||
<li><span class="parameter">{% trans "Digest" %}{% trans ":" %}</span> {{ formdef.default_digest_template|default:"-" }}</li>
|
||||
<li><span class="parameter">{% trans "Lateral Block" %}{% trans ":" %}</span> {{ formdef.lateral_template|default:"-" }}</li>
|
||||
<li><span class="parameter">{% trans "Submission Lateral Block" %}{% trans ":" %}</span> {{ formdef.submission_lateral_template|default:"-" }}</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><span class="parameter">{% trans "Disable access to form" %}{% trans ":" %}</span> {{ formdef.disabled|yesno }}</li>
|
||||
<li><span class="parameter">{% trans "Redirection when disabled" %}{% trans ":" %}</span> {{ formdef.disabled_redirection|default:"-" }}</li>
|
||||
<li><span class="parameter">{% trans "Publication date" %}{% trans ":" %}</span> {{ formdef.publication_date|default:"-" }}</li>
|
||||
<li><span class="parameter">{% trans "Expiration date" %}{% trans ":" %}</span> {{ formdef.expiration_date|default:"-" }}</li>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div id="inspect-fields" role="tabpanel" tabindex="0" aria-labelledby="tab-fields" hidden>
|
||||
<div class="pk-information"><p>
|
||||
{% blocktrans count page_count=formdef.page_count %}{{ page_count }} page{% plural %}{{ page_count }} pages{% endblocktrans %},
|
||||
{% blocktrans count fields_count=formdef.fields|count %}{{ fields_count }} field{% plural %}{{ fields_count }} fields.{% endblocktrans %}
|
||||
</p></div>
|
||||
{% for field in formdef.fields %}
|
||||
<div class="inspect-field inspect-field--{{ field.key }} {% if forloop.first %}inspect-field--first{% endif %}" data-field-id="{{ field.id }}">
|
||||
<h4><a href="fields/{{ field.id }}/">{{ field.ellipsized_label }}</a> <span class="inspect-field-type">- {{ field.get_type_label }}</span></h4>
|
||||
{{ field.get_parameters_view|safe }}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
{% endblock %}
|
Loading…
Reference in New Issue