diff --git a/joeflow/models.py b/joeflow/models.py index 1ff6ece..cfe51e1 100644 --- a/joeflow/models.py +++ b/joeflow/models.py @@ -19,6 +19,7 @@ from .conf import settings from .typing import HUMAN, MACHINE from .utils import NoDashDiGraph +from .views import StartViewMixin logger = logging.getLogger(__name__) @@ -139,7 +140,7 @@ def urls(cls): urls = [] for name, node in cls.get_nodes(): if isinstance(node, View): - if isinstance(node, BaseCreateView): + if isinstance(node, (BaseCreateView, StartViewMixin)): route = f"{name}/" else: route = f"{name}//" diff --git a/joeflow/tasks/human.py b/joeflow/tasks/human.py index 1094d45..a82e45c 100644 --- a/joeflow/tasks/human.py +++ b/joeflow/tasks/human.py @@ -2,7 +2,7 @@ from django.views import generic -from joeflow.views import TaskViewMixin +from joeflow.views import StartViewMixin, TaskViewMixin __all__ = ( "StartView", @@ -10,7 +10,7 @@ ) -class StartView(TaskViewMixin, generic.CreateView): +class StartView(StartViewMixin, generic.CreateView): """ Start a new workflow by a human with a view. diff --git a/joeflow/views.py b/joeflow/views.py index 7f8ac2c..a66adb1 100644 --- a/joeflow/views.py +++ b/joeflow/views.py @@ -97,6 +97,25 @@ def create_task(self, workflow, prev_task): ) +class StartViewMixin(TaskViewMixin): + """ + View-mixin to create a start workflow. + + Example: + class MyStartWorkflowView(StartViewMixin, View): + def post(self, request, *args, **kwargs): + try: + data = json.loads(request.body) + workflow_id = self.start_workflow(data) + except Exception as e: + return HttpResponseBadRequest("Failed to start workflow") + + return JsonResponse({'message': 'Workflow started successfully.', 'id': workflow_id}, status=201) + """ + + model = None + + class WorkflowDetailView(WorkflowTemplateNameViewMixin, generic.DetailView): pass diff --git a/tests/fixtures/simpleworkflow.dot b/tests/fixtures/simpleworkflow.dot index 5253bcc..25ebeb5 100644 --- a/tests/fixtures/simpleworkflow.dot +++ b/tests/fixtures/simpleworkflow.dot @@ -5,7 +5,9 @@ digraph { "save the princess" [color=black fontcolor=black style="filled, rounded"] "start method" [color=black fontcolor=black style=filled] "start view" [color=black fontcolor=black style="filled, rounded"] + "custom start view" [color=black fontcolor=black style="filled, rounded"] "save the princess" -> end [color=black] "start method" -> "save the princess" [color=black] "start view" -> "save the princess" [color=black] + "custom start view" -> "save the princess" [color=black] } diff --git a/tests/fixtures/simpleworkflow_instance.dot b/tests/fixtures/simpleworkflow_instance.dot index ca04368..623f51c 100644 --- a/tests/fixtures/simpleworkflow_instance.dot +++ b/tests/fixtures/simpleworkflow_instance.dot @@ -5,7 +5,9 @@ digraph { "save the princess" [color=black fontcolor=black href="/simple/save_the_princess/2/" peripheries=1 style="filled, rounded, bold"] "start method" [color=black fontcolor=black peripheries=1 style=filled] "start view" [color="#888888" fontcolor="#888888" style="filled, rounded"] + "custom start view" [color="#888888" fontcolor="#888888" style="filled, rounded"] "save the princess" -> end [color="#888888"] "start method" -> "save the princess" [color=black] "start view" -> "save the princess" [color="#888888"] + "custom start view" -> "save the princess" [color="#888888"] } diff --git a/tests/test_models.py b/tests/test_models.py index d8801af..00f96b0 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -207,6 +207,7 @@ def test_urls(self): assert namespace == "simpleworkflow" names = {pattern.name for pattern in patterns} assert names == { + "custom_start_view", "save_the_princess", "start_view", "override", diff --git a/tests/testapp/workflows.py b/tests/testapp/workflows.py index c0427c2..bb97a83 100644 --- a/tests/testapp/workflows.py +++ b/tests/testapp/workflows.py @@ -1,8 +1,10 @@ from datetime import timedelta from django.core.mail import send_mail +from django.views import generic from joeflow import tasks +from joeflow.views import StartViewMixin from . import models from .views import UpdateWithPrevUserView @@ -40,8 +42,13 @@ class Meta: proxy = True +class CustomStartViewTaskView(StartViewMixin, generic.View): + pass + + class SimpleWorkflow(models.SimpleWorkflowState): start_view = tasks.StartView(fields="__all__", path="custom/postfix/") + custom_start_view = CustomStartViewTaskView() start_method = tasks.Start() save_the_princess = tasks.UpdateView(fields="__all__") @@ -50,6 +57,7 @@ def end(self): edges = ( (start_view, save_the_princess), + (custom_start_view, save_the_princess), (start_method, save_the_princess), (save_the_princess, end), )