backoffice: use a template to render formdef/carddef pages (#78148)
gitea/wcs/pipeline/head This commit looks good Details

This commit is contained in:
Frédéric Péters 2023-06-03 22:58:48 +02:00
parent 6e552c3fff
commit 45b8e6aad8
6 changed files with 316 additions and 322 deletions

View File

@ -3972,14 +3972,14 @@ def test_forms_last_test_result(pub, formdef):
app = login(get_app(pub))
resp = app.get('/backoffice/forms/1/')
assert '<h2>form title</h2>' in resp.text
assert resp.pyquery('h2').text() == 'form title'
pub.site_options.set('options', 'enable-tests', 'true')
with open(os.path.join(pub.app_dir, 'site-options.cfg'), 'w') as fd:
pub.site_options.write(fd)
resp = app.get('/backoffice/forms/1/')
assert '<h2>form title</h2>' in resp.text
assert resp.pyquery('h2').text() == 'form title'
test_result = TestResult()
test_result.object_type = formdef.get_table_name()
@ -3992,17 +3992,16 @@ def test_forms_last_test_result(pub, formdef):
for url in ('/backoffice/forms/1/', '/backoffice/forms/1/fields/'):
resp = app.get(url)
assert '<h2>form title <a href="%s"' % test_result.get_admin_url() in resp.text
assert 'test-success' in resp.text
assert 'test-failure' not in resp.text
assert resp.pyquery('h2 .test-success')
assert not resp.pyquery('h2 .test-failure')
test_result.success = False
test_result.store()
for url in ('/backoffice/forms/1/', '/backoffice/forms/1/fields/'):
resp = app.get(url)
assert 'test-failure' in resp.text
assert 'test-success' not in resp.text
assert not resp.pyquery('h2 .test-success')
assert resp.pyquery('h2 .test-failure')
test_result.success = True
test_result.id = None
@ -4011,13 +4010,13 @@ def test_forms_last_test_result(pub, formdef):
for url in ('/backoffice/forms/1/', '/backoffice/forms/1/fields/'):
resp = app.get(url)
assert 'test-success' in resp.text
assert 'test-failure' not in resp.text
assert resp.pyquery('h2 .test-success')
assert not resp.pyquery('h2 .test-failure')
TestDef.remove_object(testdef.id)
for url in ('/backoffice/forms/1/', '/backoffice/forms/1/fields/'):
resp = app.get(url)
assert '<h2>form title</h2>' in resp.text
assert resp.pyquery('h2').text() == 'form title'
def test_jump_identifiers_unicity(pub):

View File

@ -647,8 +647,7 @@ class FormDefPage(Directory):
'The form has been successfully overwritten. '
'Do note it kept its existing address and role and workflow parameters.'
)
readonly_message = _('This form is readonly.')
management_view_label = _('Management view')
formdef_template_name = 'wcs/backoffice/formdef.html'
inspect_template_name = 'wcs/backoffice/formdef-inspect.html'
def __init__(self, component, instance=None):
@ -686,62 +685,127 @@ class FormDefPage(Directory):
def _q_index(self):
get_response().set_title(title=self.formdef.name)
r = TemplateIO(html=True)
get_response().filter['sidebar'] = self.get_sidebar()
get_response().add_javascript(
['jquery.js', 'widget_list.js', 'qommon.wysiwyg.js', 'qommon.fileupload.js', 'select2.js']
['popup.js', 'widget_list.js', 'qommon.wysiwyg.js', 'qommon.fileupload.js', 'select2.js']
)
DateWidget.prepare_javascript()
r += htmltext('<div id="appbar">')
r += htmltext('<h2>%s') % self.formdef.name
r += utils.last_test_result_block(self.formdef)
r += htmltext('</h2>')
r += htmltext('<span class="actions">')
if not self.formdef.is_readonly():
r += htmltext('<a rel="popup" href="title">%s</a>') % _('change title')
r += htmltext('</span>')
r += htmltext('</div>')
r += utils.last_modification_block(obj=self.formdef)
r += get_session().display_message()
r += htmltext('<div class="bo-block">')
r += htmltext('<h3>%s</h3>') % _('Information')
r += htmltext('<ul class="biglist optionslist">')
r += self.add_option_line(
'options/description',
_('Description'),
self.formdef.description
and pgettext_lazy('description', 'On')
or pgettext_lazy('description', 'None'),
user = get_request().user
context = {
'tests_enabled': get_publisher().has_site_option('enable-tests'),
'has_qrcode': bool(qrcode is not None),
'view': self,
'formdef': self.formdef,
'has_sidebar': True,
'include_management_link': bool(user.is_admin or self.formdef.is_of_concern_for_user(user)),
'options': self.get_option_lines(),
'has_captcha_option': get_publisher().has_site_option('formdef-captcha-option'),
'has_appearance_keywords': get_publisher().has_site_option('formdef-appearance-keywords'),
}
return template.QommonTemplateResponse(
templates=[self.formdef_template_name],
context=context,
is_django_native=True,
)
r += self.add_option_line(
'options/keywords',
_('Keywords'),
self.formdef.keywords and self.formdef.keywords or pgettext_lazy('keywords', 'None'),
)
r += self.add_option_line(
'options/category',
_('Category'),
self.formdef.category_id
and self.formdef.category
and self.formdef.category.name
or pgettext_lazy('category', 'None'),
)
r += htmltext('</ul>')
r += htmltext('</div>')
r += htmltext('<div class="splitcontent-left">')
r += htmltext('<div class="bo-block">')
r += htmltext('<h3>%s</h3>') % _('Workflow')
r += htmltext('<ul class="biglist optionslist">')
def snapshot_info_block(self):
return utils.snapshot_info_block(snapshot=self.formdef.snapshot_object)
def last_modification_block(self):
return utils.last_modification_block(obj=self.formdef)
def last_test_result_block(self):
return utils.last_test_result_block(self.formdef)
def errors_block(self):
return LoggedErrorsDirectory.errors_block(
formdef_class=self.formdef_class, formdef_id=self.formdef.id
)
def get_option_lines(self):
options = {
'description': self.add_option_line(
'options/description',
_('Description'),
self.formdef.description
and pgettext_lazy('description', 'On')
or pgettext_lazy('description', 'None'),
),
'keywords': self.add_option_line(
'options/keywords',
_('Keywords'),
self.formdef.keywords and self.formdef.keywords or pgettext_lazy('keywords', 'None'),
),
'category': self.add_option_line(
'options/category',
_('Category'),
self.formdef.category_id
and self.formdef.category
and self.formdef.category.name
or pgettext_lazy('category', 'None'),
),
'user_roles': self.add_option_line(
'roles', _('User Roles'), self.get_roles_label_and_auth_context()
),
'backoffice_submission_roles': self.add_option_line(
'backoffice-submission-roles',
_('Backoffice Submission Role'),
self._get_roles_label('backoffice_submission_roles'),
),
'confirmation': self.add_option_line(
'options/confirmation',
_('Confirmation Page'),
self.formdef.confirmation
and pgettext_lazy('confirmation page', 'Enabled')
or pgettext_lazy('confirmation page', 'Disabled'),
),
'only_allow_one': self.add_option_line(
'options/only_allow_one',
_('Limit to one form'),
self.formdef.only_allow_one
and pgettext_lazy('limit to one', 'Enabled')
or pgettext_lazy('limit to one', 'Disabled'),
),
'always_advertise': self.add_option_line(
'options/always_advertise',
_('Display to unlogged users'),
self.formdef.always_advertise
and pgettext_lazy('display to unlogged', 'Enabled')
or pgettext_lazy('display to unlogged', 'Disabled'),
),
'management': self.add_option_line(
'options/management',
_('Management'),
_('Custom')
if (self.formdef.skip_from_360_view or self.formdef.include_download_all_button)
else _('Default'),
),
'tracking_code': self.add_option_line(
'options/tracking_code',
_('Tracking Code'),
self.formdef.enable_tracking_codes
and pgettext_lazy('tracking code', 'Enabled')
or pgettext_lazy('tracking code', 'Disabled'),
),
'captcha': self.add_option_line(
'options/captcha',
_('CAPTCHA for anonymous users'),
self.formdef.has_captcha
and pgettext_lazy('captcha', 'Enabled')
or pgettext_lazy('captcha', 'Disabled'),
),
'appearance': self.add_option_line(
'options/appearance',
_('Appearance'),
self.formdef.appearance_keywords
and self.formdef.appearance_keywords
or pgettext_lazy('appearance', 'Standard'),
),
}
unknown_wf = self.formdef.workflow.id == Workflow.get_unknown_workflow().id
if get_publisher().get_backoffice_root().is_accessible('workflows') and not unknown_wf:
# custom option line to also include a link to the workflow itself.
r += htmltext(
options['workflow'] = htmltext(
'<li><a rel="popup" href="%(link)s">'
'<span class="label">%(label)s</span> '
'<span class="value offset">%(current_value)s</span>'
@ -757,98 +821,27 @@ class FormDefPage(Directory):
}
)
else:
r += self.add_option_line(
options['workflow'] = self.add_option_line(
'workflow', _('Workflow'), self.formdef.workflow and self.formdef.workflow.name or '-'
)
options['workflow_options'] = ''
if self.formdef.workflow_id:
pristine_workflow = Workflow.get(self.formdef.workflow_id, ignore_errors=True)
if pristine_workflow and pristine_workflow.variables_formdef:
r += self.add_option_line('workflow-variables', _('Options'), '')
options['workflow_options'] = self.add_option_line('workflow-variables', _('Options'), '')
elif self.formdef.workflow_options:
# there are no variables defined but there are some values
# in workflow_options, this is probably the legacy stuff.
if any(x for x in self.formdef.workflow_options if '*' in x):
r += self.add_option_line('workflow-options', _('Options'), '')
options['workflow_options'] = self.add_option_line('workflow-options', _('Options'), '')
options['workflow_roles_list'] = []
if self.formdef.workflow.roles:
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())
r += self.add_option_line(
'backoffice-submission-roles',
_('Backoffice Submission Role'),
self._get_roles_label('backoffice_submission_roles'),
)
r += htmltext('</ul>')
r += htmltext('</div>')
r += htmltext('</div>')
r += htmltext('<div class="splitcontent-right">')
r += htmltext('<div class="bo-block">')
r += htmltext('<h3>%s</h3>') % _('Options')
r += htmltext('<ul class="biglist optionslist">')
r += self.add_option_line(
'options/confirmation',
_('Confirmation Page'),
self.formdef.confirmation
and pgettext_lazy('confirmation page', 'Enabled')
or pgettext_lazy('confirmation page', 'Disabled'),
)
r += self.add_option_line(
'options/only_allow_one',
_('Limit to one form'),
self.formdef.only_allow_one
and pgettext_lazy('limit to one', 'Enabled')
or pgettext_lazy('limit to one', 'Disabled'),
)
if self.formdef.roles:
r += self.add_option_line(
'options/always_advertise',
_('Display to unlogged users'),
self.formdef.always_advertise
and pgettext_lazy('display to unlogged', 'Enabled')
or pgettext_lazy('display to unlogged', 'Disabled'),
)
r += self.add_option_line(
'options/management',
_('Management'),
_('Custom')
if (self.formdef.skip_from_360_view or self.formdef.include_download_all_button)
else _('Default'),
)
r += self.add_option_line(
'options/tracking_code',
_('Tracking Code'),
self.formdef.enable_tracking_codes
and pgettext_lazy('tracking code', 'Enabled')
or pgettext_lazy('tracking code', 'Disabled'),
)
if get_publisher().has_site_option('formdef-captcha-option'):
r += self.add_option_line(
'options/captcha',
_('CAPTCHA for anonymous users'),
self.formdef.has_captcha
and pgettext_lazy('captcha', 'Enabled')
or pgettext_lazy('captcha', 'Disabled'),
)
if get_publisher().has_site_option('formdef-appearance-keywords'):
r += self.add_option_line(
'options/appearance',
_('Appearance'),
self.formdef.appearance_keywords
and self.formdef.appearance_keywords
or pgettext_lazy('appearance', 'Standard'),
)
options['workflow_roles_list'].append(
self.add_option_line('role/%s' % wf_role_id, wf_role_label, role_label)
)
if (
self.formdef.default_digest_template
@ -858,7 +851,9 @@ class FormDefPage(Directory):
template_status = pgettext_lazy('template', 'Custom')
else:
template_status = pgettext_lazy('template', 'None')
r += self.add_option_line('options/templates', _('Templates'), template_status, popup=False)
options['templates'] = self.add_option_line(
'options/templates', _('Templates'), template_status, popup=False
)
online_status = pgettext_lazy('online status', 'Active')
if self.formdef.disabled:
@ -869,22 +864,10 @@ class FormDefPage(Directory):
elif self.formdef.is_disabled():
# disabled by date
online_status = pgettext_lazy('online status', 'Inactive by date')
r += self.add_option_line('options/online_status', _('Online Status'), online_status)
r += htmltext('</ul>')
r += htmltext('</div>')
r += htmltext('</div>')
r += htmltext('<div class="bo-block clear">')
r += htmltext(
'<h3 class="clear">%s <span class="change"><a class="pk-button" href="fields/">%s</a></span></h3>'
) % (
_('Fields'),
_('edit'),
options['online_status'] = self.add_option_line(
'options/online_status', _('Online Status'), online_status
)
r += self.get_preview()
r += htmltext('</div>')
return r.getvalue()
return options
def get_workflow_roles_elements(self):
if not self.formdef.workflow_roles:
@ -934,47 +917,6 @@ class FormDefPage(Directory):
)
return value
def get_sidebar(self):
r = TemplateIO(html=True)
if self.formdef.is_readonly():
r += htmltext('<div class="infonotice"><p>%s</p></div>') % self.readonly_message
r += utils.snapshot_info_block(snapshot=self.formdef.snapshot_object)
return r.getvalue()
r += htmltext('<ul id="sidebar-actions">')
r += htmltext('<li><a href="delete" rel="popup">%s</a></li>') % _('Delete')
r += htmltext('<li><a href="duplicate" rel="popup">%s</a></li>') % _('Duplicate')
r += htmltext('<li><a rel="popup" href="overwrite">%s</a></li>') % _('Overwrite with new import')
r += htmltext('<li><a href="export">%s</a></li>') % _('Export')
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 get_publisher().has_site_option('enable-tests'):
r += htmltext('<li><a href="tests/">%s</a></li>') % _('Tests')
r += htmltext('</ul>')
r += htmltext('<ul>')
if self.formdef_class == FormDef:
if self.formdef.is_disabled():
r += htmltext('<li><a href="%s">%s</a></li>') % (
self.formdef.get_url(preview=True),
_('Preview Online'),
)
else:
r += htmltext('<li><a href="%s">%s</a></li>') % (self.formdef.get_url(), _('Display Online'))
r += htmltext('<li><a href="public-url" rel="popup">%s</a></li>') % _('Display public URL')
if qrcode is not None:
r += htmltext('<li><a href="qrcode" rel="popup">%s</a></li>') % _('Display QR Code')
user = get_request().user
if user.is_admin or self.formdef.is_of_concern_for_user(user):
r += htmltext('<li><a href="%s">%s</a></li>') % (
self.formdef.get_url(backoffice=True),
self.management_view_label,
)
r += htmltext('</ul>')
r += LoggedErrorsDirectory.errors_block(formdef_class=self.formdef_class, formdef_id=self.formdef.id)
return r.getvalue()
def public_url(self):
get_response().set_title(title=self.formdef.name)
get_response().breadcrumb.append(('public-url', _('Public URL')))

View File

@ -14,10 +14,9 @@
# You should have received a copy of the GNU General Public License
# along with this program; if not, see <http://www.gnu.org/licenses/>.
from quixote import get_publisher, get_request, get_response, get_session, redirect
from quixote import get_publisher, get_request, get_response, redirect
from quixote.html import TemplateIO, htmltext
from wcs.admin import utils
from wcs.admin.categories import CardDefCategoriesDirectory
from wcs.admin.forms import (
FormDefPage,
@ -30,7 +29,6 @@ from wcs.admin.forms import (
from wcs.carddef import CardDef, get_cards_graph
from wcs.categories import CardDefCategory
from wcs.sql_criterias import Null, StrictNotEqual
from wcs.workflows import Workflow
from ..qommon import _, pgettext_lazy
@ -71,6 +69,7 @@ class CardDefPage(FormDefPage):
options_directory_class = CardDefOptionsDirectory
fields_directory_class = CardFieldsDirectory
formdef_template_name = 'wcs/backoffice/carddef.html'
delete_message = _('You are about to irrevocably delete this card model.')
delete_title = _('Deleting Card Model:')
duplicate_title = _('Duplicate Card Model')
@ -79,144 +78,28 @@ class CardDefPage(FormDefPage):
'The card model has been successfully overwritten. '
'Do note it kept its existing address and role and workflow parameters.'
)
readonly_message = _('This card model is readonly.')
management_view_label = _('List of cards')
def _q_index(self):
get_response().set_title(self.formdef.name)
r = TemplateIO(html=True)
get_response().filter['sidebar'] = self.get_sidebar()
get_response().add_javascript(['jquery.js', 'widget_list.js', 'qommon.wysiwyg.js'])
r += htmltext('<div id="appbar">')
r += htmltext('<h2>%s</h2>') % self.formdef.name
if not self.formdef.is_readonly():
r += htmltext('<span class="actions">')
r += htmltext('<a rel="popup" href="title">%s</a>') % _('change title')
r += htmltext('</span>')
r += htmltext('</div>')
r += utils.last_modification_block(obj=self.formdef)
r += get_session().display_message()
r += htmltext('<div class="bo-block">')
r += htmltext('<h3>%s</h3>') % _('Information')
r += htmltext('<ul class="biglist optionslist">')
r += self.add_option_line(
'options/category',
_('Category'),
self.formdef.category_id
and self.formdef.category
and self.formdef.category.name
or pgettext_lazy('category', 'None'),
)
r += htmltext('</ul>')
r += htmltext('</div>')
r += htmltext('<div class="splitcontent-left">')
r += htmltext('<div class="bo-block">')
r += htmltext('<h3>%s</h3>') % _('Workflow')
r += htmltext('<ul class="biglist optionslist">')
unknown_wf = self.formdef.workflow.id == Workflow.get_unknown_workflow().id
if get_publisher().get_backoffice_root().is_accessible('workflows') and not unknown_wf:
# custom option line to also include a link to the workflow itself.
r += htmltext(
'<li><a rel="popup" href="%(link)s">'
'<span class="label">%(label)s</span> '
'<span class="value offset">%(current_value)s</span>'
'</a>'
'<a class="extra-link" title="%(title)s" href="%(workflow_url)s">↗</a>'
'</li>'
% {
'link': 'workflow',
'label': _('Workflow'),
'title': _('Open workflow page'),
'workflow_url': self.formdef.workflow.get_admin_url(),
'current_value': self.formdef.workflow.name or '-',
}
)
else:
r += self.add_option_line(
'workflow', _('Workflow'), self.formdef.workflow and self.formdef.workflow.name or '-'
)
if self.formdef.workflow_id:
pristine_workflow = Workflow.get(self.formdef.workflow_id, ignore_errors=True)
if pristine_workflow and pristine_workflow.variables_formdef:
r += self.add_option_line('workflow-variables', _('Options'), '')
r += self.add_option_line(
def get_option_lines(self):
options = super().get_option_lines()
options['backoffice_submission_roles'] = self.add_option_line(
'backoffice-submission-roles',
_('Creation Role'),
self._get_roles_label('backoffice_submission_roles'),
)
if self.formdef.workflow.roles:
if not self.formdef.workflow_roles:
self.formdef.workflow_roles = {}
for wf_role_id, wf_role_label in self.formdef.workflow.roles.items():
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 = '-'
r += self.add_option_line('role/%s' % wf_role_id, wf_role_label, role_label)
r += htmltext('</ul>')
r += htmltext('</div>')
r += htmltext('</div>')
r += htmltext('<div class="splitcontent-right">')
r += htmltext('<div class="bo-block">')
r += htmltext('<h3>%s</h3>') % _('Options')
r += htmltext('<ul class="biglist optionslist">')
if (
self.formdef.default_digest_template
or self.formdef.lateral_template
or self.formdef.submission_lateral_template
):
template_status = pgettext_lazy('template', 'Custom')
else:
template_status = pgettext_lazy('template', 'None')
r += self.add_option_line('options/templates', _('Templates'), template_status, popup=False)
if self.formdef.user_support == 'optional':
user_support_status = pgettext_lazy('user_support', 'Optional')
else:
user_support_status = pgettext_lazy('user_support', 'No')
r += self.add_option_line('options/user_support', _('User support'), user_support_status)
r += htmltext('</ul>')
r += htmltext('</div>')
r += htmltext('</div>')
r += htmltext('<div class="bo-block clear">')
r += htmltext('<h3 class="clear">%s <span class="change">(<a href="fields/">%s</a>)</span></h3>') % (
_('Fields'),
_('edit'),
options['user_support'] = self.add_option_line(
'options/user_support', _('User support'), user_support_status
)
r += self.get_preview()
r += htmltext('</div>')
return options
def get_sorted_usage_in_formdefs(self):
formdefs = list(self.formdef.usage_in_formdefs())
if formdefs:
formdefs.sort(key=lambda x: x.name.lower())
r += htmltext('<div class="bo-block">')
r += htmltext('<h3>%s</h3>') % _('Forms')
r += htmltext('<p>%s ') % _('This card model is used as data source in the following forms:')
r += htmltext(', ').join(
[htmltext('<a href="%s">%s</a>') % (x.get_admin_url(), x.name) for x in formdefs]
)
r += htmltext('</p>')
r += htmltext('</div>')
return r.getvalue()
formdefs.sort(key=lambda x: x.name.lower())
return formdefs
def duplicate_submit(self, form):
response = super().duplicate_submit(form)

View File

@ -704,6 +704,12 @@ class FormDef(StorableObject):
base_url = get_publisher().get_backoffice_url()
return '%s/forms/%s/' % (base_url, self.id)
def get_backoffice_url(self):
return self.get_url(backoffice=True)
def get_preview_url(self):
return self.get_url(preview=True)
def get_field_admin_url(self, field):
return self.get_admin_url() + 'fields/%s/' % field.id

View File

@ -0,0 +1,60 @@
{% extends "wcs/backoffice/formdef.html" %}
{% load i18n %}
{% block body %}
{{ view.last_modification_block|safe }}
{{ publisher.get_request.session.display_message|safe }}
<div class="bo-block">
<h3>{% trans "Information" %}</h3>
<ul class="biglist optionslist">
{{ options.category|safe }}
</ul>
</div>
<div class="splitcontent-left">
<div class="bo-block">
<h3>{% trans "Workflow" %}</h3>
<ul class="biglist optionslist">
{{ options.workflow|safe }}
{{ options.workflow_options|safe }}
{% for workflow_role_line in options.workflow_roles_list %}{{ workflow_role_line|safe }}{% endfor %}
{{ options.backoffice_submission_roles|safe }}
</ul>
</div>
</div>
<div class="splitcontent-right">
<div class="bo-block">
<h3>{% trans "Options" %}</h3>
<ul class="biglist optionslist">
{{ options.templates|safe }}
{{ options.user_support|safe }}
</ul>
</div>
</div>
<div class="bo-block clear">
<h3 class="clear">{% trans "Fields" %}
<span class="change"><a class="pk-button" href="fields/">{% trans "edit" %}</a></span></h3>
{{ view.get_preview|safe }}
</div>
{% with usage_in_formdefs=view.get_sorted_usage_in_formdefs %}
{% if usage_in_formdefs %}
<div class="bo-block">
<h3>{% trans "Forms" %}</h3>
<p>{% trans "This card model is used as data source in the following forms:" %}
{% for usage in usage_in_formdefs %}
<a href="{{ usage.get_admin_url }}">{{ usage.name }}</a>{% if not forloop.last %}, {% endif %}
{% endfor %}
</p>
</div>
{% endif %}
{% endwith %}
{% endblock %}
{% block sidebar-content-readonly-message %}
{% trans "This card model is readonly." %}
{% endblock %}

View File

@ -0,0 +1,104 @@
{% extends "wcs/backoffice.html" %}
{% load i18n %}
{% block appbar-title %}{{ formdef.name }} {{ view.last_test_result_block|safe }}{% endblock %}
{% block appbar-actions %}
{% if not formdef.is_readonly %}
<a rel="popup" href="title">{% trans "change title" %}</a>
{% endif %}
{% endblock %}
{% block body %}
{{ view.last_modification_block|safe }}
{{ publisher.get_request.session.display_message|safe }}
<div class="bo-block">
<h3>{% trans "Information" %}</h3>
<ul class="biglist optionslist">
{{ options.description|safe }}
{{ options.keywords|safe }}
{{ options.category|safe }}
</ul>
</div>
<div class="splitcontent-left">
<div class="bo-block">
<h3>{% trans "Workflow" %}</h3>
<ul class="biglist optionslist">
{{ options.workflow|safe }}
{{ options.workflow_options|safe }}
{% for workflow_role_line in options.workflow_roles_list %}{{ workflow_role_line|safe }}{% endfor %}
{{ options.workflow_roles|safe }}
{{ options.user_roles|safe }}
{{ options.backoffice_submission_roles|safe }}
</ul>
</div>
</div>
<div class="splitcontent-right">
<div class="bo-block">
<h3>{% trans "Options" %}</h3>
<ul class="biglist optionslist">
{{ options.confirmation|safe }}
{{ options.only_allow_one|safe }}
{% if formdef.roles %}{{ options.always_advertise|safe }}{% endif %}
{{ options.management|safe }}
{{ options.tracking_code|safe }}
{% if has_captcha_option %}{{ options.captcha|safe }}{% endif %}
{% if has_appearance_keywords %}{{ options.appearance|safe }}{% endif %}
{{ options.templates|safe }}
{{ options.online_status|safe }}
</ul>
</div>
</div>
<div class="bo-block clear">
<h3 class="clear">{% trans "Fields" %}
<span class="change"><a class="pk-button" href="fields/">{% trans "edit" %}</a></span></h3>
{{ view.get_preview|safe }}
</div>
{% endblock %}
{% block sidebar-content %}
{% if formdef.is_readonly %}
<div class="infonotice">
{% block sidebar-content-readonly-message %}
{% trans "This form is readonly." %}
{% endblock %}
{{ view.snapshot_info_block|safe }}
</div>
{% else %}
<ul id="sidebar-actions">
<li><a href="delete" rel="popup">{% trans "Delete" %}</a></li>
<li><a href="duplicate" rel="popup">{% trans "Duplicate" %}</a></li>
<li><a rel="popup" href="overwrite">{% trans "Overwrite with new import" %}</a></li>
<li><a href="export">{% trans "Export" %}</a></li>
<li><a rel="popup" href="history/save">{% trans "Save snapshot" %}</a></li>
<li><a href="history/">{% trans "History" %}</a></li>
<li><a href="inspect">{% trans "Inspector" %}</a></li>
{% if tests_enabled %}
<li><a href="tests/">{% trans "Tests" %}</a></li>
{% endif %}
</ul>
<ul>
{% block sidebar-links %}
{% if formdef.is_disabled %}
<li><a href="{{ formdef.get_preview_url }}">{% trans "Preview Online" %}</a></li>
{% else %}
<li><a href="{{ formdef.get_url }}">{% trans "Display Online" %}</a></li>
{% endif %}
<li><a href="public-url" rel="popup">{% trans "Display public URL" %}</a></li>
{% if has_qrcode %}
<li><a href="qrcode" rel="popup">{% trans "Display QR Code" %}</a></li>
{% endif %}
{% if include_management_link %}
<li><a href="{{ formdef.get_backoffice_url }}">{% trans "Management view" %}</a></li>
{% endif %}
{% endblock %}
</ul>
{{ view.errors_block|safe }}
{% endif %}
{% endblock %}