run pyl.
This commit is contained in:
parent
b1568fb472
commit
a8fd0a246d
|
@ -18,13 +18,13 @@ def setup_database_uri(app: Flask) -> None:
|
|||
if app.config.get("SPIFFWORKFLOW_BACKEND_DATABASE_URI") is None:
|
||||
database_name = f"spiffworkflow_backend_{app.config['ENV_IDENTIFIER']}"
|
||||
if app.config.get("SPIFFWORKFLOW_BACKEND_DATABASE_TYPE") == "sqlite":
|
||||
app.config["SQLALCHEMY_DATABASE_URI"] = (
|
||||
f"sqlite:///{app.instance_path}/db_{app.config['ENV_IDENTIFIER']}.sqlite3"
|
||||
)
|
||||
app.config[
|
||||
"SQLALCHEMY_DATABASE_URI"
|
||||
] = f"sqlite:///{app.instance_path}/db_{app.config['ENV_IDENTIFIER']}.sqlite3"
|
||||
elif app.config.get("SPIFFWORKFLOW_BACKEND_DATABASE_TYPE") == "postgres":
|
||||
app.config["SQLALCHEMY_DATABASE_URI"] = (
|
||||
f"postgresql://spiffworkflow_backend:spiffworkflow_backend@localhost:5432/{database_name}"
|
||||
)
|
||||
app.config[
|
||||
"SQLALCHEMY_DATABASE_URI"
|
||||
] = f"postgresql://spiffworkflow_backend:spiffworkflow_backend@localhost:5432/{database_name}"
|
||||
else:
|
||||
# use pswd to trick flake8 with hardcoded passwords
|
||||
db_pswd = app.config.get("SPIFFWORKFLOW_BACKEND_DATABASE_PASSWORD")
|
||||
|
|
|
@ -127,9 +127,9 @@ class ProcessInstanceModel(SpiffworkflowBaseDBModel):
|
|||
def serialized_with_metadata(self) -> dict[str, Any]:
|
||||
process_instance_attributes = self.serialized
|
||||
process_instance_attributes["process_metadata"] = self.process_metadata
|
||||
process_instance_attributes["process_model_with_diagram_identifier"] = (
|
||||
self.process_model_with_diagram_identifier
|
||||
)
|
||||
process_instance_attributes[
|
||||
"process_model_with_diagram_identifier"
|
||||
] = self.process_model_with_diagram_identifier
|
||||
return process_instance_attributes
|
||||
|
||||
@property
|
||||
|
|
|
@ -5,6 +5,7 @@ import uuid
|
|||
from sys import exc_info
|
||||
from typing import Any
|
||||
from typing import Dict
|
||||
from typing import Generator
|
||||
from typing import Optional
|
||||
from typing import TypedDict
|
||||
from typing import Union
|
||||
|
@ -353,7 +354,7 @@ def task_show(process_instance_id: int, task_guid: str = "next") -> flask.wrappe
|
|||
return make_response(jsonify(task), 200)
|
||||
|
||||
|
||||
def _render_instructions_for_end_user(spiff_task: SpiffTask, task: Task):
|
||||
def _render_instructions_for_end_user(spiff_task: SpiffTask, task: Task) -> str:
|
||||
"""Assure any instructions for end user are processed for jinja syntax."""
|
||||
if task.properties and "instructionsForEndUser" in task.properties:
|
||||
if task.properties["instructionsForEndUser"]:
|
||||
|
@ -391,7 +392,7 @@ def process_data_show(
|
|||
)
|
||||
|
||||
|
||||
def _interstitial_stream(process_instance_id: int):
|
||||
def _interstitial_stream(process_instance_id: int) -> Generator[str, str, None]:
|
||||
process_instance = _find_process_instance_by_id_or_raise(process_instance_id)
|
||||
processor = ProcessInstanceProcessor(process_instance)
|
||||
reported_ids = [] # bit of an issue with end tasks showing as getting completed twice.
|
||||
|
@ -415,9 +416,8 @@ def _interstitial_stream(process_instance_id: int):
|
|||
processor.save() # Fixme - maybe find a way not to do this on every method?
|
||||
|
||||
|
||||
def interstitial(process_instance_id: int):
|
||||
"""A Server Side Events Stream for watching the execution of engine tasks in a
|
||||
process instance."""
|
||||
def interstitial(process_instance_id: int) -> Response:
|
||||
"""A Server Side Events Stream for watching the execution of engine tasks."""
|
||||
return Response(stream_with_context(_interstitial_stream(process_instance_id)), mimetype="text/event-stream")
|
||||
|
||||
|
||||
|
|
|
@ -433,9 +433,9 @@ class ProcessInstanceProcessor:
|
|||
tld.process_instance_id = process_instance_model.id
|
||||
|
||||
# we want this to be the fully qualified path to the process model including all group subcomponents
|
||||
current_app.config["THREAD_LOCAL_DATA"].process_model_identifier = (
|
||||
f"{process_instance_model.process_model_identifier}"
|
||||
)
|
||||
current_app.config[
|
||||
"THREAD_LOCAL_DATA"
|
||||
].process_model_identifier = f"{process_instance_model.process_model_identifier}"
|
||||
|
||||
self.process_instance_model = process_instance_model
|
||||
self.process_model_service = ProcessModelService()
|
||||
|
@ -595,9 +595,9 @@ class ProcessInstanceProcessor:
|
|||
bpmn_subprocess_definition.bpmn_identifier
|
||||
] = bpmn_process_definition_dict
|
||||
spiff_bpmn_process_dict["subprocess_specs"][bpmn_subprocess_definition.bpmn_identifier]["task_specs"] = {}
|
||||
bpmn_subprocess_definition_bpmn_identifiers[bpmn_subprocess_definition.id] = (
|
||||
bpmn_subprocess_definition.bpmn_identifier
|
||||
)
|
||||
bpmn_subprocess_definition_bpmn_identifiers[
|
||||
bpmn_subprocess_definition.id
|
||||
] = bpmn_subprocess_definition.bpmn_identifier
|
||||
|
||||
task_definitions = TaskDefinitionModel.query.filter(
|
||||
TaskDefinitionModel.bpmn_process_definition_id.in_( # type: ignore
|
||||
|
|
|
@ -267,8 +267,7 @@ class RunUntilServiceTaskExecutionStrategy(ExecutionStrategy):
|
|||
|
||||
|
||||
class RunUntilUserTaskOrMessageExecutionStrategy(ExecutionStrategy):
|
||||
"""When you want to run tasks until you hit something to report to the end user, or
|
||||
until there are no other engine steps to complete."""
|
||||
"""When you want to run tasks until you hit something to report to the end user."""
|
||||
|
||||
def get_engine_steps(self, bpmn_process_instance: BpmnWorkflow) -> List[SpiffTask]:
|
||||
return list(
|
||||
|
|
|
@ -1654,7 +1654,7 @@ class TestProcessApi(BaseTest):
|
|||
# a list. It tests all of our code. No reason to test Flasks SSE support.
|
||||
results = list(_interstitial_stream(process_instance_id))
|
||||
# strip the "data:" prefix and convert remaining string to dict.
|
||||
json_results = list(map(lambda x: json.loads(x[5:]), results))
|
||||
json_results = list(map(lambda x: json.loads(x[5:]), results)) # type: ignore
|
||||
# There should be 2 results back -
|
||||
# the first script task should not be returned (it contains no end user instructions)
|
||||
# The second script task should produce rendered jinja text
|
||||
|
@ -1675,10 +1675,10 @@ class TestProcessApi(BaseTest):
|
|||
|
||||
# we should now be on a task that does not belong to the original user, and the interstitial page should know this.
|
||||
results = list(_interstitial_stream(process_instance_id))
|
||||
json_results = list(map(lambda x: json.loads(x[5:]), results))
|
||||
json_results = list(map(lambda x: json.loads(x[5:]), results)) # type: ignore
|
||||
assert len(results) == 1
|
||||
assert json_results[0]["state"] == "READY"
|
||||
assert json_results[0]["can_complete"] == False
|
||||
assert json_results[0]["can_complete"] is False
|
||||
assert json_results[0]["title"] == "Please Approve"
|
||||
assert json_results[0]["properties"]["instructionsForEndUser"] == "I am a manual task in another lane"
|
||||
|
||||
|
@ -1692,7 +1692,7 @@ class TestProcessApi(BaseTest):
|
|||
list(_interstitial_stream(process_instance_id))
|
||||
list(_interstitial_stream(process_instance_id))
|
||||
results = list(_interstitial_stream(process_instance_id))
|
||||
json_results = list(map(lambda x: json.loads(x[5:]), results))
|
||||
json_results = list(map(lambda x: json.loads(x[5:]), results)) # type: ignore
|
||||
assert len(json_results) == 1
|
||||
assert json_results[0]["state"] == "COMPLETED"
|
||||
assert json_results[0]["properties"]["instructionsForEndUser"] == "I am the end task"
|
||||
|
|
|
@ -17,6 +17,7 @@ export default function ProcessInterstitial() {
|
|||
const [status, setStatus] = useState<string>('running');
|
||||
const params = useParams();
|
||||
const navigate = useNavigate();
|
||||
const userTasks = ['User Task', 'Manual Task'];
|
||||
|
||||
useEffect(() => {
|
||||
fetchEventSource(
|
||||
|
@ -35,7 +36,8 @@ export default function ProcessInterstitial() {
|
|||
},
|
||||
}
|
||||
);
|
||||
}, []);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []); // it is critical to only run this once.
|
||||
|
||||
useEffect(() => {
|
||||
// Added this seperate use effect so that the timer interval will be cleared if
|
||||
|
@ -43,7 +45,7 @@ export default function ProcessInterstitial() {
|
|||
if (
|
||||
lastTask &&
|
||||
lastTask.can_complete &&
|
||||
['User Task', 'Manual Task'].includes(lastTask.type)
|
||||
userTasks.includes(lastTask.type)
|
||||
) {
|
||||
const timerId = setInterval(() => {
|
||||
navigate(`/tasks/${lastTask.process_instance_id}/${lastTask.id}`);
|
||||
|
@ -57,14 +59,9 @@ export default function ProcessInterstitial() {
|
|||
if (status !== 'running') {
|
||||
setStatus(lastTask.state);
|
||||
}
|
||||
if (
|
||||
!lastTask.can_complete &&
|
||||
['User Task', 'Manual Task'].includes(lastTask.type)
|
||||
) {
|
||||
if (!lastTask.can_complete && userTasks.includes(lastTask.type)) {
|
||||
setStatus('LOCKED');
|
||||
}
|
||||
console.log(`Status is : ${status}}`);
|
||||
console.log('last task is : ', lastTask);
|
||||
switch (status) {
|
||||
case 'running':
|
||||
return (
|
||||
|
@ -87,10 +84,7 @@ export default function ProcessInterstitial() {
|
|||
};
|
||||
|
||||
const userMessage = (myTask: ProcessInstanceTask) => {
|
||||
if (
|
||||
!myTask.can_complete &&
|
||||
['User Task', 'Manual Task'].includes(myTask.type)
|
||||
) {
|
||||
if (!myTask.can_complete && userTasks.includes(myTask.type)) {
|
||||
return <div>This next task must be completed by a different person.</div>;
|
||||
}
|
||||
return (
|
||||
|
|
|
@ -1,12 +1,5 @@
|
|||
import { useEffect, useState } from 'react';
|
||||
import { Route, Routes, useLocation, useNavigate } from 'react-router-dom';
|
||||
import { Route, Routes } from 'react-router-dom';
|
||||
// @ts-ignore
|
||||
import { Tabs, TabList, Tab } from '@carbon/react';
|
||||
import TaskShow from './TaskShow';
|
||||
import MyTasks from './MyTasks';
|
||||
import GroupedTasks from './GroupedTasks';
|
||||
import CompletedInstances from './CompletedInstances';
|
||||
import CreateNewInstance from './CreateNewInstance';
|
||||
import ProcessInterstitial from './ProcessInterstitial';
|
||||
|
||||
export default function ProcessRoutes() {
|
||||
|
|
|
@ -13,7 +13,6 @@ import {
|
|||
ButtonSet,
|
||||
} from '@carbon/react';
|
||||
|
||||
import MDEditor from '@uiw/react-md-editor';
|
||||
// eslint-disable-next-line import/no-named-as-default
|
||||
import Form from '../themes/carbon';
|
||||
import HttpService from '../services/HttpService';
|
||||
|
@ -90,13 +89,6 @@ function TypeAheadWidget({
|
|||
);
|
||||
}
|
||||
|
||||
class UnexpectedHumanTaskType extends Error {
|
||||
constructor(message: string) {
|
||||
super(message);
|
||||
this.name = 'UnexpectedHumanTaskType';
|
||||
}
|
||||
}
|
||||
|
||||
enum FormSubmitType {
|
||||
Default,
|
||||
Draft,
|
||||
|
@ -108,16 +100,11 @@ export default function TaskShow() {
|
|||
const params = useParams();
|
||||
const navigate = useNavigate();
|
||||
const [disabled, setDisabled] = useState(false);
|
||||
const [refreshSeconds, setRefreshSeconds] = useState(0);
|
||||
|
||||
// save current form data so that we can avoid validations in certain situations
|
||||
const [currentFormObject, setCurrentFormObject] = useState<any>({});
|
||||
|
||||
const { addError, removeError } = useAPIError();
|
||||
|
||||
// eslint-disable-next-line sonarjs/no-duplicate-string
|
||||
const supportedHumanTaskTypes = ['User Task', 'Manual Task'];
|
||||
|
||||
const navigateToInterstitial = (myTask: ProcessInstanceTask) => {
|
||||
navigate(
|
||||
`/process/${modifyProcessIdentifierForPathParam(
|
||||
|
@ -361,12 +348,6 @@ export default function TaskShow() {
|
|||
Save as draft
|
||||
</Button>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<p>
|
||||
<i>Page will refresh in {refreshSeconds} seconds.</i>
|
||||
</p>
|
||||
);
|
||||
}
|
||||
reactFragmentToHideSubmitButton = (
|
||||
<ButtonSet>
|
||||
|
|
Loading…
Reference in New Issue