From 37f915e256d503e99bd41f0123785b70324b6ba1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20P=C3=A9ters?= Date: Sat, 21 Oct 2017 13:05:04 +0200 Subject: [PATCH] workflows: sort workflow actions in categories (#3405) --- tests/test_admin_pages.py | 57 ++++++++++++++++++++---------------- wcs/admin/workflows.py | 43 +++++++++++++++------------ wcs/qommon/static/css/dc2/admin.css | 4 +++ wcs/qommon/static/js/qommon.admin.js | 11 +++++++ wcs/wf/aggregation_email.py | 1 + wcs/wf/anonymise.py | 1 + wcs/wf/attachment.py | 1 + wcs/wf/backoffice_fields.py | 1 + wcs/wf/criticality.py | 1 + wcs/wf/dispatch.py | 1 + wcs/wf/export_to_model.py | 1 + wcs/wf/form.py | 1 + wcs/wf/geolocate.py | 1 + wcs/wf/profile.py | 1 + wcs/wf/redirect_to_url.py | 1 + wcs/wf/register_comment.py | 1 + wcs/wf/remove.py | 1 + wcs/wf/resubmit.py | 1 + wcs/wf/roles.py | 2 ++ wcs/wf/wscall.py | 1 + wcs/workflows.py | 6 ++++ 21 files changed, 93 insertions(+), 45 deletions(-) diff --git a/tests/test_admin_pages.py b/tests/test_admin_pages.py index 0e00d0dd..48a7c144 100644 --- a/tests/test_admin_pages.py +++ b/tests/test_admin_pages.py @@ -1576,7 +1576,7 @@ def test_workflows_new(pub): # create a new action resp = resp.click('new status') - resp.forms[0]['type'] = 'Display message' + resp.forms[0]['action-interaction'] = 'Display message' resp = resp.forms[0].submit() assert resp.location == 'http://example.net/backoffice/workflows/1/status/1/' resp = resp.follow() @@ -1848,16 +1848,20 @@ def test_workflows_add_all_actions(pub): resp = app.get('/backoffice/workflows/1/') resp = resp.click('baz') - for action in [x[0] for x in resp.forms[0]['type'].options]: - resp.forms[0]['type'] = action - resp = resp.forms[0].submit() - resp = resp.follow() - - for i in range(len(resp.forms[0]['type'].options)): - resp = resp.click('Edit', href='items/%d/' % (i+1), index=0) - resp = resp.forms[0].submit('cancel') - resp = resp.follow() # redirect to items/ - resp = resp.follow() # redirect to ./ + for category in ('status-change', 'interaction', 'formdata-action', 'user-action'): + for action in [x[0] for x in resp.forms[0]['action-%s' % category].options if x[0]]: + resp.forms[0]['action-%s' % category] = action + resp = resp.forms[0].submit() + resp = resp.follow() + + i = 1 + for category in ('status-change', 'interaction', 'formdata-action', 'user-action'): + for action in [x[0] for x in resp.forms[0]['action-%s' % category].options if x[0]]: + resp = resp.click('Edit', href='items/%d/' % i, index=0) + resp = resp.forms[0].submit('cancel') + resp = resp.follow() # redirect to items/ + resp = resp.follow() # redirect to ./ + i += 1 def test_workflows_check_available_actions(pub): create_superuser(pub) @@ -1871,8 +1875,8 @@ def test_workflows_check_available_actions(pub): resp = app.get('/backoffice/workflows/1/') resp = resp.click('baz') - assert not 'Modify Criticality' in [x[0] for x in resp.forms[0]['type'].options] - assert not 'Send SMS' in [x[0] for x in resp.forms[0]['type'].options] + assert not 'Modify Criticality' in [x[0] for x in resp.forms[0]['action-formdata-action'].options] + assert not 'Send SMS' in [x[0] for x in resp.forms[0]['action-interaction'].options] pub.cfg['sms'] = {'mode': 'foobar'} pub.write_cfg() @@ -1880,8 +1884,8 @@ def test_workflows_check_available_actions(pub): workflow.store() resp = app.get('/backoffice/workflows/1/') resp = resp.click('baz') - assert 'Modify Criticality' in [x[0] for x in resp.forms[0]['type'].options] - assert 'Send SMS' in [x[0] for x in resp.forms[0]['type'].options] + assert 'Modify Criticality' in [x[0] for x in resp.forms[0]['action-formdata-action'].options] + assert 'Send SMS' in [x[0] for x in resp.forms[0]['action-interaction'].options] def test_workflows_edit_dispatch_action(pub): create_superuser(pub) @@ -1895,7 +1899,7 @@ def test_workflows_edit_dispatch_action(pub): resp = app.get('/backoffice/workflows/1/') resp = resp.click('baz') - resp.forms[0]['type'] = 'Assign a Function' + resp.forms[0]['action-formdata-action'] = 'Assign a Function' resp = resp.forms[0].submit() resp = resp.follow() @@ -1928,7 +1932,7 @@ def test_workflows_edit_email_action(pub): resp = app.get('/backoffice/workflows/1/') resp = resp.click('baz') - resp.forms[0]['type'] = 'Send mail' + resp.forms[0]['action-interaction'] = 'Send mail' resp = resp.forms[0].submit() resp = resp.follow() @@ -2046,7 +2050,7 @@ def test_workflows_edit_sms_action(pub): resp = app.get('/backoffice/workflows/1/') resp = resp.click('baz') - resp.form['type'] = 'Send SMS' + resp.form['action-interaction'] = 'Send SMS' resp = resp.form.submit().follow() resp = resp.click('Send SMS') @@ -2064,7 +2068,7 @@ def test_workflows_edit_display_form_action(pub): resp = app.get('/backoffice/workflows/1/') resp = resp.click('baz') - resp.forms[0]['type'] = 'Display a form' + resp.forms[0]['action-interaction'] = 'Display a form' resp = resp.forms[0].submit() resp = resp.follow() @@ -2092,7 +2096,7 @@ def test_workflows_edit_choice_action(pub): resp = app.get('/backoffice/workflows/1/') resp = resp.click('baz') - resp.forms[0]['type'] = 'Change Status' + resp.forms[0]['action-status-change'] = 'Change Status' resp = resp.forms[0].submit() resp = resp.follow() @@ -2166,7 +2170,7 @@ def test_workflows_delete_action(pub): resp = app.get('/backoffice/workflows/1/') resp = resp.click('baz') - resp.forms[0]['type'] = 'Send mail' + resp.forms[0]['action-interaction'] = 'Send mail' resp = resp.forms[0].submit() resp = resp.follow() assert 'Send mail' in resp.body @@ -2296,7 +2300,7 @@ def test_workflows_backoffice_fields(pub): # check the "set backoffice fields" action is now available resp = app.get('/backoffice/workflows/1/') resp = resp.click('baz') - resp.forms[0]['type'] = 'Set Backoffice Fields' + resp.forms[0]['action-formdata-action'] = 'Set Backoffice Fields' resp = resp.forms[0].submit() resp = resp.follow() @@ -2483,10 +2487,11 @@ def test_workflows_global_actions_edit(pub): resp = resp.follow() # test adding all actions - for action in [x[0] for x in resp.forms[0]['type'].options]: - resp.forms[0]['type'] = action - resp = resp.forms[0].submit() - resp = resp.follow() + for category in ('status-change', 'interaction', 'formdata-action', 'user-action'): + for action in [x[0] for x in resp.forms[0]['action-%s' % category].options if x[0]]: + resp.forms[0]['action-%s' % category] = action + resp = resp.forms[0].submit() + resp = resp.follow() # test visiting action_id = Workflow.get(workflow.id).global_actions[0].id diff --git a/wcs/admin/workflows.py b/wcs/admin/workflows.py index 924215ac..e69e6efa 100644 --- a/wcs/admin/workflows.py +++ b/wcs/admin/workflows.py @@ -497,7 +497,7 @@ class WorkflowStatusPage(Directory): r += htmltext('
  • %s
  • ') % _('Delete') r += htmltext('') r += htmltext('
    ') - r += htmltext('

    %s

    ') % _('New Item') + r += htmltext('

    %s

    ') % _('New Action') r += self.get_new_item_form().render() r += htmltext('
    ') return r.getvalue() @@ -506,18 +506,22 @@ class WorkflowStatusPage(Directory): return item.is_available(workflow=self.workflow) def get_new_item_form(self): - form = Form(enctype='multipart/form-data', action = 'newitem') + form = Form(enctype='multipart/form-data', action='newitem', + id='new-action-form') + categories = [ + ('status-change', _('Change Status')), + ('interaction', _('Interact')), + ('formdata-action', _('Act on Form')), + ('user-action', _('Act on User')), + ] available_items = [x for x in item_classes if self.is_item_available(x)] - def cmp_items(x, y): - t = cmp(x.category and x.category[0], y.category and y.category[0]) - if t: - return t - return cmp(_(x.description), _(y.description)) - - available_items.sort(cmp_items) - options = [(x.key, _(x.description)) for x in available_items] - form.add(SingleSelectWidget, 'type', title = _('Type'), - required=True, options = options) + available_items.sort(key=lambda x: _(x.description)) + + for category, category_label in categories: + options = [(x.key, _(x.description)) for x in available_items + if x.category == category] + form.add(SingleSelectWidget, 'action-%s' % category, title=category_label, + required=False, options=[(None, '')] + options) form.add_submit('submit', _('Add')) return form @@ -535,16 +539,17 @@ class WorkflowStatusPage(Directory): get_session().message = ('error', _('Submitted form was not filled properly.')) return redirect('.') - if form.get_widget('type').parse(): - self.status.append_item(form.get_widget('type').parse()) - else: - get_session().message = ('error', _('Submitted form was not filled properly.')) - return redirect('.') - - self.workflow.store() + for category in ('status-change', 'interaction', 'formdata-action', 'user-action'): + action_type = form.get_widget('action-%s' % category).parse() + if action_type: + self.status.append_item(action_type) + self.workflow.store() + return redirect('.') + get_session().message = ('error', _('Submitted form was not filled properly.')) return redirect('.') + def delete(self): form = Form(enctype="multipart/form-data") form.widgets.append(HtmlWidget('

    %s

    ' % _( diff --git a/wcs/qommon/static/css/dc2/admin.css b/wcs/qommon/static/css/dc2/admin.css index 8e33e40c..067a5973 100644 --- a/wcs/qommon/static/css/dc2/admin.css +++ b/wcs/qommon/static/css/dc2/admin.css @@ -1620,3 +1620,7 @@ a.leaflet-popup-close-button { div.widget input[type=text][readonly] { background: #f0f0f0; } + +#new-action-form select[disabled] { + background: #f0f0f0; +} diff --git a/wcs/qommon/static/js/qommon.admin.js b/wcs/qommon/static/js/qommon.admin.js index eda24dfd..a5bc6873 100644 --- a/wcs/qommon/static/js/qommon.admin.js +++ b/wcs/qommon/static/js/qommon.admin.js @@ -87,6 +87,17 @@ $(function() { $('input[type=hidden][name=submission_channel]').val($(this).val()); }); + /* new action form */ + $('#new-action-form select').on('change', function() { + if ($(this).val() == '') { + $('#new-action-form select').prop('disabled', null) + } else { + $('#new-action-form select').prop('disabled', 'disabled') + $(this).prop('disabled', null) + } + return false; + }); + /* possibility to toggle the sidebar */ if ($('#sidebar').length) { $('#main-content').after($('')); diff --git a/wcs/wf/aggregation_email.py b/wcs/wf/aggregation_email.py index f569ec91..2b28da09 100644 --- a/wcs/wf/aggregation_email.py +++ b/wcs/wf/aggregation_email.py @@ -29,6 +29,7 @@ from wcs.roles import Role class AggregationEmailWorkflowStatusItem(WorkflowStatusItem): description = N_('Aggregate to summary email') key = 'aggregationemail' + category = 'interaction' ok_in_global_action = False to = [] diff --git a/wcs/wf/anonymise.py b/wcs/wf/anonymise.py index f2127aee..f8730479 100644 --- a/wcs/wf/anonymise.py +++ b/wcs/wf/anonymise.py @@ -19,6 +19,7 @@ from wcs.workflows import WorkflowStatusItem, register_item_class class AnonymiseWorkflowStatusItem(WorkflowStatusItem): description = N_('Anonymise') key = 'anonymise' + category = 'formdata-action' def perform(self, formdata): formdata.anonymise() diff --git a/wcs/wf/attachment.py b/wcs/wf/attachment.py index 4bb71518..5581e186 100644 --- a/wcs/wf/attachment.py +++ b/wcs/wf/attachment.py @@ -68,6 +68,7 @@ def form_attachment(self): class AddAttachmentWorkflowStatusItem(WorkflowStatusItem): description = N_('Allow Joining a File') key = 'addattachment' + category = 'interaction' endpoint = False waitpoint = True ok_in_global_action = False diff --git a/wcs/wf/backoffice_fields.py b/wcs/wf/backoffice_fields.py index eea71033..01e77aa8 100644 --- a/wcs/wf/backoffice_fields.py +++ b/wcs/wf/backoffice_fields.py @@ -67,6 +67,7 @@ class SetBackofficeFieldsTableWidget(WidgetListAsTable): class SetBackofficeFieldsWorkflowStatusItem(WorkflowStatusItem): description = N_('Set Backoffice Fields') key = 'set-backoffice-fields' + category = 'formdata-action' fields = None diff --git a/wcs/wf/criticality.py b/wcs/wf/criticality.py index d78700a4..c7d2dbca 100644 --- a/wcs/wf/criticality.py +++ b/wcs/wf/criticality.py @@ -27,6 +27,7 @@ MODE_SET = '3' class ModifyCriticalityWorkflowStatusItem(WorkflowStatusItem): description = N_('Modify Criticality') key = 'modify_criticality' + category = 'formdata-action' mode = MODE_INC absolute_value = None diff --git a/wcs/wf/dispatch.py b/wcs/wf/dispatch.py index 04dfedbc..414d74dd 100644 --- a/wcs/wf/dispatch.py +++ b/wcs/wf/dispatch.py @@ -80,6 +80,7 @@ class RuleNode(XmlSerialisable): class DispatchWorkflowStatusItem(WorkflowStatusItem): description = N_('Assign a Function') key = 'dispatch' + category = 'formdata-action' role_id = None role_key = None diff --git a/wcs/wf/export_to_model.py b/wcs/wf/export_to_model.py index 4250038b..4d058ec7 100644 --- a/wcs/wf/export_to_model.py +++ b/wcs/wf/export_to_model.py @@ -196,6 +196,7 @@ def rtf_process(value): class ExportToModel(WorkflowStatusItem): description = N_('Create Document') key = 'export_to_model' + category = 'formdata-action' support_substitution_variables = True ok_in_global_action = False diff --git a/wcs/wf/form.py b/wcs/wf/form.py index 8c3bcc27..2bab1606 100644 --- a/wcs/wf/form.py +++ b/wcs/wf/form.py @@ -71,6 +71,7 @@ class WorkflowFormFieldsDirectory(FieldsDirectory): class FormWorkflowStatusItem(WorkflowStatusItem): description = N_('Display a form') key = 'form' + category = 'interaction' ok_in_global_action = False endpoint = False waitpoint = True diff --git a/wcs/wf/geolocate.py b/wcs/wf/geolocate.py index bc2c0b16..48c21133 100644 --- a/wcs/wf/geolocate.py +++ b/wcs/wf/geolocate.py @@ -35,6 +35,7 @@ from wcs.workflows import WorkflowStatusItem, register_item_class class GeolocateWorkflowStatusItem(WorkflowStatusItem): description = N_('Geolocate') key = 'geolocate' + category = 'formdata-action' method = 'address_string' address_string = None diff --git a/wcs/wf/profile.py b/wcs/wf/profile.py index ec593b8a..13a3c351 100644 --- a/wcs/wf/profile.py +++ b/wcs/wf/profile.py @@ -101,6 +101,7 @@ class FieldNode(XmlSerialisable): class UpdateUserProfileStatusItem(WorkflowStatusItem): description = N_('Update User Profile') key = 'update_user_profile' + category = 'user-action' fields = None diff --git a/wcs/wf/redirect_to_url.py b/wcs/wf/redirect_to_url.py index 9355febd..acb5da33 100644 --- a/wcs/wf/redirect_to_url.py +++ b/wcs/wf/redirect_to_url.py @@ -22,6 +22,7 @@ from wcs.workflows import WorkflowStatusItem, register_item_class class RedirectToUrlWorkflowStatusItem(WorkflowStatusItem): description = N_('Redirect to URL') key = 'redirect_to_url' + category = 'formdata-action' endpoint = False support_substitution_variables = True diff --git a/wcs/wf/register_comment.py b/wcs/wf/register_comment.py index 7a1c5c63..beebecf7 100644 --- a/wcs/wf/register_comment.py +++ b/wcs/wf/register_comment.py @@ -64,6 +64,7 @@ class JournalEvolutionPart: #pylint: disable=C1001 class RegisterCommenterWorkflowStatusItem(WorkflowStatusItem): description = N_('Record in Log') key = 'register-comment' + category = 'interaction' comment = None diff --git a/wcs/wf/remove.py b/wcs/wf/remove.py index 0c536c0a..0a71d5e7 100644 --- a/wcs/wf/remove.py +++ b/wcs/wf/remove.py @@ -21,6 +21,7 @@ from wcs.workflows import WorkflowStatusItem, register_item_class class RemoveWorkflowStatusItem(WorkflowStatusItem): description = N_('Remove') key = 'remove' + category = 'formdata-action' def perform(self, formdata): formdata.remove_self() diff --git a/wcs/wf/resubmit.py b/wcs/wf/resubmit.py index 20cd139c..df3d4687 100644 --- a/wcs/wf/resubmit.py +++ b/wcs/wf/resubmit.py @@ -26,6 +26,7 @@ from wcs.qommon.form import (WidgetList, SingleSelectWidget, StringWidget, class ResubmitWorkflowStatusItem(WorkflowStatusItem): description = N_('Resubmit') key = 'resubmit' + category = 'formdata-action' endpoint = False waitpoint = True ok_in_global_action = False diff --git a/wcs/wf/roles.py b/wcs/wf/roles.py index 13006331..28263a2a 100644 --- a/wcs/wf/roles.py +++ b/wcs/wf/roles.py @@ -44,6 +44,7 @@ def roles_ws_url(role_uuid, user_uuid): class AddRoleWorkflowStatusItem(WorkflowStatusItem): description = N_('Add Role to User') key = 'add_role' + category = 'user-action' role_id = None @@ -112,6 +113,7 @@ register_item_class(AddRoleWorkflowStatusItem) class RemoveRoleWorkflowStatusItem(WorkflowStatusItem): description = N_('Remove Role from User') key = 'remove_role' + category = 'user-action' role_id = None diff --git a/wcs/wf/wscall.py b/wcs/wf/wscall.py index d801243a..869e4ba1 100644 --- a/wcs/wf/wscall.py +++ b/wcs/wf/wscall.py @@ -94,6 +94,7 @@ class JournalWsCallErrorPart: #pylint: disable=C1001 class WebserviceCallStatusItem(WorkflowStatusItem): description = N_('Webservice Call') key = 'webservice_call' + category = 'interaction' support_substitution_variables = True label = None diff --git a/wcs/workflows.py b/wcs/workflows.py index 0197a2c2..27108ce7 100644 --- a/wcs/workflows.py +++ b/wcs/workflows.py @@ -1705,6 +1705,7 @@ class WorkflowStatusJumpItem(WorkflowStatusItem): status = None endpoint = False set_marker_on_status = False + category = 'status-change' def add_parameters_widgets(self, form, parameters, prefix='', formdef=None): if 'status' in parameters: @@ -1790,6 +1791,7 @@ def register_item_class(klass): class CommentableWorkflowStatusItem(WorkflowStatusItem): description = N_('Allow Comment') key = 'commentable' + category = 'interaction' endpoint = False waitpoint = True ok_in_global_action = False @@ -2010,6 +2012,7 @@ register_item_class(JumpOnSubmitWorkflowStatusItem) class SendmailWorkflowStatusItem(WorkflowStatusItem): description = N_('Send mail') key = 'sendmail' + category = 'interaction' support_substitution_variables = True to = [] @@ -2286,6 +2289,7 @@ def template_on_context(context=None, template=None, process=None, class SendSMSWorkflowStatusItem(WorkflowStatusItem): description = N_('Send SMS') key = 'sendsms' + category = 'interaction' support_substitution_variables = True to = [] @@ -2355,6 +2359,7 @@ register_item_class(SendSMSWorkflowStatusItem) class DisplayMessageWorkflowStatusItem(WorkflowStatusItem): description = N_('Display message') key = 'displaymsg' + category = 'interaction' support_substitution_variables = True ok_in_global_action = False @@ -2456,6 +2461,7 @@ class RedirectToStatusWorkflowStatusItem(WorkflowStatusItem): class EditableWorkflowStatusItem(WorkflowStatusItem): description = N_('Allow Edition') key = 'editable' + category = 'formdata-action' endpoint = False waitpoint = True ok_in_global_action = False -- 2.15.0.rc1