workflows: handle "add block" buttons in display form action (#47898)

This commit is contained in:
Frédéric Péters 2021-03-30 09:15:42 +02:00
parent b9cbbe9893
commit e47209ac47
4 changed files with 80 additions and 6 deletions

View File

@ -4239,6 +4239,64 @@ def test_backoffice_workflow_form_with_live_data_source(pub):
]
def test_backoffice_workflow_display_form_with_block_add(pub):
user = create_user(pub)
create_environment(pub)
block = BlockDef()
block.name = 'foobar'
block.fields = [
fields.StringField(id='123', required=True, label='Test', type='string'),
]
block.store()
wf = Workflow.get_default_workflow()
wf.id = '2'
wf.store()
wf = Workflow.get(wf.id)
status = wf.get_status('new')
status.items = []
display_form = FormWorkflowStatusItem()
display_form.id = '_display_form'
display_form.by = [user.roles[0]]
display_form.varname = 'blah'
display_form.formdef = WorkflowFormFieldsFormDef(item=display_form)
display_form.formdef.fields = [
fields.StringField(id='1', label='Test', varname='str', type='string', required=True),
fields.BlockField(id='2', label='Blocks', type='block:foobar', varname='data', max_items=3),
]
status.items.append(display_form)
display_form.parent = status
jump = JumpOnSubmitWorkflowStatusItem()
jump.id = '_jump'
jump.status = 'accepted'
status.items.append(jump)
jump.parent = status
wf.store()
formdef = FormDef.get_by_urlname('form-title')
formdef.workflow_id = wf.id
formdef.store()
for formdata in formdef.data_class().select():
if formdata.status == 'wf-new':
break
app = login(get_app(pub))
resp = app.get(formdata.get_url(backoffice=True))
resp.form['fblah_1'] = 'blah'
resp.form['fblah_2$element0$f123'] = 'foo'
resp = resp.form.submit('fblah_2$add_element')
resp.form['fblah_2$element1$f123'] = 'bar'
resp = resp.form.submit('submit')
assert formdef.data_class().get(formdata.id).workflow_data == {
'blah_var_data': 'foobar, foobar',
'blah_var_data_raw': {'data': [{'123': 'foo'}, {'123': 'bar'}], 'schema': {'123': 'string'}},
'blah_var_str': 'blah',
}
def test_backoffice_criticality_in_formdef_listing(pub):
if not pub.is_using_postgresql():
pytest.skip('this requires SQL')

View File

@ -28,7 +28,7 @@ from wcs import data_sources
from wcs.api_utils import get_user_from_api_query_string, is_url_signed, sign_url_auto_orig
from wcs.blocks import BlockSubWidget, BlockWidget
from wcs.qommon.admin.texts import TextsDirectory
from wcs.workflows import EditableWorkflowStatusItem
from wcs.workflows import EditableWorkflowStatusItem, RedisplayFormException
from ..qommon import _, errors, get_logger, misc, template
@ -544,10 +544,15 @@ class FormStatusPage(Directory, FormTemplateMixin):
user = self.check_receiver()
form = self.get_workflow_form(user)
response = self.check_submitted_form(form)
if response:
get_session().unmark_visited_object(self.filled)
return response
try:
response = self.check_submitted_form(form)
except RedisplayFormException:
# don't display errors after "add block" button has been clicked.
form.clear_errors()
else:
if response:
get_session().unmark_visited_object(self.filled)
return response
get_logger().info('form %s - id: %s - view status' % (self.formdef.name, self.filled.id))
get_response().add_javascript(['jquery.js', 'qommon.forms.js'])

View File

@ -24,7 +24,7 @@ from wcs.formdata import get_dict_with_varnames
from wcs.formdef import FormDef, lax_int
from wcs.forms.common import FileDirectory
from wcs.forms.root import FormPage
from wcs.workflows import WorkflowStatusItem, register_item_class
from wcs.workflows import RedisplayFormException, WorkflowStatusItem, register_item_class
from ..qommon import N_, _
from ..qommon.form import SingleSelectWidget, VarnameWidget, WidgetList
@ -243,6 +243,13 @@ class FormWorkflowStatusItem(WorkflowStatusItem):
def submit_form(self, form, formdata, user, evo):
if not self.formdef:
return
if form.get_submit() is True:
# non-submit button, maybe a "add block" button, look for them.
for widget in form.widgets:
if isinstance(widget, WidgetList): # BlockWidget
add_element_widget = widget.get_widget('add_element')
if add_element_widget and add_element_widget.parse():
raise RedisplayFormException()
if form.get_submit() == 'submit' and not form.has_errors():
self.evaluate_live_form(form, formdata, user)
formdata.store()

View File

@ -114,6 +114,10 @@ class AbortActionException(Exception):
self.url = url
class RedisplayFormException(Exception):
pass
class AttachmentSubstitutionProxy:
def __init__(self, formdata, attachment_evolution_part):
self.formdata = formdata