Changes sync

This commit is contained in:
Mikhail Podgurskiy
2023-07-10 16:33:40 +06:00
parent 743b1bf4f9
commit f74bbda314
6 changed files with 66 additions and 28 deletions

View File

@ -2,10 +2,13 @@
Changelog Changelog
========= =========
GIT VERSION 2.0.0.b5 2023-07-10
----------- -------------------
- Alow attach layout to forms in default form rendering template - Alow attach layout to forms in default form rendering template
- Fix subprocess node activation
- Added db indexes for workflow models
- Improve workflow REST API support
2.0.0.b4 2023-06-05 2.0.0.b4 2023-06-05
------------------- -------------------

View File

@ -179,17 +179,13 @@ modifications of Viewflow. You can find the commercial license terms in
## Changelog ## Changelog
2.0.0.b4 2023-06-05 2.0.0.b5 2023-07-10
------------------- -------------------
- New flow.SplitFirst Node - Alow attach layout to forms in default form rendering template
- New celery.Timer Node - Fix subprocess node activation
- Expose REST API with drf-spectacular - Added db indexes for workflow models
- Expose list_ordering_fields in a ModelViewset - Improve workflow REST API support
- Retain history and return to the Inbox/Queue list views after completing a flow task
- Enable smooth page transitions in Chrome/Safari
- Hotwire/Turbo integration for Django Admin with viewflow.contrib.admin app
- Resolved issue with viewflow.fsm reporting unmet condition messages

View File

@ -4,7 +4,7 @@ README = open("README.md", "r", encoding="utf-8").read()
setuptools.setup( setuptools.setup(
name="django-viewflow", name="django-viewflow",
version="2.0.0b4", version="2.0.0b5",
author_email="kmmbvnr@gmail.com", author_email="kmmbvnr@gmail.com",
author="Mikhail Podgurskiy", author="Mikhail Podgurskiy",
description="Reusable library to build business applications fast", description="Reusable library to build business applications fast",

View File

@ -34,7 +34,11 @@ class DashboardView(
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
sorted_nodes, _ = chart.topsort(self.flow_class) sorted_nodes, _ = chart.topsort(self.flow_class)
nodes = [node for node in sorted_nodes if node.task_type in ["HUMAN", "JOB"]] nodes = [
node
for node in sorted_nodes
if node.task_type in ["HUMAN", "JOB", "SUBPROCESS"]
]
start_nodes = [ start_nodes = [
{"node": node, "can_execute": node.can_execute(self.request.user)} {"node": node, "can_execute": node.can_execute(self.request.user)}

View File

@ -8,6 +8,7 @@ from django.db.models.constants import LOOKUP_SEP
from django.db.models.query import ModelIterable from django.db.models.query import ModelIterable
from .status import STATUS from .status import STATUS
from .utils import get_next_process_task
def _available_flows(flow_classes, user): def _available_flows(flow_classes, user):
@ -257,22 +258,28 @@ class TaskQuerySet(QuerySet):
Prefer assigned tasks first, if not, return first task from user queue Prefer assigned tasks first, if not, return first task from user queue
""" """
# first try to find an assigned task # task inside a same process
task = self.filter(process=process, owner=user, status=STATUS.ASSIGNED).first() task = get_next_process_task(self, process, user)
# lookup for a task in a queue # task inside subprocess
if task is None: if task is None:
task = ( subprocess_task = self.filter(process__parent_task__process=process).first()
self.user_queue(user).filter(process=process, status=STATUS.NEW).first() if subprocess_task:
) task = get_next_process_task(self, subprocess_task.process, user)
# lookup for a job # task inside parent process
if task is None: if task is None and process.parent_task_id:
task = ( task = get_next_process_task(self, process.parent_task.process, user)
self.filter(process=process, flow_task_type='JOB', status__in=[
STATUS.NEW, STATUS.SCHEDULED, STATUS.STARTED # task inside other subprocesses of parent task
]).first() if task is None and process.parent_task_id:
) processes = process.__class__._default_manager.filter(
parent_task__process=process.parent_task.process
).exclude(pk=process.pk)
for sub_process in processes:
task = get_next_process_task(self, sub_process, user)
if task:
break
return task return task

View File

@ -1,20 +1,48 @@
from .status import STATUS
class Act(object): class Act(object):
"""Shortcut to access activation data.""" """Shortcut to access activation data."""
@property @property
def process(self): def process(self):
"""Shortcut for lambda activation: activation.process...)""" """Shortcut for lambda activation: activation.process...)"""
class Lookup(object): class Lookup(object):
def __getattribute__(self, name): def __getattribute__(self, name):
return lambda activation: getattr(activation.process, name) return lambda activation: getattr(activation.process, name)
return Lookup() return Lookup()
@property @property
def task(self): def task(self):
"""Shortcut for lambda activation: activation.task...)""" """Shortcut for lambda activation: activation.task...)"""
class Lookup(object): class Lookup(object):
def __getattribute__(self, name): def __getattribute__(self, name):
return lambda activation: getattr(activation.task, name) return lambda activation: getattr(activation.task, name)
return Lookup() return Lookup()
act = Act() act = Act()
def get_next_process_task(manager, process, user):
task = manager.filter(process=process, owner=user, status=STATUS.ASSIGNED).first()
# lookup for a task in a queue
if task is None:
task = (
manager.user_queue(user).filter(process=process, status=STATUS.NEW).first()
)
# lookup for a job
if task is None:
task = manager.filter(
process=process,
flow_task_type="JOB",
status__in=[STATUS.NEW, STATUS.SCHEDULED, STATUS.STARTED],
).first()
return task