workflows: add options to limit pages displayed on created formdata (#86411)
This commit is contained in:
parent
f5422ddef0
commit
48593b4e86
|
@ -1093,3 +1093,73 @@ def test_create_formdata_multiple(pub):
|
|||
resp = app.get(formdata2.get_url())
|
||||
resp = resp.form.submit('button-action-1')
|
||||
assert target_formdef.data_class().count() == 3
|
||||
|
||||
|
||||
@pytest.mark.parametrize('mode', ['single', 'partial'])
|
||||
def test_create_formdata_edit_single_or_partial_pages(pub, mode):
|
||||
FormDef.wipe()
|
||||
pub.tracking_code_class.wipe()
|
||||
|
||||
target_formdef = FormDef()
|
||||
target_formdef.name = 'target-form'
|
||||
target_formdef.fields = [
|
||||
fields.PageField(id='1', label='page1'),
|
||||
fields.StringField(id='2', label='string', varname='foo_string'),
|
||||
fields.PageField(id='3', label='page2', varname='page2'),
|
||||
fields.StringField(id='4', label='string2', varname='bar_string'),
|
||||
fields.PageField(id='4', label='page3'),
|
||||
]
|
||||
target_formdef.store()
|
||||
|
||||
wf = Workflow(name='create-formdata')
|
||||
wf.possible_status = Workflow.get_default_workflow().possible_status[:]
|
||||
create = wf.possible_status[1].add_action('create_formdata', id='_create', prepend=True)
|
||||
create.label = 'create a new linked form'
|
||||
create.varname = 'resubmitted'
|
||||
create.draft = True
|
||||
create.formdef_slug = target_formdef.url_name
|
||||
create.attach_to_history = True
|
||||
create.draft_edit_operation_mode = mode
|
||||
create.page_identifier = 'page2'
|
||||
create.mappings = [
|
||||
Mapping(field_id='2', expression='blah1'),
|
||||
Mapping(field_id='4', expression='blah2'),
|
||||
]
|
||||
wf.store()
|
||||
|
||||
source_formdef = FormDef()
|
||||
source_formdef.name = 'source-form'
|
||||
source_formdef.fields = []
|
||||
source_formdef.workflow_id = wf.id
|
||||
source_formdef.enable_tracking_codes = True
|
||||
source_formdef.store()
|
||||
|
||||
source_formdef.data_class().wipe()
|
||||
target_formdef.data_class().wipe()
|
||||
|
||||
create_user(pub)
|
||||
app = login(get_app(pub), username='foo', password='foo')
|
||||
resp = app.get('/source-form/')
|
||||
resp = resp.forms[0].submit('submit') # -> validation
|
||||
resp = resp.forms[0].submit('submit').follow() # -> submit
|
||||
assert 'The form has been recorded' in resp.text
|
||||
|
||||
created_url = resp.pyquery('.wf-links a')[0].attrib['href']
|
||||
resp = app.get(created_url).follow()
|
||||
|
||||
if mode == 'single':
|
||||
assert resp.pyquery('.wcs-step').length == 2
|
||||
else:
|
||||
assert resp.pyquery('.wcs-step').length == 3
|
||||
assert resp.pyquery('.wcs-step.current .label').text() == 'page2 (current step)'
|
||||
assert resp.forms[1]['f4'].value == 'blah2'
|
||||
|
||||
if mode == 'partial':
|
||||
resp = resp.forms[1].submit('submit') # -> page 3
|
||||
assert resp.pyquery('.wcs-step.current .label').text() == 'page3 (current step)'
|
||||
|
||||
resp = resp.forms[1].submit('submit') # -> validation
|
||||
resp = resp.forms[1].submit('submit') # -> submit
|
||||
assert target_formdef.data_class().count() == 1
|
||||
formdata = target_formdef.data_class().select()[0]
|
||||
assert formdata.data == {'2': 'blah1', '4': 'blah2'}
|
||||
|
|
|
@ -946,9 +946,13 @@ class FormPage(Directory, TempfileDirectoryMixin, FormTemplateMixin):
|
|||
# create a fake FormData with current submission data
|
||||
formdata.user = get_request().user
|
||||
formdata._formdef = self.formdef
|
||||
if draft_formdata and draft_formdata.submission_context:
|
||||
# restore submission context, this is required to get access to form_parent_* variables
|
||||
formdata.submission_context = draft_formdata.submission_context
|
||||
if draft_formdata:
|
||||
if draft_formdata.submission_context:
|
||||
# restore submission context, this is required to get access to form_parent_* variables
|
||||
formdata.submission_context = draft_formdata.submission_context
|
||||
if draft_formdata.workflow_data:
|
||||
# restore workflow_data, this is used for partial edit
|
||||
formdata.workflow_data = draft_formdata.workflow_data
|
||||
formdata.data = session_data
|
||||
formdata.prefilling_data = formdata.data.get('prefilling_data', {})
|
||||
computed_values = get_session().get_by_magictoken('%s-computed' % magictoken) or {}
|
||||
|
@ -1074,7 +1078,8 @@ class FormPage(Directory, TempfileDirectoryMixin, FormTemplateMixin):
|
|||
def pages(self):
|
||||
if self._pages:
|
||||
return self._pages
|
||||
current_data = self.get_transient_formdata().data
|
||||
transient_formdata = self.get_transient_formdata()
|
||||
current_data = transient_formdata.data
|
||||
|
||||
pages = [x for x in self.formdef.fields if x.key == 'page']
|
||||
has_page_fields = bool(pages)
|
||||
|
@ -1086,12 +1091,27 @@ class FormPage(Directory, TempfileDirectoryMixin, FormTemplateMixin):
|
|||
# submitted data) (#27247).
|
||||
hidden_pages = [x for x in pages if not x.is_visible(current_data, self.formdef)]
|
||||
|
||||
if self.edit_mode and self.edit_action and self.edit_action.operation_mode in ('single', 'partial'):
|
||||
if self.edit_mode and self.edit_action:
|
||||
operation_mode = self.edit_action.operation_mode
|
||||
page_identifier = self.edit_action.page_identifier
|
||||
elif (
|
||||
not self.edit_mode
|
||||
and transient_formdata.workflow_data
|
||||
and '_create_formdata_draft_edit' in transient_formdata.workflow_data
|
||||
):
|
||||
operation_mode = transient_formdata.workflow_data['_create_formdata_draft_edit']['operation_mode']
|
||||
page_identifier = transient_formdata.workflow_data['_create_formdata_draft_edit'][
|
||||
'page_identifier'
|
||||
]
|
||||
else:
|
||||
operation_mode = 'full'
|
||||
|
||||
if operation_mode in ('single', 'partial'):
|
||||
edit_pages = []
|
||||
for page in pages:
|
||||
if self.edit_action.page_identifier == page.varname or edit_pages:
|
||||
if page_identifier == page.varname or edit_pages:
|
||||
edit_pages.append(page)
|
||||
if self.edit_action.operation_mode == 'single':
|
||||
if operation_mode == 'single':
|
||||
break
|
||||
edit_pages = [x for x in edit_pages if x not in hidden_pages]
|
||||
if not edit_pages:
|
||||
|
|
|
@ -387,6 +387,8 @@ class CreateFormdataWorkflowStatusItem(WorkflowStatusItem):
|
|||
map_fields_by_varname = False
|
||||
attach_to_history = False
|
||||
cached_field_labels = None
|
||||
draft_edit_operation_mode = 'full' # or 'single' or 'partial'
|
||||
page_identifier = None
|
||||
|
||||
def migrate(self):
|
||||
changed = super().migrate()
|
||||
|
@ -412,6 +414,13 @@ class CreateFormdataWorkflowStatusItem(WorkflowStatusItem):
|
|||
parameters = super().get_inspect_parameters()
|
||||
if self.user_association_mode != 'custom' and 'user_association_template' in parameters:
|
||||
parameters.remove('user_association_template')
|
||||
if not self.draft:
|
||||
if 'draft_edit_operation_mode' in parameters:
|
||||
parameters.remove('draft_edit_operation_mode')
|
||||
if 'page_identifier' in parameters:
|
||||
parameters.remove('page_identifier')
|
||||
if self.draft_edit_operation_mode not in ('single', 'partial') and 'page_identifier' in parameters:
|
||||
parameters.remove('page_identifier')
|
||||
return parameters
|
||||
|
||||
def add_parameters_widgets(self, form, parameters, prefix='', formdef=None, **kwargs):
|
||||
|
@ -443,7 +452,46 @@ class CreateFormdataWorkflowStatusItem(WorkflowStatusItem):
|
|||
**{'data-autocomplete': 'true'},
|
||||
)
|
||||
if 'draft' in parameters:
|
||||
form.add(CheckboxWidget, '%sdraft' % prefix, title=_('Create new draft'), value=self.draft)
|
||||
form.add(
|
||||
CheckboxWidget,
|
||||
'%sdraft' % prefix,
|
||||
title=_('Create new draft'),
|
||||
value=self.draft,
|
||||
attrs={'data-dynamic-display-parent': 'true'},
|
||||
tab=('draft', _('Draft')),
|
||||
)
|
||||
if 'draft_edit_operation_mode' in parameters:
|
||||
form.add(
|
||||
RadiobuttonsWidget,
|
||||
'%sdraft_edit_operation_mode' % prefix,
|
||||
title=_('Operation mode when a draft is created'),
|
||||
options=[
|
||||
('full', _('All pages'), 'full'),
|
||||
('single', _('Single page'), 'single'),
|
||||
('partial', _('From specific page'), 'partial'),
|
||||
],
|
||||
tab=('draft', _('Draft')),
|
||||
value=self.draft_edit_operation_mode,
|
||||
attrs={
|
||||
'data-dynamic-display-parent': 'true',
|
||||
'data-dynamic-display-child-of': f'{prefix}draft',
|
||||
'data-dynamic-display-checked': 'true',
|
||||
},
|
||||
extra_css_class='widget-inline-radio',
|
||||
default_value=self.__class__.draft_edit_operation_mode,
|
||||
)
|
||||
if 'page_identifier' in parameters:
|
||||
form.add(
|
||||
StringWidget,
|
||||
'%spage_identifier' % prefix,
|
||||
title=_('Page Identifier'),
|
||||
value=self.page_identifier,
|
||||
tab=('draft', _('Draft')),
|
||||
attrs={
|
||||
'data-dynamic-display-child-of': '%sdraft_edit_operation_mode' % prefix,
|
||||
'data-dynamic-display-value-in': 'single|partial',
|
||||
},
|
||||
)
|
||||
if 'backoffice_submission' in parameters:
|
||||
form.add(
|
||||
CheckboxWidget,
|
||||
|
@ -566,6 +614,12 @@ class CreateFormdataWorkflowStatusItem(WorkflowStatusItem):
|
|||
mapped_subfield_id = f'{field.id}${subfield.id}'
|
||||
if mapped_subfield_id in mapped_field_ids:
|
||||
self.cached_field_labels[mapped_subfield_id] = f'{field.label} - {subfield.label}'
|
||||
if not self.draft:
|
||||
# cleanup
|
||||
if 'draft_edit_operation_mode' in self.get_parameters():
|
||||
delattr(self, 'draft_edit_operation_mode')
|
||||
if 'page_identifier' in self.get_parameters():
|
||||
delattr(self, 'page_identifier')
|
||||
|
||||
def get_mappings_parameter_view_value(self):
|
||||
to_id_fields = {str(field.id): field for field in self.formdef.get_widget_fields()}
|
||||
|
@ -595,11 +649,13 @@ class CreateFormdataWorkflowStatusItem(WorkflowStatusItem):
|
|||
def get_parameters(self):
|
||||
return (
|
||||
'action_label',
|
||||
'draft',
|
||||
'formdef_slug',
|
||||
'map_fields_by_varname',
|
||||
'mappings',
|
||||
'backoffice_submission',
|
||||
'draft',
|
||||
'draft_edit_operation_mode',
|
||||
'page_identifier',
|
||||
'user_association_mode',
|
||||
'user_association_template',
|
||||
'keep_submission_context',
|
||||
|
@ -737,6 +793,13 @@ class CreateFormdataWorkflowStatusItem(WorkflowStatusItem):
|
|||
if self.draft:
|
||||
new_formdata.status = 'draft'
|
||||
new_formdata.receipt_time = localtime()
|
||||
if self.draft_edit_operation_mode != 'full':
|
||||
new_formdata.workflow_data = {
|
||||
'_create_formdata_draft_edit': {
|
||||
'operation_mode': self.draft_edit_operation_mode,
|
||||
'page_identifier': self.page_identifier,
|
||||
},
|
||||
}
|
||||
new_formdata.store()
|
||||
if formdef.enable_tracking_codes:
|
||||
code.formdata = new_formdata # this will .store() the code
|
||||
|
|
Loading…
Reference in New Issue