workflows: add new edit modes (single, partial) (#41470)
This commit is contained in:
parent
6523d409bd
commit
0fdd529074
|
@ -10281,3 +10281,80 @@ def test_form_edit_with_category(pub):
|
|||
assert 'wfedit' in resp.location
|
||||
resp = resp.follow()
|
||||
assert 'f1' in resp.form.fields
|
||||
|
||||
|
||||
def test_form_edit_single_page(pub):
|
||||
user = create_user(pub)
|
||||
|
||||
workflow = Workflow(name='test')
|
||||
st1 = workflow.add_status('Status1', 'st1')
|
||||
editable = st1.add_action('editable', id='_editable')
|
||||
editable.by = ['_submitter', '_receiver']
|
||||
workflow.store()
|
||||
|
||||
formdef = create_formdef()
|
||||
formdef.data_class().wipe()
|
||||
formdef.fields = [
|
||||
fields.PageField(id='1', label='1st page', type='page'),
|
||||
fields.StringField(id='2', label='field1', type='string'),
|
||||
fields.PageField(id='3', label='2nd page', type='page'),
|
||||
fields.StringField(id='4', label='field2', type='string'),
|
||||
fields.PageField(id='5', label='3rd page', type='page'),
|
||||
fields.StringField(id='6', label='field3', type='string'),
|
||||
]
|
||||
formdef.workflow_id = workflow.id
|
||||
formdef.store()
|
||||
|
||||
formdata = formdef.data_class()()
|
||||
formdata.user_id = user.id
|
||||
formdata.data = {'2': 'a', '4': 'b', '6': 'c'}
|
||||
formdata.just_created()
|
||||
formdata.store()
|
||||
|
||||
app = get_app(pub)
|
||||
login(app, username='foo', password='foo')
|
||||
|
||||
resp = app.get(formdata.get_url())
|
||||
resp = resp.form.submit('button_editable').follow()
|
||||
assert [x.text for x in resp.pyquery('#steps .label')] == ['1st page', '2nd page', '3rd page']
|
||||
|
||||
editable.operation_mode = 'single'
|
||||
editable.page_identifier = 'plop'
|
||||
workflow.store()
|
||||
|
||||
# unknown page identifier, a 404 is raised
|
||||
resp = app.get(formdata.get_url())
|
||||
resp = resp.form.submit('button_editable').follow(status=404)
|
||||
|
||||
# add identifier to second page, and edit it
|
||||
formdef.fields[2].varname = 'plop'
|
||||
formdef.store()
|
||||
|
||||
resp = app.get(formdata.get_url())
|
||||
resp = resp.form.submit('button_editable').follow()
|
||||
assert [x.text for x in resp.pyquery('#steps .label')] == ['2nd page']
|
||||
resp.form['f4'] = 'changed'
|
||||
assert [x.text for x in resp.pyquery('.buttons button')] == ['Save Changes', 'Cancel']
|
||||
resp = resp.form.submit('submit')
|
||||
formdata.refresh_from_storage()
|
||||
assert formdata.data == {'2': 'a', '4': 'changed', '6': 'c'}
|
||||
|
||||
# change action to edit all pages starting at page 2
|
||||
editable.operation_mode = 'partial'
|
||||
workflow.store()
|
||||
|
||||
resp = app.get(formdata.get_url())
|
||||
resp = resp.form.submit('button_editable').follow()
|
||||
assert [x.text for x in resp.pyquery('#steps .label')] == ['2nd page', '3rd page']
|
||||
resp.form['f4'] = 'other change'
|
||||
assert [x.text for x in resp.pyquery('.buttons button')] == ['Next', 'Cancel']
|
||||
resp = resp.form.submit('submit')
|
||||
assert [x.text for x in resp.pyquery('.buttons button')] == ['Save Changes', 'Previous', 'Cancel']
|
||||
resp = resp.form.submit('previous')
|
||||
assert [x.text for x in resp.pyquery('.buttons button')] == ['Next', 'Cancel']
|
||||
resp = resp.form.submit('submit')
|
||||
resp.form['f6'] = 'last change'
|
||||
assert [x.text for x in resp.pyquery('.buttons button')] == ['Save Changes', 'Previous', 'Cancel']
|
||||
resp = resp.form.submit('submit')
|
||||
formdata.refresh_from_storage()
|
||||
assert formdata.data == {'2': 'a', '4': 'other change', '6': 'last change'}
|
||||
|
|
|
@ -1004,8 +1004,8 @@ class FormStatusPage(Directory, FormTemplateMixin):
|
|||
f = self.form_page_class(self.formdef.url_name)
|
||||
f.edit_mode = True
|
||||
f.edited_data = self.filled
|
||||
f.edit_action_id = action_id
|
||||
f.action_url = 'wfedit-%s' % action_id
|
||||
f.edit_action = item
|
||||
f.action_url = 'wfedit-%s' % item.id
|
||||
if get_request().is_in_backoffice():
|
||||
get_session().mark_visited_object(self.filled)
|
||||
get_response().breadcrumb = get_response().breadcrumb[:-1]
|
||||
|
|
|
@ -297,6 +297,7 @@ class FormPage(FormdefDirectoryBase, FormTemplateMixin):
|
|||
self.code = TrackingCodesDirectory(self.formdef)
|
||||
self.action_url = '.'
|
||||
self.edit_mode = False
|
||||
self.edit_action = None
|
||||
self.on_validation_page = False
|
||||
self.current_page = None
|
||||
self.user = get_request().user
|
||||
|
@ -960,6 +961,16 @@ class FormPage(FormdefDirectoryBase, FormTemplateMixin):
|
|||
field_page = field
|
||||
if field.is_visible(current_data, self.formdef):
|
||||
pages.append(field)
|
||||
if self.edit_mode and self.edit_action and self.edit_action.operation_mode in ('single', 'partial'):
|
||||
edit_pages = []
|
||||
for page in pages:
|
||||
if self.edit_action.page_identifier == page.varname or edit_pages:
|
||||
edit_pages.append(page)
|
||||
if self.edit_action.operation_mode == 'single':
|
||||
break
|
||||
if not edit_pages:
|
||||
raise errors.TraversalError()
|
||||
pages = edit_pages
|
||||
if not field_page: # form without page fields
|
||||
pages = [None]
|
||||
self._pages = pages
|
||||
|
@ -1715,7 +1726,7 @@ class FormPage(FormdefDirectoryBase, FormTemplateMixin):
|
|||
wf_status = self.edited_data.get_status()
|
||||
url = None
|
||||
for item in wf_status.items:
|
||||
if item.id == self.edit_action_id:
|
||||
if item.id == self.edit_action.id:
|
||||
user = get_request().user
|
||||
user_id = None
|
||||
if user:
|
||||
|
|
|
@ -17,7 +17,13 @@
|
|||
from quixote import get_publisher, get_request
|
||||
|
||||
from wcs.qommon import _
|
||||
from wcs.qommon.form import SingleSelectWidget, StringWidget, WidgetList, WysiwygTextWidget
|
||||
from wcs.qommon.form import (
|
||||
RadiobuttonsWidget,
|
||||
SingleSelectWidget,
|
||||
StringWidget,
|
||||
WidgetList,
|
||||
WysiwygTextWidget,
|
||||
)
|
||||
from wcs.workflows import WorkflowStatusItem, register_item_class
|
||||
|
||||
|
||||
|
@ -33,6 +39,8 @@ class EditableWorkflowStatusItem(WorkflowStatusItem):
|
|||
status = None
|
||||
label = None
|
||||
backoffice_info_text = None
|
||||
operation_mode = 'full' # or 'single' or 'partial'
|
||||
page_identifier = None
|
||||
|
||||
def get_line_details(self):
|
||||
if self.by:
|
||||
|
@ -103,9 +111,44 @@ class EditableWorkflowStatusItem(WorkflowStatusItem):
|
|||
title=_('Information Text for Backoffice'),
|
||||
value=self.backoffice_info_text,
|
||||
)
|
||||
if 'operation_mode' in parameters:
|
||||
form.add(
|
||||
RadiobuttonsWidget,
|
||||
'%soperation_mode' % prefix,
|
||||
title=_('Operation Mode'),
|
||||
options=[
|
||||
('full', _('All pages'), 'full'),
|
||||
('single', _('Single page'), 'single'),
|
||||
('partial', _('From specific page'), 'partial'),
|
||||
],
|
||||
advanced=True,
|
||||
value=self.operation_mode,
|
||||
attrs={'data-dynamic-display-parent': 'true'},
|
||||
extra_css_class='widget-inline-radio',
|
||||
)
|
||||
if 'page_identifier' in parameters:
|
||||
form.add(
|
||||
StringWidget,
|
||||
'%spage_identifier' % prefix,
|
||||
title=_('Page Identifier'),
|
||||
value=self.page_identifier,
|
||||
advanced=True,
|
||||
attrs={
|
||||
'data-dynamic-display-child-of': '%soperation_mode' % prefix,
|
||||
'data-dynamic-display-value-in': 'single|partial',
|
||||
},
|
||||
)
|
||||
|
||||
def get_parameters(self):
|
||||
return ('by', 'status', 'label', 'backoffice_info_text', 'condition')
|
||||
return (
|
||||
'by',
|
||||
'status',
|
||||
'label',
|
||||
'backoffice_info_text',
|
||||
'condition',
|
||||
'operation_mode',
|
||||
'page_identifier',
|
||||
)
|
||||
|
||||
|
||||
register_item_class(EditableWorkflowStatusItem)
|
||||
|
|
Loading…
Reference in New Issue