workflows: be explicit about jump modes (#83418)
This commit is contained in:
parent
db8e6bc0a5
commit
5365983716
|
@ -164,6 +164,7 @@ def test_deprecations(pub):
|
|||
|
||||
timeout_jump = st0.add_action('jump')
|
||||
timeout_jump.timeout = '213'
|
||||
timeout_jump.mode = 'timeout'
|
||||
timeout_jump.condition = {'type': 'python', 'value': 'True'}
|
||||
|
||||
for klass in (
|
||||
|
|
|
@ -1538,6 +1538,7 @@ def test_workflows_edit_jump_previous(pub):
|
|||
|
||||
jump = st1.add_action('jump', id='_jump')
|
||||
jump.timeout = 86400
|
||||
jump.mode = 'timeout'
|
||||
|
||||
ac1 = workflow.add_global_action('Action', 'ac1')
|
||||
|
||||
|
@ -1584,6 +1585,7 @@ def test_workflows_edit_jump_timeout(pub):
|
|||
jump = st1.add_action('jump', id='_jump')
|
||||
jump.status = '1'
|
||||
jump.timeout = 86400
|
||||
jump.mode = 'timeout'
|
||||
|
||||
workflow.store()
|
||||
|
||||
|
@ -1639,6 +1641,7 @@ def test_workflows_jump_target_links(pub):
|
|||
|
||||
jump = st1.add_action('jump', id='_jump')
|
||||
jump.timeout = 86400
|
||||
jump.mode = 'timeout'
|
||||
jump.status = st2.id
|
||||
|
||||
workflow.store()
|
||||
|
@ -3920,6 +3923,7 @@ def test_workflows_inspect_view(pub):
|
|||
|
||||
jump = baz_status.add_action('jump', id='_jump')
|
||||
jump.timeout = 86400
|
||||
jump.mode = 'timeout'
|
||||
jump.status = foo_status.id
|
||||
jump.condition = {'type': 'django', 'value': '1 == 1'}
|
||||
|
||||
|
|
|
@ -449,6 +449,7 @@ def test_formdef_schema(pub, access):
|
|||
jump = st1.add_action('jump')
|
||||
jump.status = 'st2'
|
||||
jump.timeout = 100
|
||||
jump.mode = 'timeout'
|
||||
st2 = workflow.add_status('Status2', 'st2')
|
||||
jump = st2.add_action('jump')
|
||||
jump.status = 'st3'
|
||||
|
|
|
@ -59,6 +59,7 @@ def formdef(pub):
|
|||
jump = new_status.add_action('jump', id='_jump')
|
||||
jump.status = '2'
|
||||
jump.timeout = 86400
|
||||
jump.mode = 'timeout'
|
||||
jump = new_status.add_action('jump', id='_jump')
|
||||
jump.status = '3'
|
||||
jump = middle_status1.add_action('jump', id='_jump')
|
||||
|
|
|
@ -46,6 +46,7 @@ def test_workflow_trigger(pub, local_user):
|
|||
st1 = workflow.add_status('Status1', 'st1')
|
||||
jump = st1.add_action('jump')
|
||||
jump.trigger = 'XXX'
|
||||
jump.mode = 'trigger'
|
||||
jump.status = 'st2'
|
||||
workflow.add_status('Status2', 'st2')
|
||||
workflow.store()
|
||||
|
@ -122,6 +123,7 @@ def test_workflow_trigger_with_data(pub, local_user):
|
|||
st1 = workflow.add_status('Status1', 'st1')
|
||||
jump = st1.add_action('jump')
|
||||
jump.trigger = 'xx-yy'
|
||||
jump.mode = 'trigger'
|
||||
jump.status = 'st2'
|
||||
workflow.add_status('Status2', 'st2')
|
||||
workflow.store()
|
||||
|
@ -224,6 +226,7 @@ def test_workflow_trigger_with_file_data(pub, local_user):
|
|||
st1 = workflow.add_status('Status1', 'st1')
|
||||
jump = st1.add_action('jump')
|
||||
jump.trigger = 'XXX'
|
||||
jump.mode = 'trigger'
|
||||
jump.status = 'st2'
|
||||
|
||||
st2 = workflow.add_status('Status2', 'st2')
|
||||
|
@ -268,6 +271,7 @@ def test_workflow_trigger_with_condition(pub, local_user):
|
|||
st1 = workflow.add_status('Status1', 'st1')
|
||||
jump = st1.add_action('jump')
|
||||
jump.trigger = 'XXX'
|
||||
jump.mode = 'trigger'
|
||||
jump.condition = {'type': 'django', 'value': 'form_var_foo == "bar"'}
|
||||
jump.status = 'st2'
|
||||
workflow.add_status('Status2', 'st2')
|
||||
|
@ -307,9 +311,11 @@ def test_workflow_trigger_jump_once(pub, local_user):
|
|||
workflow.add_status('Status3', 'st3')
|
||||
jump = st1.add_action('jump')
|
||||
jump.trigger = 'XXX'
|
||||
jump.mode = 'trigger'
|
||||
jump.status = 'st2'
|
||||
jump = st2.add_action('jump')
|
||||
jump.trigger = 'XXX'
|
||||
jump.mode = 'trigger'
|
||||
jump.status = 'st3'
|
||||
workflow.store()
|
||||
|
||||
|
@ -347,6 +353,7 @@ def test_workflow_trigger_api_access(pub, local_user):
|
|||
st1 = workflow.add_status('Status1', 'st1')
|
||||
jump = st1.add_action('jump')
|
||||
jump.trigger = 'XXX'
|
||||
jump.mode = 'trigger'
|
||||
jump.status = 'st2'
|
||||
workflow.add_status('Status2', 'st2')
|
||||
workflow.store()
|
||||
|
@ -400,6 +407,7 @@ def test_workflow_trigger_http_auth_access(pub, local_user):
|
|||
st1 = workflow.add_status('Status1', 'st1')
|
||||
jump = st1.add_action('jump')
|
||||
jump.trigger = 'XXX'
|
||||
jump.mode = 'trigger'
|
||||
jump.status = 'st2'
|
||||
workflow.add_status('Status2', 'st2')
|
||||
workflow.store()
|
||||
|
|
|
@ -271,6 +271,7 @@ def test_backoffice_forms(pub):
|
|||
st1 = workflow.add_status('Status1')
|
||||
jump = st1.add_action('jump', id='_jump')
|
||||
jump.timeout = 86400
|
||||
jump.mode = 'timeout'
|
||||
jump.status = 'finished'
|
||||
workflow.store()
|
||||
|
||||
|
@ -384,6 +385,7 @@ def test_backoffice_listing(pub):
|
|||
st1.id = 'plop'
|
||||
jump = st1.add_action('jump', id='_jump')
|
||||
jump.timeout = 86400
|
||||
jump.mode = 'timeout'
|
||||
jump.status = 'finished'
|
||||
workflow.store()
|
||||
|
||||
|
|
|
@ -38,6 +38,7 @@ def test_workflow_inspect_page(pub):
|
|||
st1 = workflow.add_status('Status1')
|
||||
jump = st1.add_action('jump', id='_jump')
|
||||
jump.timeout = '=86400'
|
||||
jump.mode = 'timeout'
|
||||
jump.status = 'finished'
|
||||
workflow.store()
|
||||
|
||||
|
|
|
@ -2863,10 +2863,12 @@ def test_form_workflow_trigger(pub):
|
|||
st1 = workflow.add_status('Status1', 'st1')
|
||||
jump = st1.add_action('jump')
|
||||
jump.trigger = 'XXX'
|
||||
jump.mode = 'trigger'
|
||||
jump.status = 'st2'
|
||||
|
||||
jump2 = st1.add_action('jump')
|
||||
jump2.trigger = 'YYY'
|
||||
jump2.mode = 'trigger'
|
||||
jump2.status = 'st3'
|
||||
jump2.set_marker_on_status = True
|
||||
|
||||
|
@ -2935,6 +2937,7 @@ def test_form_worklow_multiple_identical_status(pub):
|
|||
st1.extra_css_class = 'CSS-STATUS1'
|
||||
jump = st1.add_action('jump')
|
||||
jump.trigger = 'XXX'
|
||||
jump.mode = 'trigger'
|
||||
jump.status = 'st1'
|
||||
workflow.store()
|
||||
|
||||
|
@ -3341,6 +3344,7 @@ def test_form_worklow_multiple_identical_status_with_journal_error(pub):
|
|||
st1 = workflow.add_status('Status1', 'st1')
|
||||
jump = st1.add_action('jump')
|
||||
jump.trigger = 'XXX'
|
||||
jump.mode = 'trigger'
|
||||
jump.status = 'st1'
|
||||
workflow.store()
|
||||
|
||||
|
|
|
@ -159,6 +159,7 @@ def test_trigger_jumps(pub):
|
|||
st1 = workflow.add_status('Status1', 'st1')
|
||||
jump = st1.add_action('jump')
|
||||
jump.trigger = 'goto2'
|
||||
jump.mode = 'trigger'
|
||||
jump.status = 'st2'
|
||||
st2 = workflow.add_status('Status2', 'st2')
|
||||
workflow.store()
|
||||
|
|
|
@ -2167,6 +2167,7 @@ def test_view_performances(pub):
|
|||
jump = status.add_action('jump', id='_jump%s' % j)
|
||||
jump.by = []
|
||||
jump.timeout = 5
|
||||
jump.mode = 'timeout'
|
||||
jump.status = 'st%s' % (j + 1)
|
||||
workflow.store()
|
||||
workflows.append(workflow)
|
||||
|
|
|
@ -478,6 +478,7 @@ def test_workflow_tests_automatic_jump_timeout(pub):
|
|||
jump = new_status.add_action('jump')
|
||||
jump.status = stalled_status.id
|
||||
jump.timeout = 120 * 60 # 2 hours
|
||||
jump.mode = 'timeout'
|
||||
jump.condition = {'type': 'django', 'value': 'form_receipt_datetime|age_in_days >= 1'}
|
||||
|
||||
sendmail = new_status.add_action('sendmail')
|
||||
|
@ -1267,6 +1268,7 @@ def test_workflow_tests_create_from_formdata(pub, http_requests, freezer):
|
|||
jump = status_with_timeout_jump.add_action('jump')
|
||||
jump.status = status_with_button.id
|
||||
jump.timeout = '{{ 1 }} day'
|
||||
jump.mode = 'timeout'
|
||||
|
||||
choice = status_with_button.add_action('choice')
|
||||
choice.label = 'Accept'
|
||||
|
|
|
@ -94,6 +94,7 @@ def test_get_json_export_dict(pub):
|
|||
jump = st1.add_action('jump', id='_jump')
|
||||
jump.by = ['_submitter', '_receiver']
|
||||
jump.timeout = 0.1
|
||||
jump.mode = 'timeout'
|
||||
jump.status = 'st2'
|
||||
|
||||
workflow.roles['_other'] = 'Other Function'
|
||||
|
@ -122,6 +123,7 @@ def test_action_repr(pub):
|
|||
jump = st1.add_action('jump', id='_jump')
|
||||
jump.by = ['_submitter', '_receiver']
|
||||
jump.timeout = 0.1
|
||||
jump.mode = 'timeout'
|
||||
jump.status = 'st2'
|
||||
|
||||
action = workflow.add_global_action('Timeout')
|
||||
|
|
|
@ -46,6 +46,28 @@ def rewind(formdata, seconds):
|
|||
formdata.evolution[-1].time = formdata.evolution[-1].time - datetime.timedelta(seconds=seconds)
|
||||
|
||||
|
||||
def test_jump_migrate_mode(pub):
|
||||
item = JumpWorkflowStatusItem()
|
||||
item.migrate()
|
||||
assert item.mode == 'immediate'
|
||||
|
||||
item = JumpWorkflowStatusItem()
|
||||
item.trigger = 'plop'
|
||||
item.migrate()
|
||||
assert item.mode == 'trigger'
|
||||
|
||||
item = JumpWorkflowStatusItem()
|
||||
item.timeout = '12'
|
||||
item.migrate()
|
||||
assert item.mode == 'timeout'
|
||||
|
||||
item = JumpWorkflowStatusItem()
|
||||
item.trigger = 'plop'
|
||||
item.timeout = '12'
|
||||
item.migrate()
|
||||
assert item.mode == 'trigger'
|
||||
|
||||
|
||||
def test_jump_nothing(pub):
|
||||
FormDef.wipe()
|
||||
formdef = FormDef()
|
||||
|
@ -246,8 +268,8 @@ def test_timeout(pub):
|
|||
jump = st1.add_action('jump', id='_jump')
|
||||
jump.by = ['_submitter', '_receiver']
|
||||
jump.timeout = 30 * 60 # 30 minutes
|
||||
jump.mode = 'timeout'
|
||||
jump.status = 'st2'
|
||||
|
||||
workflow.store()
|
||||
|
||||
formdef = FormDef()
|
||||
|
@ -311,6 +333,7 @@ def test_timeout_with_humantime_template(pub):
|
|||
jump = st1.add_action('jump', id='_jump')
|
||||
jump.by = ['_submitter', '_receiver']
|
||||
jump.timeout = '{{ 30 }} minutes'
|
||||
jump.mode = 'timeout'
|
||||
jump.status = 'st2'
|
||||
|
||||
workflow.store()
|
||||
|
@ -385,6 +408,7 @@ def test_legacy_timeout(pub):
|
|||
|
||||
jump = st1.add_action('timeout', id='_jump')
|
||||
jump.timeout = 30 * 60 # 30 minutes
|
||||
jump.mode = 'timeout'
|
||||
jump.status = 'st2'
|
||||
|
||||
workflow.store()
|
||||
|
@ -415,6 +439,7 @@ def test_timeout_then_remove(pub):
|
|||
jump = st1.add_action('jump', id='_jump')
|
||||
jump.by = ['_submitter', '_receiver']
|
||||
jump.timeout = 30 * 60 # 30 minutes
|
||||
jump.mode = 'timeout'
|
||||
jump.status = 'st2'
|
||||
|
||||
st2.add_action('remove')
|
||||
|
@ -453,6 +478,7 @@ def test_timeout_with_mark(pub):
|
|||
jump = st1.add_action('jump', id='_jump')
|
||||
jump.by = ['_submitter', '_receiver']
|
||||
jump.timeout = 30 * 60 # 30 minutes
|
||||
jump.mode = 'timeout'
|
||||
jump.status = 'st2'
|
||||
jump.set_marker_on_status = True
|
||||
|
||||
|
@ -484,6 +510,7 @@ def test_timeout_on_anonymised(pub):
|
|||
|
||||
jump = st1.add_action('timeout', id='_jump')
|
||||
jump.timeout = 30 * 60 # 30 minutes
|
||||
jump.mode = 'timeout'
|
||||
jump.status = 'st2'
|
||||
|
||||
workflow.store()
|
||||
|
@ -518,6 +545,7 @@ def test_jump_missing_previous_mark(pub):
|
|||
jump.by = ['_submitter', '_receiver']
|
||||
jump.status = '_previous'
|
||||
jump.timeout = 30 * 60 # 30 minutes
|
||||
jump.mode = 'timeout'
|
||||
|
||||
workflow.store()
|
||||
|
||||
|
@ -575,6 +603,7 @@ def test_timeout_tracing(pub, admin_user):
|
|||
|
||||
jump = st1.add_action('timeout', id='_jump')
|
||||
jump.timeout = 30 * 60 # 30 minutes
|
||||
jump.mode = 'timeout'
|
||||
jump.status = 'st2'
|
||||
|
||||
add_message = st2.add_action('register-comment')
|
||||
|
@ -616,6 +645,7 @@ def test_jump_self_timeout(pub):
|
|||
|
||||
jump = st1.add_action('jump')
|
||||
jump.timeout = 30 * 60 # 30 minutes
|
||||
jump.mode = 'timeout'
|
||||
jump.status = 'st1'
|
||||
|
||||
workflow.store()
|
||||
|
@ -645,6 +675,7 @@ def test_timeout_cron_debug_log(pub):
|
|||
jump = st1.add_action('jump', id='_jump')
|
||||
jump.by = ['_submitter', '_receiver']
|
||||
jump.timeout = 30 * 60 # 30 minutes
|
||||
jump.mode = 'timeout'
|
||||
jump.status = 'st2'
|
||||
|
||||
workflow.store()
|
||||
|
|
|
@ -38,7 +38,13 @@ from wcs.workflows import (
|
|||
|
||||
from ..qommon import _, errors, force_str, misc
|
||||
from ..qommon.cron import CronJob
|
||||
from ..qommon.form import ComputedExpressionWidget, SingleSelectWidget, StringWidget, WidgetList
|
||||
from ..qommon.form import (
|
||||
ComputedExpressionWidget,
|
||||
RadiobuttonsWidget,
|
||||
SingleSelectWidget,
|
||||
StringWidget,
|
||||
WidgetList,
|
||||
)
|
||||
from ..qommon.humantime import humanduration2seconds, seconds2humanduration, timewords
|
||||
from ..qommon.publisher import get_publisher_class
|
||||
from ..qommon.template import Template
|
||||
|
@ -94,9 +100,7 @@ class TriggerDirectory(Directory):
|
|||
for item in self.wfstatus.items:
|
||||
if not isinstance(item, JumpWorkflowStatusItem):
|
||||
continue
|
||||
if not hasattr(item, 'trigger'):
|
||||
continue
|
||||
if component == item.trigger:
|
||||
if item.mode == 'trigger' and item.trigger == component:
|
||||
if not item.get_target_status():
|
||||
raise errors.PublishError('broken jump / missing target')
|
||||
if not get_request().get_method() == 'POST':
|
||||
|
@ -152,6 +156,7 @@ class JumpWorkflowStatusItem(WorkflowStatusJumpItem):
|
|||
key = 'jump'
|
||||
|
||||
by = []
|
||||
mode = None
|
||||
condition = None
|
||||
trigger = None
|
||||
timeout = None
|
||||
|
@ -160,6 +165,18 @@ class JumpWorkflowStatusItem(WorkflowStatusJumpItem):
|
|||
directory_name = 'jump'
|
||||
directory_class = JumpDirectory
|
||||
|
||||
def migrate(self):
|
||||
changed = super().migrate()
|
||||
if not self.mode: # 2024-03-29
|
||||
if self.trigger:
|
||||
self.mode = 'trigger'
|
||||
elif self.timeout:
|
||||
self.mode = 'timeout'
|
||||
else:
|
||||
self.mode = 'immediate'
|
||||
changed = True
|
||||
return changed
|
||||
|
||||
def timeout_init_with_xml(self, elem, include_id=False, snapshot=False):
|
||||
if elem is None or elem.text is None:
|
||||
self.timeout = None
|
||||
|
@ -217,12 +234,38 @@ class JumpWorkflowStatusItem(WorkflowStatusJumpItem):
|
|||
def get_parameters(self):
|
||||
if hasattr(self, 'parent') and isinstance(self.parent, WorkflowGlobalAction):
|
||||
return ('status', 'condition', 'set_marker_on_status')
|
||||
return ('status', 'condition', 'trigger', 'by', 'timeout', 'set_marker_on_status')
|
||||
return ('status', 'condition', 'mode', 'trigger', 'by', 'timeout', 'set_marker_on_status')
|
||||
|
||||
def get_inspect_parameters(self):
|
||||
parameters = list(self.get_parameters())
|
||||
if self.mode != 'trigger' and 'trigger' in parameters:
|
||||
parameters.remove('trigger')
|
||||
if self.mode != 'trigger' and 'by' in parameters:
|
||||
parameters.remove('by')
|
||||
if self.mode != 'timeout' and 'timeout' in parameters:
|
||||
parameters.remove('timeout')
|
||||
return parameters
|
||||
|
||||
def add_parameters_widgets(self, form, parameters, prefix='', formdef=None, **kwargs):
|
||||
super().add_parameters_widgets(form, parameters, prefix, formdef, **kwargs)
|
||||
if 'condition' in parameters:
|
||||
form.get_widget('%scondition' % prefix).advanced = False
|
||||
form.get_widget('%scondition' % prefix).tab = ('general', _('General'))
|
||||
if 'mode' in parameters:
|
||||
form.add(
|
||||
RadiobuttonsWidget,
|
||||
'%smode' % prefix,
|
||||
title=_('Execution mode'),
|
||||
options=[
|
||||
('immediate', _('Immediate'), 'immediate'),
|
||||
('timeout', _('After timeout delay'), 'timeout'),
|
||||
('trigger', _('After call to webservice trigger'), 'trigger'),
|
||||
],
|
||||
value=self.mode if self.mode else 'immediate',
|
||||
default_value='immediate',
|
||||
attrs={'data-dynamic-display-parent': 'true'},
|
||||
extra_css_class='widget-inline-radio',
|
||||
)
|
||||
if 'trigger' in parameters:
|
||||
form.add(
|
||||
StringWidget,
|
||||
|
@ -234,6 +277,10 @@ class JumpWorkflowStatusItem(WorkflowStatusJumpItem):
|
|||
),
|
||||
value=self.trigger,
|
||||
size=40,
|
||||
attrs={
|
||||
'data-dynamic-display-child-of': '%smode' % prefix,
|
||||
'data-dynamic-display-value': 'trigger',
|
||||
},
|
||||
)
|
||||
if 'by' in parameters:
|
||||
if get_publisher().has_site_option('workflow-functions-only'):
|
||||
|
@ -251,6 +298,10 @@ class JumpWorkflowStatusItem(WorkflowStatusJumpItem):
|
|||
'render_br': False,
|
||||
'options': [(None, '---', None)] + self.get_list_of_roles(include_logged_in_users=False),
|
||||
},
|
||||
attrs={
|
||||
'data-dynamic-display-child-of': '%smode' % prefix,
|
||||
'data-dynamic-display-value': 'trigger',
|
||||
},
|
||||
)
|
||||
if 'timeout' in parameters:
|
||||
_hint = htmltext(
|
||||
|
@ -267,6 +318,10 @@ class JumpWorkflowStatusItem(WorkflowStatusJumpItem):
|
|||
title=_('Timeout'),
|
||||
value=self.timeout,
|
||||
hint=_hint,
|
||||
attrs={
|
||||
'data-dynamic-display-child-of': '%smode' % prefix,
|
||||
'data-dynamic-display-value': 'timeout',
|
||||
},
|
||||
)
|
||||
else:
|
||||
form.add(
|
||||
|
@ -275,6 +330,10 @@ class JumpWorkflowStatusItem(WorkflowStatusJumpItem):
|
|||
title=_('Timeout'),
|
||||
value=seconds2humanduration(self.timeout),
|
||||
hint=_hint,
|
||||
attrs={
|
||||
'data-dynamic-display-child-of': '%smode' % prefix,
|
||||
'data-dynamic-display-value': 'timeout',
|
||||
},
|
||||
)
|
||||
|
||||
def timeout_parse(self, value):
|
||||
|
@ -302,7 +361,7 @@ class JumpWorkflowStatusItem(WorkflowStatusJumpItem):
|
|||
if not result:
|
||||
return False
|
||||
|
||||
if self.timeout:
|
||||
if self.mode == 'timeout' and self.timeout:
|
||||
timeout_str = self.compute(self.timeout)
|
||||
try:
|
||||
timeout_seconds = float(timeout_str)
|
||||
|
@ -327,7 +386,7 @@ class JumpWorkflowStatusItem(WorkflowStatusJumpItem):
|
|||
if diff < timeout_seconds:
|
||||
return False
|
||||
|
||||
if self.trigger:
|
||||
if self.mode == 'trigger' and self.trigger:
|
||||
if trigger is None or trigger != self.trigger:
|
||||
return False
|
||||
|
||||
|
|
Loading…
Reference in New Issue