Add workflows per document type view
Make workflows, workflows states, workflow transitions column sortable. Show completion and intial state in the workflow proxy instance menu list. Signed-off-by: Roberto Rosario <roberto.rosario.gonzalez@gmail.com>
This commit is contained in:
@@ -227,6 +227,12 @@
|
|||||||
the new AddRemove view.
|
the new AddRemove view.
|
||||||
* Add the workflow created and edited events.
|
* Add the workflow created and edited events.
|
||||||
* Remove AssignRemove View.
|
* Remove AssignRemove View.
|
||||||
|
* Add view to setup workflows per document type
|
||||||
|
from the document type side.
|
||||||
|
* Make workflows, workflows states, workflow
|
||||||
|
transitions column sortable.
|
||||||
|
* Show completion and intial state in the
|
||||||
|
workflow proxy instance menu list.
|
||||||
|
|
||||||
3.1.11 (2019-04-XX)
|
3.1.11 (2019-04-XX)
|
||||||
===================
|
===================
|
||||||
|
|||||||
@@ -260,6 +260,12 @@ Other changes
|
|||||||
the new AddRemove view.
|
the new AddRemove view.
|
||||||
* Add the workflow created and edited events.
|
* Add the workflow created and edited events.
|
||||||
* Remove AssignRemove View.
|
* Remove AssignRemove View.
|
||||||
|
* Add view to setup workflows per document type
|
||||||
|
from the document type side.
|
||||||
|
* Make workflows, workflows states, workflow
|
||||||
|
transitions column sortable.
|
||||||
|
* Show completion and intial state in the
|
||||||
|
workflow proxy instance menu list.
|
||||||
|
|
||||||
Removals
|
Removals
|
||||||
--------
|
--------
|
||||||
|
|||||||
@@ -31,10 +31,11 @@ from .handlers import (
|
|||||||
handler_index_document, handler_launch_workflow, handler_trigger_transition
|
handler_index_document, handler_launch_workflow, handler_trigger_transition
|
||||||
)
|
)
|
||||||
from .links import (
|
from .links import (
|
||||||
link_document_workflow_instance_list, link_setup_workflow_document_types,
|
link_document_workflow_instance_list, link_setup_document_type_workflows,
|
||||||
link_setup_workflow_create, link_setup_workflow_delete,
|
link_setup_workflow_document_types, link_setup_workflow_create,
|
||||||
link_setup_workflow_edit, link_setup_workflow_list,
|
link_setup_workflow_delete, link_setup_workflow_edit,
|
||||||
link_setup_workflow_states, link_setup_workflow_state_action_delete,
|
link_setup_workflow_list, link_setup_workflow_states,
|
||||||
|
link_setup_workflow_state_action_delete,
|
||||||
link_setup_workflow_state_action_edit,
|
link_setup_workflow_state_action_edit,
|
||||||
link_setup_workflow_state_action_list,
|
link_setup_workflow_state_action_list,
|
||||||
link_setup_workflow_state_action_selection,
|
link_setup_workflow_state_action_selection,
|
||||||
@@ -74,6 +75,9 @@ class DocumentStatesApp(MayanAppConfig):
|
|||||||
Document = apps.get_model(
|
Document = apps.get_model(
|
||||||
app_label='documents', model_name='Document'
|
app_label='documents', model_name='Document'
|
||||||
)
|
)
|
||||||
|
DocumentType = apps.get_model(
|
||||||
|
app_label='documents', model_name='DocumentType'
|
||||||
|
)
|
||||||
ErrorLogEntry = apps.get_model(
|
ErrorLogEntry = apps.get_model(
|
||||||
app_label='common', model_name='ErrorLogEntry'
|
app_label='common', model_name='ErrorLogEntry'
|
||||||
)
|
)
|
||||||
@@ -158,15 +162,14 @@ class DocumentStatesApp(MayanAppConfig):
|
|||||||
)
|
)
|
||||||
|
|
||||||
SourceColumn(
|
SourceColumn(
|
||||||
source=Workflow, label=_('Label'), attribute='label'
|
attribute='label', is_sortable=True, source=Workflow
|
||||||
)
|
)
|
||||||
SourceColumn(
|
SourceColumn(
|
||||||
source=Workflow, label=_('Internal name'),
|
attribute='internal_name', is_sortable=True, source=Workflow
|
||||||
attribute='internal_name'
|
|
||||||
)
|
)
|
||||||
SourceColumn(
|
SourceColumn(
|
||||||
source=Workflow, label=_('Initial state'),
|
attribute='get_initial_state', empty_value=_('None'),
|
||||||
func=lambda context: context['object'].get_initial_state() or _('None')
|
source=Workflow
|
||||||
)
|
)
|
||||||
|
|
||||||
SourceColumn(
|
SourceColumn(
|
||||||
@@ -213,36 +216,42 @@ class DocumentStatesApp(MayanAppConfig):
|
|||||||
)
|
)
|
||||||
|
|
||||||
SourceColumn(
|
SourceColumn(
|
||||||
attribute='initial', label=_('Is initial state?'),
|
attribute='label', is_sortable=True, source=WorkflowState
|
||||||
source=WorkflowState, widget=TwoStateWidget
|
|
||||||
)
|
)
|
||||||
SourceColumn(
|
SourceColumn(
|
||||||
source=WorkflowState, label=_('Completion'), attribute='completion'
|
attribute='initial', is_sortable=True, source=WorkflowState,
|
||||||
|
widget=TwoStateWidget
|
||||||
|
)
|
||||||
|
SourceColumn(
|
||||||
|
attribute='completion', source=WorkflowState, is_sortable=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
SourceColumn(
|
SourceColumn(
|
||||||
source=WorkflowStateAction, label=_('Label'), attribute='label'
|
attribute='label', is_sortable=True, source=WorkflowStateAction
|
||||||
)
|
)
|
||||||
SourceColumn(
|
SourceColumn(
|
||||||
attribute='enabled', label=_('Enabled?'),
|
attribute='enabled', is_sortable=True, source=WorkflowStateAction,
|
||||||
source=WorkflowStateAction, widget=TwoStateWidget
|
widget=TwoStateWidget
|
||||||
)
|
)
|
||||||
SourceColumn(
|
SourceColumn(
|
||||||
source=WorkflowStateAction, label=_('When?'),
|
attribute='get_when_display', label=_('When?'),
|
||||||
attribute='get_when_display'
|
source=WorkflowStateAction
|
||||||
)
|
)
|
||||||
SourceColumn(
|
SourceColumn(
|
||||||
source=WorkflowStateAction, label=_('Action type'),
|
attribute='get_class_label', label=_('Action type'),
|
||||||
attribute='get_class_label'
|
source=WorkflowStateAction
|
||||||
)
|
)
|
||||||
|
|
||||||
SourceColumn(
|
SourceColumn(
|
||||||
source=WorkflowTransition, label=_('Origin state'),
|
attribute='label', is_sortable=True, source=WorkflowTransition,
|
||||||
attribute='origin_state'
|
|
||||||
)
|
)
|
||||||
SourceColumn(
|
SourceColumn(
|
||||||
source=WorkflowTransition, label=_('Destination state'),
|
attribute='origin_state', is_sortable=True,
|
||||||
attribute='destination_state'
|
source=WorkflowTransition
|
||||||
|
)
|
||||||
|
SourceColumn(
|
||||||
|
attribute='destination_state', is_sortable=True,
|
||||||
|
source=WorkflowTransition
|
||||||
)
|
)
|
||||||
SourceColumn(
|
SourceColumn(
|
||||||
source=WorkflowTransition, label=_('Triggers'),
|
source=WorkflowTransition, label=_('Triggers'),
|
||||||
@@ -271,6 +280,7 @@ class DocumentStatesApp(MayanAppConfig):
|
|||||||
menu_facet.bind_links(
|
menu_facet.bind_links(
|
||||||
links=(link_document_workflow_instance_list,), sources=(Document,)
|
links=(link_document_workflow_instance_list,), sources=(Document,)
|
||||||
)
|
)
|
||||||
|
|
||||||
menu_list_facet.bind_links(
|
menu_list_facet.bind_links(
|
||||||
links=(
|
links=(
|
||||||
link_acl_list, link_events_for_object,
|
link_acl_list, link_events_for_object,
|
||||||
@@ -280,6 +290,12 @@ class DocumentStatesApp(MayanAppConfig):
|
|||||||
link_workflow_preview
|
link_workflow_preview
|
||||||
), sources=(Workflow,)
|
), sources=(Workflow,)
|
||||||
)
|
)
|
||||||
|
menu_list_facet.bind_links(
|
||||||
|
links=(
|
||||||
|
link_setup_document_type_workflows,
|
||||||
|
), sources=(DocumentType,)
|
||||||
|
)
|
||||||
|
|
||||||
menu_main.bind_links(links=(link_workflow_runtime_proxy_list,), position=10)
|
menu_main.bind_links(links=(link_workflow_runtime_proxy_list,), position=10)
|
||||||
menu_object.bind_links(
|
menu_object.bind_links(
|
||||||
links=(
|
links=(
|
||||||
|
|||||||
@@ -3,6 +3,11 @@ from __future__ import absolute_import, unicode_literals
|
|||||||
from mayan.apps.appearance.classes import Icon
|
from mayan.apps.appearance.classes import Icon
|
||||||
from mayan.apps.documents.icons import icon_document_type
|
from mayan.apps.documents.icons import icon_document_type
|
||||||
|
|
||||||
|
|
||||||
|
icon_workflow = Icon(driver_name='fontawesome', symbol='sitemap')
|
||||||
|
|
||||||
|
icon_document_type_workflow_list = icon_workflow
|
||||||
|
|
||||||
icon_document_workflow_instance_list = Icon(
|
icon_document_workflow_instance_list = Icon(
|
||||||
driver_name='fontawesome', symbol='sitemap'
|
driver_name='fontawesome', symbol='sitemap'
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ from __future__ import unicode_literals
|
|||||||
|
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
|
from mayan.apps.documents.permissions import permission_document_type_edit
|
||||||
from mayan.apps.navigation.classes import Link
|
from mayan.apps.navigation.classes import Link
|
||||||
|
|
||||||
from .permissions import (
|
from .permissions import (
|
||||||
@@ -10,6 +11,12 @@ from .permissions import (
|
|||||||
permission_workflow_view,
|
permission_workflow_view,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
link_setup_document_type_workflows = Link(
|
||||||
|
args='resolved_object.pk',
|
||||||
|
icon_class_path='mayan.apps.document_states.icons.icon_document_type_workflow_list',
|
||||||
|
permissions=(permission_document_type_edit,), text=_('Workflows'),
|
||||||
|
view='document_states:document_type_workflows',
|
||||||
|
)
|
||||||
link_setup_workflow_create = Link(
|
link_setup_workflow_create = Link(
|
||||||
icon_class_path='mayan.apps.document_states.icons.icon_workflow_create',
|
icon_class_path='mayan.apps.document_states.icons.icon_workflow_create',
|
||||||
permissions=(permission_workflow_create,),
|
permissions=(permission_workflow_create,),
|
||||||
@@ -67,17 +74,21 @@ link_setup_workflow_state_action_selection = Link(
|
|||||||
)
|
)
|
||||||
link_setup_workflow_state_create = Link(
|
link_setup_workflow_state_create = Link(
|
||||||
args='resolved_object.pk',
|
args='resolved_object.pk',
|
||||||
icon_class_path='mayan.apps.document_states.icons.icon_workflow_state',
|
icon_class_path='mayan.apps.document_states.icons.icon_workflow_state_create',
|
||||||
permissions=(permission_workflow_edit,), text=_('Create state'),
|
permissions=(permission_workflow_edit,), text=_('Create state'),
|
||||||
view='document_states:setup_workflow_state_create',
|
view='document_states:setup_workflow_state_create',
|
||||||
)
|
)
|
||||||
link_setup_workflow_state_delete = Link(
|
link_setup_workflow_state_delete = Link(
|
||||||
args='object.pk', permissions=(permission_workflow_edit,),
|
args='object.pk',
|
||||||
|
icon_class_path='mayan.apps.document_states.icons.icon_workflow_state_delete',
|
||||||
|
permissions=(permission_workflow_edit,),
|
||||||
tags='dangerous', text=_('Delete'),
|
tags='dangerous', text=_('Delete'),
|
||||||
view='document_states:setup_workflow_state_delete',
|
view='document_states:setup_workflow_state_delete',
|
||||||
)
|
)
|
||||||
link_setup_workflow_state_edit = Link(
|
link_setup_workflow_state_edit = Link(
|
||||||
args='resolved_object.pk', permissions=(permission_workflow_edit,),
|
args='resolved_object.pk',
|
||||||
|
icon_class_path='mayan.apps.document_states.icons.icon_workflow_state_edit',
|
||||||
|
permissions=(permission_workflow_edit,),
|
||||||
text=_('Edit'), view='document_states:setup_workflow_state_edit',
|
text=_('Edit'), view='document_states:setup_workflow_state_edit',
|
||||||
)
|
)
|
||||||
link_setup_workflow_states = Link(
|
link_setup_workflow_states = Link(
|
||||||
@@ -88,17 +99,21 @@ link_setup_workflow_states = Link(
|
|||||||
)
|
)
|
||||||
link_setup_workflow_transition_create = Link(
|
link_setup_workflow_transition_create = Link(
|
||||||
args='resolved_object.pk',
|
args='resolved_object.pk',
|
||||||
icon_class_path='mayan.apps.document_states.icons.icon_workflow_transition',
|
icon_class_path='mayan.apps.document_states.icons.icon_workflow_transition_create',
|
||||||
permissions=(permission_workflow_edit,), text=_('Create transition'),
|
permissions=(permission_workflow_edit,), text=_('Create transition'),
|
||||||
view='document_states:setup_workflow_transition_create',
|
view='document_states:setup_workflow_transition_create',
|
||||||
)
|
)
|
||||||
link_setup_workflow_transition_delete = Link(
|
link_setup_workflow_transition_delete = Link(
|
||||||
args='resolved_object.pk', permissions=(permission_workflow_edit,),
|
args='resolved_object.pk',
|
||||||
|
icon_class_path='mayan.apps.document_states.icons.icon_workflow_transition_delete',
|
||||||
|
permissions=(permission_workflow_edit,),
|
||||||
tags='dangerous', text=_('Delete'),
|
tags='dangerous', text=_('Delete'),
|
||||||
view='document_states:setup_workflow_transition_delete',
|
view='document_states:setup_workflow_transition_delete',
|
||||||
)
|
)
|
||||||
link_setup_workflow_transition_edit = Link(
|
link_setup_workflow_transition_edit = Link(
|
||||||
args='resolved_object.pk', permissions=(permission_workflow_edit,),
|
args='resolved_object.pk',
|
||||||
|
icon_class_path='mayan.apps.document_states.icons.icon_workflow_transition_edit',
|
||||||
|
permissions=(permission_workflow_edit,),
|
||||||
text=_('Edit'), view='document_states:setup_workflow_transition_edit',
|
text=_('Edit'), view='document_states:setup_workflow_transition_edit',
|
||||||
)
|
)
|
||||||
link_setup_workflow_transitions = Link(
|
link_setup_workflow_transitions = Link(
|
||||||
@@ -108,7 +123,9 @@ link_setup_workflow_transitions = Link(
|
|||||||
view='document_states:setup_workflow_transition_list',
|
view='document_states:setup_workflow_transition_list',
|
||||||
)
|
)
|
||||||
link_workflow_transition_events = Link(
|
link_workflow_transition_events = Link(
|
||||||
args='resolved_object.pk', permissions=(permission_workflow_edit,),
|
args='resolved_object.pk',
|
||||||
|
icon_class_path='mayan.apps.document_states.icons.icon_workflow_transition_triggers',
|
||||||
|
permissions=(permission_workflow_edit,),
|
||||||
text=_('Transition triggers'),
|
text=_('Transition triggers'),
|
||||||
view='document_states:setup_workflow_transition_events'
|
view='document_states:setup_workflow_transition_events'
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -71,6 +71,7 @@ class Workflow(models.Model):
|
|||||||
return self.states.get(initial=True)
|
return self.states.get(initial=True)
|
||||||
except self.states.model.DoesNotExist:
|
except self.states.model.DoesNotExist:
|
||||||
return None
|
return None
|
||||||
|
get_initial_state.short_description = _('Initial state')
|
||||||
|
|
||||||
def launch_for(self, document):
|
def launch_for(self, document):
|
||||||
try:
|
try:
|
||||||
|
|||||||
@@ -25,6 +25,15 @@ from .views import (
|
|||||||
WorkflowImageView, WorkflowInstanceTransitionView, WorkflowListView,
|
WorkflowImageView, WorkflowInstanceTransitionView, WorkflowListView,
|
||||||
WorkflowPreviewView, WorkflowStateDocumentListView, WorkflowStateListView,
|
WorkflowPreviewView, WorkflowStateDocumentListView, WorkflowStateListView,
|
||||||
)
|
)
|
||||||
|
from .views.workflow_views import SetupDocumentTypeWorkflowsView
|
||||||
|
|
||||||
|
urlpatterns_workflows = [
|
||||||
|
url(
|
||||||
|
regex=r'^document_type/(?P<pk>\d+)/workflows/$',
|
||||||
|
view=SetupDocumentTypeWorkflowsView.as_view(),
|
||||||
|
name='document_type_workflows'
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
url(
|
url(
|
||||||
@@ -174,6 +183,7 @@ urlpatterns = [
|
|||||||
name='workflow_state_document_list'
|
name='workflow_state_document_list'
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
urlpatterns.extend(urlpatterns_workflows)
|
||||||
|
|
||||||
api_urls = [
|
api_urls = [
|
||||||
url(
|
url(
|
||||||
|
|||||||
@@ -131,8 +131,8 @@ class WorkflowStateListView(SingleObjectListView):
|
|||||||
|
|
||||||
def get_extra_context(self):
|
def get_extra_context(self):
|
||||||
return {
|
return {
|
||||||
'hide_columns': True,
|
|
||||||
'hide_link': True,
|
'hide_link': True,
|
||||||
|
'hide_object': True,
|
||||||
'no_results_main_link': link_setup_workflow_state_create.resolve(
|
'no_results_main_link': link_setup_workflow_state_create.resolve(
|
||||||
context=RequestContext(
|
context=RequestContext(
|
||||||
request=self.request, dict_={'object': self.get_workflow()}
|
request=self.request, dict_={'object': self.get_workflow()}
|
||||||
|
|||||||
@@ -64,6 +64,60 @@ __all__ = (
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class SetupDocumentTypeWorkflowsView(AddRemoveView):
|
||||||
|
main_object_permission = permission_document_type_edit
|
||||||
|
main_object_model = DocumentType
|
||||||
|
main_object_pk_url_kwarg = 'pk'
|
||||||
|
secondary_object_model = Workflow
|
||||||
|
secondary_object_permission = permission_workflow_edit
|
||||||
|
list_available_title = _('Available workflows')
|
||||||
|
list_added_title = _('Workflows assigned this document type')
|
||||||
|
related_field = 'workflows'
|
||||||
|
|
||||||
|
def get_actions_extra_kwargs(self):
|
||||||
|
return {'_user': self.request.user}
|
||||||
|
|
||||||
|
def get_extra_context(self):
|
||||||
|
return {
|
||||||
|
'object': self.main_object,
|
||||||
|
'subtitle': _(
|
||||||
|
'Removing a workflow from a document type will also '
|
||||||
|
'remove all running instances of that workflow.'
|
||||||
|
),
|
||||||
|
'title': _(
|
||||||
|
'Workflows assigned the document type: %s'
|
||||||
|
) % self.main_object,
|
||||||
|
}
|
||||||
|
|
||||||
|
def action_add(self, queryset, _user):
|
||||||
|
with transaction.atomic():
|
||||||
|
event_document_type_edited.commit(
|
||||||
|
actor=_user, target=self.main_object
|
||||||
|
)
|
||||||
|
|
||||||
|
for obj in queryset:
|
||||||
|
self.main_object.workflows.add(obj)
|
||||||
|
event_workflow_edited.commit(
|
||||||
|
action_object=self.main_object, actor=_user, target=obj
|
||||||
|
)
|
||||||
|
|
||||||
|
def action_remove(self, queryset, _user):
|
||||||
|
with transaction.atomic():
|
||||||
|
event_document_type_edited.commit(
|
||||||
|
actor=_user, target=self.main_object
|
||||||
|
)
|
||||||
|
|
||||||
|
for obj in queryset:
|
||||||
|
self.main_object.workflows.remove(obj)
|
||||||
|
event_workflow_edited.commit(
|
||||||
|
action_object=self.main_object, actor=_user,
|
||||||
|
target=obj
|
||||||
|
)
|
||||||
|
obj.instances.filter(
|
||||||
|
document__document_type=self.main_object
|
||||||
|
).delete()
|
||||||
|
|
||||||
|
|
||||||
class SetupWorkflowListView(SingleObjectListView):
|
class SetupWorkflowListView(SingleObjectListView):
|
||||||
model = Workflow
|
model = Workflow
|
||||||
object_permission = permission_workflow_view
|
object_permission = permission_workflow_view
|
||||||
@@ -449,6 +503,7 @@ class SetupWorkflowStateListView(SingleObjectListView):
|
|||||||
def get_extra_context(self):
|
def get_extra_context(self):
|
||||||
return {
|
return {
|
||||||
'hide_link': True,
|
'hide_link': True,
|
||||||
|
'hide_object': True,
|
||||||
'no_results_icon': icon_workflow_state,
|
'no_results_icon': icon_workflow_state,
|
||||||
'no_results_main_link': link_setup_workflow_state_create.resolve(
|
'no_results_main_link': link_setup_workflow_state_create.resolve(
|
||||||
context=RequestContext(
|
context=RequestContext(
|
||||||
@@ -577,6 +632,7 @@ class SetupWorkflowTransitionListView(SingleObjectListView):
|
|||||||
def get_extra_context(self):
|
def get_extra_context(self):
|
||||||
return {
|
return {
|
||||||
'hide_link': True,
|
'hide_link': True,
|
||||||
|
'hide_object': True,
|
||||||
'no_results_icon': icon_workflow_transition,
|
'no_results_icon': icon_workflow_transition,
|
||||||
'no_results_main_link': link_setup_workflow_transition_create.resolve(
|
'no_results_main_link': link_setup_workflow_transition_create.resolve(
|
||||||
context=RequestContext(
|
context=RequestContext(
|
||||||
|
|||||||
Reference in New Issue
Block a user