Merge branch 'main' of github.com:sartography/spiff-arena into main
|
@ -1,48 +0,0 @@
|
|||
# BPMN Unit Tests
|
||||
|
||||
Software Engineers test their code.
|
||||
With this feature, BPMN authors can test their creations, too.
|
||||
These tests can provide you with faster feedback than you would get by simply running your process model, and they allow you to mock out form input and service task connections as well as provide specific input to exercise different branches of your process model.
|
||||
BPMN unit tests are designed to give you greater confidence that your process models will work as designed when they are run in the wild, both the first time they are used by real users and also after you make changes to them.
|
||||
|
||||
## Creating BPMN Unit Tests
|
||||
|
||||
First, create a process model that you want to test.
|
||||
Navigate to the process model and add a JSON file based on the name of one of the BPMN files.
|
||||
For example, if you have a process model that includes a file called `awesome_script_task.bpmn`, your test JSON file would be called `test_awesome_script_task.json`.
|
||||
If you have multiple BPMN files you want to test, you can have multiple test JSON files.
|
||||
The BPMN files you test do not have to be marked as the primary file for the process model in question.
|
||||
The structure of your json should be as follows:
|
||||
|
||||
{
|
||||
"test_case_1": {
|
||||
"tasks": {
|
||||
"ServiceTaskProcess:service_task_one": {
|
||||
"data": [{ "the_result": "result_from_service" }]
|
||||
}
|
||||
},
|
||||
"expected_output_json": { "the_result": "result_from_service" }
|
||||
}
|
||||
}
|
||||
|
||||
The top-level keys should be names of unit tests.
|
||||
In this example, the unit test is named "test_case_1."
|
||||
Under that, you can specify "tasks" and "expected_output_json."
|
||||
|
||||
Under "tasks," each key is the BPMN id of a specific task.
|
||||
If you are testing a file that uses Call Activities and therefore calls other processes, there can be conflicting BPMN ids.
|
||||
In this case, you can specify the unique activity by prepending the Process id (in the above example, that is "ServiceTaskProcess").
|
||||
For simple processes, "service_task_one" (for example) would be sufficient as the BPMN id.
|
||||
For User Tasks, the "data" (under a specific task) represents the data that will be entered by the user in the form.
|
||||
For Service Tasks, the data represents the data that will be returned by the service.
|
||||
Note that all User Tasks and Service Tasks must have their BPMN ids mentioned in the JSON file (with mock task data as desired), since otherwise we won't know what to do when the flow arrives at these types of tasks.
|
||||
|
||||
The "expected_output_json" represents the state of the task data that you expect when the process completes.
|
||||
When the test is run, if the actual task data differs from this expectation, the test will fail.
|
||||
The test will also fail if the process never completes or if an error occurs.
|
||||
|
||||
## Running BPMN Unit Tests
|
||||
|
||||
Go to a process model and either click “Run Unit Tests” to run all tests for the process model or click on the “play icon” next to a "test_something.json" file.
|
||||
Then you will get a green check mark or a red x.
|
||||
You can click on these colored icons to get more details about the passing or failing test.
|
Before Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 2.0 KiB |
Before Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 449 B |
After Width: | Height: | Size: 561 B |
After Width: | Height: | Size: 400 B |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 2.8 KiB |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 2.5 KiB |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 1.8 KiB |
After Width: | Height: | Size: 4.2 KiB |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 1.0 KiB |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 2.8 KiB |
After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 2.6 KiB |
After Width: | Height: | Size: 1.8 KiB |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 2.3 KiB |
After Width: | Height: | Size: 1.5 KiB |
|
@ -15,19 +15,36 @@ BPMN (Business Process Model and Notation) elements are the building blocks used
|
|||
### Tasks
|
||||
Tasks represent activities or work that needs to be performed as part of a process. They can be manual tasks that require human intervention or automated tasks that are executed by systems or applications.
|
||||
|
||||
| **Element** | **Symbol** | **Description** |
|
||||
| **Task** | **Symbol** | **Description** |
|
||||
|---------------|------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| Service | <div style="width:100px"></div> ![Untitled](images/04-BPMN-Service-Task.png) | Task that uses a Web service, an automated application, or other kinds of service in completing the task. |
|
||||
| Send | <div style="width:100px"></div>![Untitled](images/06-BPMN-Send-Task.png) | Task that sends a Message to another pool. The Task is completed once the Message has been sent. |
|
||||
| Receive | <div style="width:100px"></div>![Untitled](images/23-BPMN-Receive-Task.png) | A Receive Task indicates that the process has to wait for a message to arrive in order to continue. The Task is completed once the message has received. |
|
||||
| User | ![Untitled](images/08-BPMN-User-Task.png) | A User Task represents that a human performer performs the Task with the use of a software application. |
|
||||
| Manual | ![Untitled](images/10-BPMN-Manual-Task.png) | A Manual Task is a Task that is performed without the aid of any business process execution engine or any application. |
|
||||
| Business Rule | ![Untitled](images/12-BPMN-Business-Rule-Task.png) | Business Rule Task is newly added in BPMN 2.0. It provides a mechanism for a process to provide input to a Business Rules Engine and then obtain the output provided by the Business Rules Engine. |
|
||||
| Script | ![Untitled](images/14-BPMN-Script-Task.png) | A Script Task is executed by a business process engine. The task defines a script that the engine can interpret. | |
|
||||
| Service |<div style="width:70px; height:10px"></div>![Untitled](images/Service-tasks.png) | Task that uses a Web service, an automated application, or other kinds of service in completing the task. |
|
||||
| Send |![Untitled](images/Send_task.png) | Task that sends a Message to another pool. The Task is completed once the Message has been sent. |
|
||||
| Receive |<div style="width:70px; height:10px"></div> ![Untitled](images/Receive_task.png) | A Receive Task indicates that the process has to wait for a message to arrive in order to continue. The Task is completed once the| message has received. |
|
||||
| User | <div style="width:70px; height:10px"></div> ![Untitled](images/Users_task.png) | A User Task represents that a human performer performs the Task with the use of a software application. |
|
||||
| Manual |<div style="width:70px; height:10px"></div> ![Untitled](images/Manual_task.png) | A Manual Task is a Task that is performed without the aid of any business process execution engine or any application. |
|
||||
| Business Rule |<div style="width:70px; height:10px"></div> ![Untitled](images/Business-rule-tasks.png) | Business Rule Task provides a mechanism for a process to provide input to a Business Rules Engine and then obtain the output provided by the Business Rules Engine. |
|
||||
| Script | <div style="width:70px; height:10px"></div>![Untitled](images/Script-tasks.png) | A Script Task defines a script that the engine can interpret. | |
|
||||
|
||||
### Events
|
||||
Events, represented with circles, describe something that happens during the course of a process. There are three main events within business process modeling: start events, intermediate events, and end events.
|
||||
|
||||
| **Event** | **Symbol**| **Description** |
|
||||
|---------------|-----------|-----------------|
|
||||
| Start Event |![Untitled](images/Start_Event.png) | Signals the first step of a process |
|
||||
| Intermediate Event | ![Untitled](images/Intermdiate.png) | Represents any event that occurs between a start and end event. |
|
||||
| End event | ![Untitled](images/End_Event.png) | Signals the final step in a process. |
|
||||
|
||||
### Gateways
|
||||
Gateways represent decision points in a process. They determine which path the process will take based on certain conditions or rules. There are different types of gateways, such as exclusive gateways (XOR), inclusive gateways (OR), and parallel gateways (AND).
|
||||
Gateways represent decision points in a process. They determine which path the process will take based on certain conditions or rules. There are different types of gateways:
|
||||
|
||||
| **Gateway** | **Symbol**| **Description** |
|
||||
|---------------|-----------|-----------------|
|
||||
| Exclusive gateway |![Untitled](images/Exclusive_Gateway.png) | Evaluates the state of the business process and, based on the condition, breaks the flow into one or more mutually exclusive paths |
|
||||
| Event-based gateway | ![Untitled](images/Event_Gateway.png) | An event-based gateway is similar to an exclusive gateway both involve one path in the flow. In the case of an event-based gateway, however, you evaluate which event has occurred, not which condition has been met. |
|
||||
| Parallel gateway | ![Untitled](images/Parallet_gateway.png) | Parallel gateways are used to represent two tasks in a business flow. A parallel gateway is used to visualize the concurrent execution of activities. |
|
||||
| Inclusive gateway | ![Untitled](images/Inclusive_Gateway.png) | An inclusive gateway breaks the process flow into one or more flows. |
|
||||
| Complex gateway | ![Untitled](images/Complex_Gateway.png) | complex gateways are only used for the most complex flows in the business process. They use words in place of symbols and, therefore, require more descriptive text. |
|
||||
| |
|
||||
|
||||
### Flows
|
||||
Flows represent the sequence or direction of activities in a process. There are different types of flows in BPMN, including sequence flows, message flows, and association flows. Sequence flows indicate the order in which tasks are performed, message flows represent the exchange of messages between participants, and association flows connect data objects or artifacts to activities.
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
.wy-table-responsive table td {
|
||||
white-space: normal !important;
|
||||
}
|
||||
|
||||
.wy-table-responsive {
|
||||
overflow: visible !important;
|
||||
}
|
||||
|
||||
html.writer-html5 .rst-content table.docutils td>p, html.writer-html5 .rst-content table.docutils th>p {
|
||||
line-height: 1.5rem;
|
||||
}
|
|
@ -19,6 +19,8 @@ if [[ "${RUN_WITH_DAEMON:-}" != "false" ]]; then
|
|||
additional_args="${additional_args} -d"
|
||||
fi
|
||||
|
||||
docker --version
|
||||
|
||||
docker compose --profile "$SPIFFWORKFLOW_BACKEND_DOCKER_COMPOSE_PROFILE" build
|
||||
docker compose --profile "$SPIFFWORKFLOW_BACKEND_DOCKER_COMPOSE_PROFILE" stop
|
||||
|
||||
|
@ -37,4 +39,7 @@ if [[ "${SPIFFWORKFLOW_BACKEND_RECREATE_DATABASE:-}" == "true" ]]; then
|
|||
docker volume rm spiffworkflow-backend_spiffworkflow_backend || echo 'docker volume not found'
|
||||
fi
|
||||
|
||||
# docker compose isn't automatically pulling the image in ci so do it explicitly with docker
|
||||
docker pull mysql:8.0.29
|
||||
|
||||
docker compose --profile "$SPIFFWORKFLOW_BACKEND_DOCKER_COMPOSE_PROFILE" up --wait $additional_args
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
furo==2022.9.29
|
||||
furo==2023.5.20
|
||||
sphinx==5.3.0
|
||||
sphinx-click==4.3.0
|
||||
sphinx-click==4.4.0
|
||||
|
|
|
@ -2385,7 +2385,7 @@ lxml = "*"
|
|||
type = "git"
|
||||
url = "https://github.com/sartography/SpiffWorkflow"
|
||||
reference = "main"
|
||||
resolved_reference = "01a25fc3f829786c4b65d19fd0fda408de37c79f"
|
||||
resolved_reference = "efcdcf545c861d58cfae92ad070b3208ef6028db"
|
||||
|
||||
[[package]]
|
||||
name = "sqlalchemy"
|
||||
|
|
|
@ -168,6 +168,7 @@ explicit_package_bases = false
|
|||
[tool.ruff]
|
||||
select = [
|
||||
"B", # flake8-bugbear
|
||||
"C", # mccabe
|
||||
"E", # pycodestyle error
|
||||
# "ERA", # eradicate
|
||||
"F", # pyflakes
|
||||
|
@ -180,6 +181,7 @@ select = [
|
|||
]
|
||||
|
||||
ignore = [
|
||||
"C901", # "complexity" category
|
||||
"PLR", # "refactoring" category has "too many lines in method" type stuff
|
||||
"PLC1901",
|
||||
"PLE1205" # saw this Too many arguments for `logging` format string give a false positive once
|
||||
|
|
|
@ -278,9 +278,7 @@ def task_show(process_instance_id: int, task_guid: str = "next") -> flask.wrappe
|
|||
|
||||
can_complete = False
|
||||
try:
|
||||
AuthorizationService.assert_user_can_complete_task(
|
||||
process_instance.id, task_definition.bpmn_identifier, g.user
|
||||
)
|
||||
AuthorizationService.assert_user_can_complete_task(process_instance.id, task_model.guid, g.user)
|
||||
can_complete = True
|
||||
except HumanTaskNotFoundError:
|
||||
can_complete = False
|
||||
|
@ -440,7 +438,7 @@ def _interstitial_stream(process_instance: ProcessInstanceModel) -> Generator[st
|
|||
|
||||
|
||||
def get_ready_engine_step_count(bpmn_process_instance: BpmnWorkflow) -> int:
|
||||
return len(list([t for t in bpmn_process_instance.get_tasks(TaskState.READY) if not t.task_spec.manual]))
|
||||
return len([t for t in bpmn_process_instance.get_tasks(TaskState.READY) if not t.task_spec.manual])
|
||||
|
||||
|
||||
def _dequeued_interstitial_stream(process_instance_id: int) -> Generator[str | None, str | None, None]:
|
||||
|
@ -483,7 +481,7 @@ def _task_submit_shared(
|
|||
|
||||
processor = ProcessInstanceProcessor(process_instance)
|
||||
spiff_task = _get_spiff_task_from_process_instance(task_guid, process_instance, processor=processor)
|
||||
AuthorizationService.assert_user_can_complete_task(process_instance.id, spiff_task.task_spec.name, principal.user)
|
||||
AuthorizationService.assert_user_can_complete_task(process_instance.id, str(spiff_task.id), principal.user)
|
||||
|
||||
if spiff_task.state != TaskState.READY:
|
||||
raise (
|
||||
|
|
|
@ -77,6 +77,7 @@ PATH_SEGMENTS_FOR_PERMISSION_ALL = [
|
|||
{"path": "/process-instance-terminate", "relevant_permissions": ["create"]},
|
||||
{"path": "/process-model-natural-language", "relevant_permissions": ["create"]},
|
||||
{"path": "/process-model-publish", "relevant_permissions": ["create"]},
|
||||
{"path": "/process-model-tests", "relevant_permissions": ["create"]},
|
||||
{"path": "/task-data", "relevant_permissions": ["read", "update"]},
|
||||
]
|
||||
|
||||
|
@ -335,24 +336,23 @@ class AuthorizationService:
|
|||
@staticmethod
|
||||
def assert_user_can_complete_task(
|
||||
process_instance_id: int,
|
||||
task_bpmn_identifier: str,
|
||||
task_guid: str,
|
||||
user: UserModel,
|
||||
) -> bool:
|
||||
human_task = HumanTaskModel.query.filter_by(
|
||||
task_name=task_bpmn_identifier,
|
||||
task_id=task_guid,
|
||||
process_instance_id=process_instance_id,
|
||||
completed=False,
|
||||
).first()
|
||||
if human_task is None:
|
||||
raise HumanTaskNotFoundError(
|
||||
f"Could find an human task with task name '{task_bpmn_identifier}'"
|
||||
f" for process instance '{process_instance_id}'"
|
||||
f"Could find an human task with task guid '{task_guid}' for process instance '{process_instance_id}'"
|
||||
)
|
||||
|
||||
if user not in human_task.potential_owners:
|
||||
raise UserDoesNotHaveAccessToTaskError(
|
||||
f"User {user.username} does not have access to update"
|
||||
f" task'{task_bpmn_identifier}' for process instance"
|
||||
f" task'{task_guid}' for process instance"
|
||||
f" '{process_instance_id}'"
|
||||
)
|
||||
return True
|
||||
|
@ -534,6 +534,9 @@ class AuthorizationService:
|
|||
|
||||
# read comes from PG and PM permissions
|
||||
permissions_to_assign.append(PermissionToAssign(permission="update", target_uri="/task-data/*"))
|
||||
permissions_to_assign.append(PermissionToAssign(permission="read", target_uri="/task-data/*"))
|
||||
permissions_to_assign.append(PermissionToAssign(permission="read", target_uri="/process-data/*"))
|
||||
permissions_to_assign.append(PermissionToAssign(permission="read", target_uri="/process-data-file-download/*"))
|
||||
|
||||
for permission in ["create", "read", "update", "delete"]:
|
||||
permissions_to_assign.append(PermissionToAssign(permission=permission, target_uri="/process-instances/*"))
|
||||
|
|
|
@ -36,4 +36,4 @@ class ProcessCallerService:
|
|||
.filter(ProcessCallerCacheModel.process_identifier == process_id)
|
||||
.all()
|
||||
)
|
||||
return list(set(map(lambda r: r.calling_process_identifier, records))) # type: ignore
|
||||
return list({r.calling_process_identifier for r in records})
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
# TODO: clean up this service for a clear distinction between it and the process_instance_service
|
||||
# where this points to the pi service
|
||||
import decimal
|
||||
import uuid
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
import time
|
||||
import uuid
|
||||
from collections.abc import Callable
|
||||
from datetime import datetime
|
||||
from datetime import timedelta
|
||||
|
@ -134,7 +134,7 @@ class BoxedTaskDataBasedScriptEngineEnvironment(BoxedTaskDataEnvironment): # ty
|
|||
return {}
|
||||
|
||||
def last_result(self) -> dict[str, Any]:
|
||||
return {k: v for k, v in self._last_result.items()}
|
||||
return dict(self._last_result.items())
|
||||
|
||||
def clear_state(self) -> None:
|
||||
pass
|
||||
|
@ -212,7 +212,7 @@ class NonTaskDataBasedScriptEngineEnvironment(BasePythonScriptEngineEnvironment)
|
|||
return {k: v for k, v in self.state.items() if k not in keys_to_filter and not callable(v)}
|
||||
|
||||
def last_result(self) -> dict[str, Any]:
|
||||
return {k: v for k, v in self.state.items()}
|
||||
return dict(self.state.items())
|
||||
|
||||
def clear_state(self) -> None:
|
||||
self.state = {}
|
||||
|
@ -1556,7 +1556,16 @@ class ProcessInstanceProcessor:
|
|||
task_guid=task_model.guid,
|
||||
user_id=user.id,
|
||||
)
|
||||
task_service.process_parents_and_children_and_save_to_database(spiff_task)
|
||||
|
||||
# children of a multi-instance task has the attribute "triggered" set to True
|
||||
# so use that to determine if a spiff_task is apart of a multi-instance task
|
||||
# and therefore we need to process its parent since the current task will not
|
||||
# know what is actually going on.
|
||||
# Basically "triggered" means "this task is not part of the task spec outputs"
|
||||
spiff_task_to_process = spiff_task
|
||||
if spiff_task_to_process.triggered is True:
|
||||
spiff_task_to_process = spiff_task.parent
|
||||
task_service.process_parents_and_children_and_save_to_database(spiff_task_to_process)
|
||||
|
||||
# this is the thing that actually commits the db transaction (on behalf of the other updates above as well)
|
||||
self.save()
|
||||
|
|
|
@ -426,7 +426,7 @@ class ProcessInstanceService:
|
|||
data: dict[str, Any],
|
||||
user: UserModel,
|
||||
) -> None:
|
||||
AuthorizationService.assert_user_can_complete_task(process_instance.id, spiff_task.task_spec.name, user)
|
||||
AuthorizationService.assert_user_can_complete_task(process_instance.id, str(spiff_task.id), user)
|
||||
cls.save_file_data_and_replace_with_digest_references(
|
||||
data,
|
||||
process_instance.id,
|
||||
|
@ -521,7 +521,7 @@ class ProcessInstanceService:
|
|||
can_complete = False
|
||||
try:
|
||||
AuthorizationService.assert_user_can_complete_task(
|
||||
processor.process_instance_model.id, spiff_task.task_spec.name, g.user
|
||||
processor.process_instance_model.id, str(spiff_task.id), g.user
|
||||
)
|
||||
can_complete = True
|
||||
except HumanTaskNotFoundError:
|
||||
|
|
|
@ -126,7 +126,7 @@ class ProcessModelTestRunnerMostlyPureSpiffDelegate(ProcessModelTestRunnerDelega
|
|||
spiff_task.run()
|
||||
|
||||
def get_next_task(self, bpmn_process_instance: BpmnWorkflow) -> SpiffTask | None:
|
||||
ready_tasks = list([t for t in bpmn_process_instance.get_tasks(TaskState.READY)])
|
||||
ready_tasks = list(bpmn_process_instance.get_tasks(TaskState.READY))
|
||||
if len(ready_tasks) > 0:
|
||||
return ready_tasks[0]
|
||||
return None
|
||||
|
|
|
@ -455,7 +455,7 @@ class TaskService:
|
|||
) -> None:
|
||||
"""Update given spiff tasks in the database and remove deleted tasks."""
|
||||
# Remove all the deleted/pruned tasks from the database.
|
||||
deleted_task_guids = list(map(lambda t: str(t.id), deleted_spiff_tasks))
|
||||
deleted_task_guids = [str(t.id) for t in deleted_spiff_tasks]
|
||||
tasks_to_clear = TaskModel.query.filter(TaskModel.guid.in_(deleted_task_guids)).all() # type: ignore
|
||||
human_tasks_to_clear = HumanTaskModel.query.filter(
|
||||
HumanTaskModel.task_id.in_(deleted_task_guids) # type: ignore
|
||||
|
|
|
@ -91,7 +91,7 @@ class ExecutionStrategy:
|
|||
self.delegate.save(bpmn_process_instance)
|
||||
|
||||
def get_ready_engine_steps(self, bpmn_process_instance: BpmnWorkflow) -> list[SpiffTask]:
|
||||
tasks = list([t for t in bpmn_process_instance.get_tasks(TaskState.READY) if not t.task_spec.manual])
|
||||
tasks = [t for t in bpmn_process_instance.get_tasks(TaskState.READY) if not t.task_spec.manual]
|
||||
|
||||
if len(tasks) > 0:
|
||||
self.subprocess_spec_loader()
|
||||
|
|
|
@ -15,11 +15,6 @@ class WorkflowService:
|
|||
@classmethod
|
||||
def next_start_event_configuration(cls, workflow: BpmnWorkflow, now_in_utc: datetime) -> StartConfiguration | None:
|
||||
start_events = cls.future_start_events(workflow)
|
||||
configurations = list(
|
||||
map(
|
||||
lambda start_event: start_event.task_spec.configuration(start_event, now_in_utc), # type: ignore
|
||||
start_events,
|
||||
)
|
||||
)
|
||||
configurations = [start_event.task_spec.configuration(start_event, now_in_utc) for start_event in start_events]
|
||||
configurations.sort(key=lambda configuration: configuration[1]) # type: ignore
|
||||
return configurations[0] if len(configurations) > 0 else None
|
||||
|
|
|
@ -51,7 +51,7 @@ class BaseTest:
|
|||
|
||||
@staticmethod
|
||||
def logged_in_headers(user: UserModel, _redirect_url: str = "http://some/frontend/url") -> dict[str, str]:
|
||||
return dict(Authorization="Bearer " + user.encode_auth_token())
|
||||
return {"Authorization": "Bearer " + user.encode_auth_token()}
|
||||
|
||||
def create_group_and_model_with_bpmn(
|
||||
self,
|
||||
|
|
|
@ -1725,7 +1725,7 @@ class TestProcessApi(BaseTest):
|
|||
stream_results = _dequeued_interstitial_stream(process_instance_id)
|
||||
results = list(stream_results)
|
||||
# strip the "data:" prefix and convert remaining string to dict.
|
||||
json_results = list(map(lambda x: json.loads(x[5:]), results)) # type: ignore
|
||||
json_results = [json.loads(x[5:]) for x in 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
|
||||
|
@ -1746,7 +1746,7 @@ 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(_dequeued_interstitial_stream(process_instance_id))
|
||||
json_results = list(map(lambda x: json.loads(x[5:]), results)) # type: ignore
|
||||
json_results = [json.loads(x[5:]) for x in results] # type: ignore
|
||||
assert len(results) == 1
|
||||
assert json_results[0]["task"]["state"] == "READY"
|
||||
assert json_results[0]["task"]["can_complete"] is False
|
||||
|
@ -1760,7 +1760,7 @@ class TestProcessApi(BaseTest):
|
|||
processor.save()
|
||||
|
||||
results = list(_dequeued_interstitial_stream(process_instance_id))
|
||||
json_results = list(map(lambda x: json.loads(x[5:]), results)) # type: ignore
|
||||
json_results = [json.loads(x[5:]) for x in results] # type: ignore
|
||||
assert len(results) == 1
|
||||
assert json_results[0]["task"]["state"] == "READY"
|
||||
assert json_results[0]["task"]["can_complete"] is False
|
||||
|
@ -1777,7 +1777,7 @@ class TestProcessApi(BaseTest):
|
|||
list(_dequeued_interstitial_stream(process_instance_id))
|
||||
list(_dequeued_interstitial_stream(process_instance_id))
|
||||
results = list(_dequeued_interstitial_stream(process_instance_id))
|
||||
json_results = list(map(lambda x: json.loads(x[5:]), results)) # type: ignore
|
||||
json_results = [json.loads(x[5:]) for x in results] # type: ignore
|
||||
assert len(json_results) == 1
|
||||
assert json_results[0]["task"]["state"] == "COMPLETED"
|
||||
assert json_results[0]["task"]["properties"]["instructionsForEndUser"] == "I am the end task"
|
||||
|
|
|
@ -131,6 +131,7 @@ class TestAuthorizationService(BaseTest):
|
|||
("/process-instances/some-process-group:some-process-model:*", "read"),
|
||||
("/process-model-natural-language/some-process-group:some-process-model:*", "create"),
|
||||
("/process-model-publish/some-process-group:some-process-model:*", "create"),
|
||||
("/process-model-tests/some-process-group:some-process-model:*", "create"),
|
||||
("/process-models/some-process-group:some-process-model:*", "create"),
|
||||
("/process-models/some-process-group:some-process-model:*", "delete"),
|
||||
("/process-models/some-process-group:some-process-model:*", "read"),
|
||||
|
@ -214,6 +215,7 @@ class TestAuthorizationService(BaseTest):
|
|||
("/process-instances/some-process-group:some-process-model/*", "read"),
|
||||
("/process-model-natural-language/some-process-group:some-process-model/*", "create"),
|
||||
("/process-model-publish/some-process-group:some-process-model/*", "create"),
|
||||
("/process-model-tests/some-process-group:some-process-model/*", "create"),
|
||||
("/process-models/some-process-group:some-process-model/*", "create"),
|
||||
("/process-models/some-process-group:some-process-model/*", "delete"),
|
||||
("/process-models/some-process-group:some-process-model/*", "read"),
|
||||
|
@ -311,6 +313,8 @@ class TestAuthorizationService(BaseTest):
|
|||
("/debug/*", "create"),
|
||||
("/messages", "read"),
|
||||
("/messages/*", "create"),
|
||||
("/process-data-file-download/*", "read"),
|
||||
("/process-data/*", "read"),
|
||||
("/process-instance-reset/*", "create"),
|
||||
("/process-instance-resume/*", "create"),
|
||||
("/process-instance-suspend/*", "create"),
|
||||
|
@ -326,6 +330,7 @@ class TestAuthorizationService(BaseTest):
|
|||
("/send-event/*", "create"),
|
||||
("/task-complete/*", "create"),
|
||||
("/task-data/*", "update"),
|
||||
("/task-data/*", "read"),
|
||||
]
|
||||
)
|
||||
permissions_to_assign = AuthorizationService.explode_permissions("all", "ELEVATED")
|
||||
|
|
|
@ -35,7 +35,6 @@
|
|||
"@uiw/react-md-editor": "^3.20.2",
|
||||
"autoprefixer": "10.4.8",
|
||||
"axios": "^0.27.2",
|
||||
"bootstrap": "^5.2.0",
|
||||
"bpmn-js": "^13.0.0",
|
||||
"bpmn-js-properties-panel": "^1.22.0",
|
||||
"bpmn-js-spiffworkflow": "github:sartography/bpmn-js-spiffworkflow#main",
|
||||
|
@ -51,8 +50,6 @@
|
|||
"keycloak-js": "^18.0.1",
|
||||
"prop-types": "^15.8.1",
|
||||
"react": "^18.2.0",
|
||||
"react-bootstrap": "^2.5.0",
|
||||
"react-bootstrap-typeahead": "^6.0.0",
|
||||
"react-datepicker": "^4.8.0",
|
||||
"react-devtools": "^4.27.1",
|
||||
"react-dom": "^18.2.0",
|
||||
|
@ -4967,17 +4964,6 @@
|
|||
"url": "https://opencollective.com/popperjs"
|
||||
}
|
||||
},
|
||||
"node_modules/@react-aria/ssr": {
|
||||
"version": "3.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@react-aria/ssr/-/ssr-3.6.0.tgz",
|
||||
"integrity": "sha512-OFiYQdv+Yk7AO7IsQu/fAEPijbeTwrrEYvdNoJ3sblBBedD5j5fBTNWrUPNVlwC4XWWnWTCMaRIVsJujsFiWXg==",
|
||||
"dependencies": {
|
||||
"@swc/helpers": "^0.4.14"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@react-icons/all-files": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@react-icons/all-files/-/all-files-4.1.0.tgz",
|
||||
|
@ -4994,37 +4980,6 @@
|
|||
"node": ">=14"
|
||||
}
|
||||
},
|
||||
"node_modules/@restart/hooks": {
|
||||
"version": "0.4.9",
|
||||
"resolved": "https://registry.npmjs.org/@restart/hooks/-/hooks-0.4.9.tgz",
|
||||
"integrity": "sha512-3BekqcwB6Umeya+16XPooARn4qEPW6vNvwYnlofIYe6h9qG1/VeD7UvShCWx11eFz5ELYmwIEshz+MkPX3wjcQ==",
|
||||
"dependencies": {
|
||||
"dequal": "^2.0.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=16.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@restart/ui": {
|
||||
"version": "1.6.3",
|
||||
"resolved": "https://registry.npmjs.org/@restart/ui/-/ui-1.6.3.tgz",
|
||||
"integrity": "sha512-7HM5aiSWvJBWr+FghZj/n3PSuH2kUrOPiu/D92aIv1zTL8IBwFoQ3oz/f76svoN5v2PKaP6pQbg6vTcIiSffzg==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.21.0",
|
||||
"@popperjs/core": "^2.11.6",
|
||||
"@react-aria/ssr": "^3.5.0",
|
||||
"@restart/hooks": "^0.4.9",
|
||||
"@types/warning": "^3.0.0",
|
||||
"dequal": "^2.0.3",
|
||||
"dom-helpers": "^5.2.0",
|
||||
"uncontrollable": "^7.2.1",
|
||||
"warning": "^4.0.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=16.14.0",
|
||||
"react-dom": ">=16.14.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@rjsf/core": {
|
||||
"version": "5.0.0-beta.20",
|
||||
"resolved": "https://registry.npmjs.org/@rjsf/core/-/core-5.0.0-beta.20.tgz",
|
||||
|
@ -5435,14 +5390,6 @@
|
|||
"url": "https://github.com/sponsors/gregberge"
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/helpers": {
|
||||
"version": "0.4.14",
|
||||
"resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.4.14.tgz",
|
||||
"integrity": "sha512-4C7nX/dvpzB7za4Ql9K81xK3HPxCpHMgwTZVyf+9JQ6VUbn9jjZVN7/Nkdz/Ugzs2CSjqnL/UPXroiVBVHUWUw==",
|
||||
"dependencies": {
|
||||
"tslib": "^2.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@szmarczak/http-timer": {
|
||||
"version": "4.0.6",
|
||||
"resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz",
|
||||
|
@ -6303,11 +6250,6 @@
|
|||
"resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.6.tgz",
|
||||
"integrity": "sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ=="
|
||||
},
|
||||
"node_modules/@types/warning": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/warning/-/warning-3.0.0.tgz",
|
||||
"integrity": "sha512-t/Tvs5qR47OLOr+4E9ckN8AmP2Tf16gWq+/qA4iUGS/OOyHVO8wv2vjJuX8SNOUTJyWb+2t7wJm6cXILFnOROA=="
|
||||
},
|
||||
"node_modules/@types/webpack": {
|
||||
"version": "4.41.33",
|
||||
"resolved": "https://registry.npmjs.org/@types/webpack/-/webpack-4.41.33.tgz",
|
||||
|
@ -8233,24 +8175,6 @@
|
|||
"integrity": "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==",
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/bootstrap": {
|
||||
"version": "5.2.3",
|
||||
"resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.2.3.tgz",
|
||||
"integrity": "sha512-cEKPM+fwb3cT8NzQZYEu4HilJ3anCrWqh3CHAok1p9jXqMPsPTBhU25fBckEJHJ/p+tTxTFTsFQGM+gaHpi3QQ==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/twbs"
|
||||
},
|
||||
{
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/bootstrap"
|
||||
}
|
||||
],
|
||||
"peerDependencies": {
|
||||
"@popperjs/core": "^2.11.6"
|
||||
}
|
||||
},
|
||||
"node_modules/boxen": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/boxen/-/boxen-7.0.0.tgz",
|
||||
|
@ -24956,23 +24880,6 @@
|
|||
"react-is": "^16.13.1"
|
||||
}
|
||||
},
|
||||
"node_modules/prop-types-extra": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/prop-types-extra/-/prop-types-extra-1.1.1.tgz",
|
||||
"integrity": "sha512-59+AHNnHYCdiC+vMwY52WmvP5dM3QLeoumYuEyceQDi9aEhtwN9zIQ2ZNo25sMyXnbh32h+P1ezDsUpUH3JAew==",
|
||||
"dependencies": {
|
||||
"react-is": "^16.3.2",
|
||||
"warning": "^4.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=0.14.0"
|
||||
}
|
||||
},
|
||||
"node_modules/prop-types-extra/node_modules/react-is": {
|
||||
"version": "16.13.1",
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
||||
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
|
||||
},
|
||||
"node_modules/prop-types/node_modules/react-is": {
|
||||
"version": "16.13.1",
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
||||
|
@ -25285,58 +25192,6 @@
|
|||
"url": "https://opencollective.com/core-js"
|
||||
}
|
||||
},
|
||||
"node_modules/react-bootstrap": {
|
||||
"version": "2.7.4",
|
||||
"resolved": "https://registry.npmjs.org/react-bootstrap/-/react-bootstrap-2.7.4.tgz",
|
||||
"integrity": "sha512-EPKPwhfbxsKsNBhJBitJwqul9fvmlYWSft6jWE2EpqhEyjhqIqNihvQo2onE5XtS+QHOavUSNmA+8Lnv5YeAyg==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.21.0",
|
||||
"@restart/hooks": "^0.4.9",
|
||||
"@restart/ui": "^1.6.3",
|
||||
"@types/react-transition-group": "^4.4.5",
|
||||
"classnames": "^2.3.2",
|
||||
"dom-helpers": "^5.2.1",
|
||||
"invariant": "^2.2.4",
|
||||
"prop-types": "^15.8.1",
|
||||
"prop-types-extra": "^1.1.0",
|
||||
"react-transition-group": "^4.4.5",
|
||||
"uncontrollable": "^7.2.1",
|
||||
"warning": "^4.0.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": ">=16.14.8",
|
||||
"react": ">=16.14.0",
|
||||
"react-dom": ">=16.14.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/react-bootstrap-typeahead": {
|
||||
"version": "6.1.2",
|
||||
"resolved": "https://registry.npmjs.org/react-bootstrap-typeahead/-/react-bootstrap-typeahead-6.1.2.tgz",
|
||||
"integrity": "sha512-waIWRQ4CUZld69iL+EFiuL/2B+N4LecaAKcRTMQey0NDOM7Sxmtl+iELFzGltt2/DK6yvrxEUCbZI8pTztPFXA==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.14.6",
|
||||
"@popperjs/core": "^2.10.2",
|
||||
"@restart/hooks": "^0.4.0",
|
||||
"classnames": "^2.2.0",
|
||||
"fast-deep-equal": "^3.1.1",
|
||||
"invariant": "^2.2.1",
|
||||
"lodash.debounce": "^4.0.8",
|
||||
"prop-types": "^15.5.8",
|
||||
"react-overlays": "^5.2.0",
|
||||
"react-popper": "^2.2.5",
|
||||
"scroll-into-view-if-needed": "^2.2.20",
|
||||
"warning": "^4.0.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=16.8.0",
|
||||
"react-dom": ">=16.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-datepicker": {
|
||||
"version": "4.11.0",
|
||||
"resolved": "https://registry.npmjs.org/react-datepicker/-/react-datepicker-4.11.0.tgz",
|
||||
|
@ -25727,25 +25582,6 @@
|
|||
"react-dom": "^15.5.x || ^16.x || ^17.x || ^18.x"
|
||||
}
|
||||
},
|
||||
"node_modules/react-overlays": {
|
||||
"version": "5.2.1",
|
||||
"resolved": "https://registry.npmjs.org/react-overlays/-/react-overlays-5.2.1.tgz",
|
||||
"integrity": "sha512-GLLSOLWr21CqtJn8geSwQfoJufdt3mfdsnIiQswouuQ2MMPns+ihZklxvsTDKD3cR2tF8ELbi5xUsvqVhR6WvA==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.13.8",
|
||||
"@popperjs/core": "^2.11.6",
|
||||
"@restart/hooks": "^0.4.7",
|
||||
"@types/warning": "^3.0.0",
|
||||
"dom-helpers": "^5.2.0",
|
||||
"prop-types": "^15.7.2",
|
||||
"uncontrollable": "^7.2.1",
|
||||
"warning": "^4.0.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=16.3.0",
|
||||
"react-dom": ">=16.3.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-popper": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/react-popper/-/react-popper-2.3.0.tgz",
|
||||
|
@ -25990,6 +25826,26 @@
|
|||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/react-scripts/node_modules/source-map-loader": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/source-map-loader/-/source-map-loader-3.0.2.tgz",
|
||||
"integrity": "sha512-BokxPoLjyl3iOrgkWaakaxqnelAJSS+0V+De0kKIq6lyWrXuiPgYTGp6z3iHmqljKAaLXwZa+ctD8GccRJeVvg==",
|
||||
"dependencies": {
|
||||
"abab": "^2.0.5",
|
||||
"iconv-lite": "^0.6.3",
|
||||
"source-map-js": "^1.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 12.13.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/webpack"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"webpack": "^5.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-scripts/node_modules/yallist": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
||||
|
@ -27004,14 +26860,6 @@
|
|||
"url": "https://opencollective.com/webpack"
|
||||
}
|
||||
},
|
||||
"node_modules/scroll-into-view-if-needed": {
|
||||
"version": "2.2.31",
|
||||
"resolved": "https://registry.npmjs.org/scroll-into-view-if-needed/-/scroll-into-view-if-needed-2.2.31.tgz",
|
||||
"integrity": "sha512-dGCXy99wZQivjmjIqihaBQNjryrz5rueJY7eHfTdyWEiR4ttYpsajb14rn9s5d4DY4EcY6+4+U/maARBXJedkA==",
|
||||
"dependencies": {
|
||||
"compute-scroll-into-view": "^1.0.20"
|
||||
}
|
||||
},
|
||||
"node_modules/select-hose": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz",
|
||||
|
@ -27751,26 +27599,6 @@
|
|||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/source-map-loader": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/source-map-loader/-/source-map-loader-3.0.2.tgz",
|
||||
"integrity": "sha512-BokxPoLjyl3iOrgkWaakaxqnelAJSS+0V+De0kKIq6lyWrXuiPgYTGp6z3iHmqljKAaLXwZa+ctD8GccRJeVvg==",
|
||||
"dependencies": {
|
||||
"abab": "^2.0.5",
|
||||
"iconv-lite": "^0.6.3",
|
||||
"source-map-js": "^1.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 12.13.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/webpack"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"webpack": "^5.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/source-map-resolve": {
|
||||
"version": "0.5.3",
|
||||
"resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz",
|
||||
|
@ -30216,20 +30044,6 @@
|
|||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/uncontrollable": {
|
||||
"version": "7.2.1",
|
||||
"resolved": "https://registry.npmjs.org/uncontrollable/-/uncontrollable-7.2.1.tgz",
|
||||
"integrity": "sha512-svtcfoTADIB0nT9nltgjujTi7BzVmwjZClOmskKu/E8FW9BXzg9os8OLr4f8Dlnk0rYWJIWr4wv9eKUXiQvQwQ==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.6.3",
|
||||
"@types/react": ">=16.9.11",
|
||||
"invariant": "^2.2.4",
|
||||
"react-lifecycles-compat": "^3.0.4"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=15.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/unicode-canonical-property-names-ecmascript": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz",
|
||||
|
@ -35860,14 +35674,6 @@
|
|||
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.7.tgz",
|
||||
"integrity": "sha512-Cr4OjIkipTtcXKjAsm8agyleBuDHvxzeBoa1v543lbv1YaIwQjESsVcmjiWiPEbC1FIeHOG/Op9kdCmAmiS3Kw=="
|
||||
},
|
||||
"@react-aria/ssr": {
|
||||
"version": "3.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@react-aria/ssr/-/ssr-3.6.0.tgz",
|
||||
"integrity": "sha512-OFiYQdv+Yk7AO7IsQu/fAEPijbeTwrrEYvdNoJ3sblBBedD5j5fBTNWrUPNVlwC4XWWnWTCMaRIVsJujsFiWXg==",
|
||||
"requires": {
|
||||
"@swc/helpers": "^0.4.14"
|
||||
}
|
||||
},
|
||||
"@react-icons/all-files": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@react-icons/all-files/-/all-files-4.1.0.tgz",
|
||||
|
@ -35879,30 +35685,6 @@
|
|||
"resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.5.0.tgz",
|
||||
"integrity": "sha512-bkUDCp8o1MvFO+qxkODcbhSqRa6P2GXgrGZVpt0dCXNW2HCSCqYI0ZoAqEOSAjRWmmlKcYgFvN4B4S+zo/f8kg=="
|
||||
},
|
||||
"@restart/hooks": {
|
||||
"version": "0.4.9",
|
||||
"resolved": "https://registry.npmjs.org/@restart/hooks/-/hooks-0.4.9.tgz",
|
||||
"integrity": "sha512-3BekqcwB6Umeya+16XPooARn4qEPW6vNvwYnlofIYe6h9qG1/VeD7UvShCWx11eFz5ELYmwIEshz+MkPX3wjcQ==",
|
||||
"requires": {
|
||||
"dequal": "^2.0.2"
|
||||
}
|
||||
},
|
||||
"@restart/ui": {
|
||||
"version": "1.6.3",
|
||||
"resolved": "https://registry.npmjs.org/@restart/ui/-/ui-1.6.3.tgz",
|
||||
"integrity": "sha512-7HM5aiSWvJBWr+FghZj/n3PSuH2kUrOPiu/D92aIv1zTL8IBwFoQ3oz/f76svoN5v2PKaP6pQbg6vTcIiSffzg==",
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.21.0",
|
||||
"@popperjs/core": "^2.11.6",
|
||||
"@react-aria/ssr": "^3.5.0",
|
||||
"@restart/hooks": "^0.4.9",
|
||||
"@types/warning": "^3.0.0",
|
||||
"dequal": "^2.0.3",
|
||||
"dom-helpers": "^5.2.0",
|
||||
"uncontrollable": "^7.2.1",
|
||||
"warning": "^4.0.3"
|
||||
}
|
||||
},
|
||||
"@rjsf/core": {
|
||||
"version": "5.0.0-beta.20",
|
||||
"resolved": "https://registry.npmjs.org/@rjsf/core/-/core-5.0.0-beta.20.tgz",
|
||||
|
@ -36149,14 +35931,6 @@
|
|||
"loader-utils": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"@swc/helpers": {
|
||||
"version": "0.4.14",
|
||||
"resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.4.14.tgz",
|
||||
"integrity": "sha512-4C7nX/dvpzB7za4Ql9K81xK3HPxCpHMgwTZVyf+9JQ6VUbn9jjZVN7/Nkdz/Ugzs2CSjqnL/UPXroiVBVHUWUw==",
|
||||
"requires": {
|
||||
"tslib": "^2.4.0"
|
||||
}
|
||||
},
|
||||
"@szmarczak/http-timer": {
|
||||
"version": "4.0.6",
|
||||
"resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz",
|
||||
|
@ -36897,11 +36671,6 @@
|
|||
"resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.6.tgz",
|
||||
"integrity": "sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ=="
|
||||
},
|
||||
"@types/warning": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/warning/-/warning-3.0.0.tgz",
|
||||
"integrity": "sha512-t/Tvs5qR47OLOr+4E9ckN8AmP2Tf16gWq+/qA4iUGS/OOyHVO8wv2vjJuX8SNOUTJyWb+2t7wJm6cXILFnOROA=="
|
||||
},
|
||||
"@types/webpack": {
|
||||
"version": "4.41.33",
|
||||
"resolved": "https://registry.npmjs.org/@types/webpack/-/webpack-4.41.33.tgz",
|
||||
|
@ -38385,12 +38154,6 @@
|
|||
"integrity": "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==",
|
||||
"optional": true
|
||||
},
|
||||
"bootstrap": {
|
||||
"version": "5.2.3",
|
||||
"resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.2.3.tgz",
|
||||
"integrity": "sha512-cEKPM+fwb3cT8NzQZYEu4HilJ3anCrWqh3CHAok1p9jXqMPsPTBhU25fBckEJHJ/p+tTxTFTsFQGM+gaHpi3QQ==",
|
||||
"requires": {}
|
||||
},
|
||||
"boxen": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/boxen/-/boxen-7.0.0.tgz",
|
||||
|
@ -50528,7 +50291,7 @@
|
|||
"@csstools/postcss-text-decoration-shorthand": "^1.0.0",
|
||||
"@csstools/postcss-trigonometric-functions": "^1.0.2",
|
||||
"@csstools/postcss-unset-value": "^1.0.2",
|
||||
"autoprefixer": "^10.4.13",
|
||||
"autoprefixer": "10.4.5",
|
||||
"browserslist": "^4.21.4",
|
||||
"css-blank-pseudo": "^3.0.3",
|
||||
"css-has-pseudo": "^3.0.4",
|
||||
|
@ -50566,7 +50329,8 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"autoprefixer": {
|
||||
"version": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.5.tgz",
|
||||
"version": "10.4.5",
|
||||
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.5.tgz",
|
||||
"integrity": "sha512-Fvd8yCoA7lNX/OUllvS+aS1I7WRBclGXsepbvT8ZaPgrH24rgXpZzF0/6Hh3ZEkwg+0AES/Osd196VZmYoEFtw==",
|
||||
"requires": {
|
||||
"browserslist": "^4.20.2",
|
||||
|
@ -50830,22 +50594,6 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"prop-types-extra": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/prop-types-extra/-/prop-types-extra-1.1.1.tgz",
|
||||
"integrity": "sha512-59+AHNnHYCdiC+vMwY52WmvP5dM3QLeoumYuEyceQDi9aEhtwN9zIQ2ZNo25sMyXnbh32h+P1ezDsUpUH3JAew==",
|
||||
"requires": {
|
||||
"react-is": "^16.3.2",
|
||||
"warning": "^4.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"react-is": {
|
||||
"version": "16.13.1",
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
||||
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"property-information": {
|
||||
"version": "6.2.0",
|
||||
"resolved": "https://registry.npmjs.org/property-information/-/property-information-6.2.0.tgz",
|
||||
|
@ -51089,44 +50837,6 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"react-bootstrap": {
|
||||
"version": "2.7.4",
|
||||
"resolved": "https://registry.npmjs.org/react-bootstrap/-/react-bootstrap-2.7.4.tgz",
|
||||
"integrity": "sha512-EPKPwhfbxsKsNBhJBitJwqul9fvmlYWSft6jWE2EpqhEyjhqIqNihvQo2onE5XtS+QHOavUSNmA+8Lnv5YeAyg==",
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.21.0",
|
||||
"@restart/hooks": "^0.4.9",
|
||||
"@restart/ui": "^1.6.3",
|
||||
"@types/react-transition-group": "^4.4.5",
|
||||
"classnames": "^2.3.2",
|
||||
"dom-helpers": "^5.2.1",
|
||||
"invariant": "^2.2.4",
|
||||
"prop-types": "^15.8.1",
|
||||
"prop-types-extra": "^1.1.0",
|
||||
"react-transition-group": "^4.4.5",
|
||||
"uncontrollable": "^7.2.1",
|
||||
"warning": "^4.0.3"
|
||||
}
|
||||
},
|
||||
"react-bootstrap-typeahead": {
|
||||
"version": "6.1.2",
|
||||
"resolved": "https://registry.npmjs.org/react-bootstrap-typeahead/-/react-bootstrap-typeahead-6.1.2.tgz",
|
||||
"integrity": "sha512-waIWRQ4CUZld69iL+EFiuL/2B+N4LecaAKcRTMQey0NDOM7Sxmtl+iELFzGltt2/DK6yvrxEUCbZI8pTztPFXA==",
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.14.6",
|
||||
"@popperjs/core": "^2.10.2",
|
||||
"@restart/hooks": "^0.4.0",
|
||||
"classnames": "^2.2.0",
|
||||
"fast-deep-equal": "^3.1.1",
|
||||
"invariant": "^2.2.1",
|
||||
"lodash.debounce": "^4.0.8",
|
||||
"prop-types": "^15.5.8",
|
||||
"react-overlays": "^5.2.0",
|
||||
"react-popper": "^2.2.5",
|
||||
"scroll-into-view-if-needed": "^2.2.20",
|
||||
"warning": "^4.0.1"
|
||||
}
|
||||
},
|
||||
"react-datepicker": {
|
||||
"version": "4.11.0",
|
||||
"resolved": "https://registry.npmjs.org/react-datepicker/-/react-datepicker-4.11.0.tgz",
|
||||
|
@ -51424,21 +51134,6 @@
|
|||
"integrity": "sha512-ty8So6tcUpIb+ZE+1HAhbLROvAIJYyJe/1vRrrcmW+jLsaM+/powDRqxzo6hSh9CuRZGSL1Q8mvcF5WRD93a0A==",
|
||||
"requires": {}
|
||||
},
|
||||
"react-overlays": {
|
||||
"version": "5.2.1",
|
||||
"resolved": "https://registry.npmjs.org/react-overlays/-/react-overlays-5.2.1.tgz",
|
||||
"integrity": "sha512-GLLSOLWr21CqtJn8geSwQfoJufdt3mfdsnIiQswouuQ2MMPns+ihZklxvsTDKD3cR2tF8ELbi5xUsvqVhR6WvA==",
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.13.8",
|
||||
"@popperjs/core": "^2.11.6",
|
||||
"@restart/hooks": "^0.4.7",
|
||||
"@types/warning": "^3.0.0",
|
||||
"dom-helpers": "^5.2.0",
|
||||
"prop-types": "^15.7.2",
|
||||
"uncontrollable": "^7.2.1",
|
||||
"warning": "^4.0.3"
|
||||
}
|
||||
},
|
||||
"react-popper": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/react-popper/-/react-popper-2.3.0.tgz",
|
||||
|
@ -51609,6 +51304,16 @@
|
|||
"lru-cache": "^6.0.0"
|
||||
}
|
||||
},
|
||||
"source-map-loader": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/source-map-loader/-/source-map-loader-3.0.2.tgz",
|
||||
"integrity": "sha512-BokxPoLjyl3iOrgkWaakaxqnelAJSS+0V+De0kKIq6lyWrXuiPgYTGp6z3iHmqljKAaLXwZa+ctD8GccRJeVvg==",
|
||||
"requires": {
|
||||
"abab": "^2.0.5",
|
||||
"iconv-lite": "^0.6.3",
|
||||
"source-map-js": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"yallist": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
||||
|
@ -52355,14 +52060,6 @@
|
|||
"ajv-keywords": "^5.1.0"
|
||||
}
|
||||
},
|
||||
"scroll-into-view-if-needed": {
|
||||
"version": "2.2.31",
|
||||
"resolved": "https://registry.npmjs.org/scroll-into-view-if-needed/-/scroll-into-view-if-needed-2.2.31.tgz",
|
||||
"integrity": "sha512-dGCXy99wZQivjmjIqihaBQNjryrz5rueJY7eHfTdyWEiR4ttYpsajb14rn9s5d4DY4EcY6+4+U/maARBXJedkA==",
|
||||
"requires": {
|
||||
"compute-scroll-into-view": "^1.0.20"
|
||||
}
|
||||
},
|
||||
"select-hose": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz",
|
||||
|
@ -52974,16 +52671,6 @@
|
|||
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
|
||||
"integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw=="
|
||||
},
|
||||
"source-map-loader": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/source-map-loader/-/source-map-loader-3.0.2.tgz",
|
||||
"integrity": "sha512-BokxPoLjyl3iOrgkWaakaxqnelAJSS+0V+De0kKIq6lyWrXuiPgYTGp6z3iHmqljKAaLXwZa+ctD8GccRJeVvg==",
|
||||
"requires": {
|
||||
"abab": "^2.0.5",
|
||||
"iconv-lite": "^0.6.3",
|
||||
"source-map-js": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"source-map-resolve": {
|
||||
"version": "0.5.3",
|
||||
"resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz",
|
||||
|
@ -54914,17 +54601,6 @@
|
|||
"which-boxed-primitive": "^1.0.2"
|
||||
}
|
||||
},
|
||||
"uncontrollable": {
|
||||
"version": "7.2.1",
|
||||
"resolved": "https://registry.npmjs.org/uncontrollable/-/uncontrollable-7.2.1.tgz",
|
||||
"integrity": "sha512-svtcfoTADIB0nT9nltgjujTi7BzVmwjZClOmskKu/E8FW9BXzg9os8OLr4f8Dlnk0rYWJIWr4wv9eKUXiQvQwQ==",
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.6.3",
|
||||
"@types/react": ">=16.9.11",
|
||||
"invariant": "^2.2.4",
|
||||
"react-lifecycles-compat": "^3.0.4"
|
||||
}
|
||||
},
|
||||
"unicode-canonical-property-names-ecmascript": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz",
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
"@uiw/react-md-editor": "^3.20.2",
|
||||
"autoprefixer": "10.4.8",
|
||||
"axios": "^0.27.2",
|
||||
"bootstrap": "^5.2.0",
|
||||
"bpmn-js": "^13.0.0",
|
||||
"bpmn-js-properties-panel": "^1.22.0",
|
||||
"bpmn-js-spiffworkflow": "github:sartography/bpmn-js-spiffworkflow#main",
|
||||
|
@ -46,8 +45,6 @@
|
|||
"keycloak-js": "^18.0.1",
|
||||
"prop-types": "^15.8.1",
|
||||
"react": "^18.2.0",
|
||||
"react-bootstrap": "^2.5.0",
|
||||
"react-bootstrap-typeahead": "^6.0.0",
|
||||
"react-datepicker": "^4.8.0",
|
||||
"react-devtools": "^4.27.1",
|
||||
"react-dom": "^18.2.0",
|
||||
|
|
|
@ -15,9 +15,7 @@ import {
|
|||
HeaderMenuItem,
|
||||
HeaderGlobalAction,
|
||||
HeaderGlobalBar,
|
||||
// @ts-ignore
|
||||
} from '@carbon/react';
|
||||
// @ts-ignore
|
||||
import { Logout, Login } from '@carbon/icons-react';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
|
@ -32,7 +30,6 @@ import { UnauthenticatedError } from '../services/HttpService';
|
|||
import { DOCUMENTATION_URL, SPIFF_ENVIRONMENT } from '../config';
|
||||
import appVersionInfo from '../helpers/appVersionInfo';
|
||||
|
||||
// for ref: https://react-bootstrap.github.io/components/navbar/
|
||||
export default function NavigationBar() {
|
||||
const handleLogout = () => {
|
||||
UserService.doLogout();
|
||||
|
@ -232,13 +229,6 @@ export default function NavigationBar() {
|
|||
</HeaderMenuItem>
|
||||
</Can>
|
||||
{configurationElement()}
|
||||
<HeaderMenuItem
|
||||
hidden
|
||||
href="/admin/process-instances/reports"
|
||||
isCurrentPage={isActivePage('/admin/process-instances/reports')}
|
||||
>
|
||||
Perspectives
|
||||
</HeaderMenuItem>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -97,7 +97,7 @@ export default function ProcessGroupListTiles({
|
|||
return (
|
||||
<>
|
||||
{/* so we can check if the groups have loaded in cypress tests */}
|
||||
<div data-qa="process-groups-loaded" hidden />
|
||||
<div data-qa="process-groups-loaded" className="hidden" />
|
||||
{processGroupArea()}
|
||||
</>
|
||||
);
|
||||
|
|
|
@ -56,8 +56,6 @@ import 'react-datepicker/dist/react-datepicker.css';
|
|||
|
||||
import HttpService from '../services/HttpService';
|
||||
|
||||
import 'react-bootstrap-typeahead/css/Typeahead.css';
|
||||
import 'react-bootstrap-typeahead/css/Typeahead.bs5.css';
|
||||
import {
|
||||
PaginationObject,
|
||||
ProcessModel,
|
||||
|
|
|
@ -124,10 +124,18 @@ export default function ReactDiagramEditor({
|
|||
const alreadyImportedXmlRef = useRef(false);
|
||||
|
||||
const { targetUris } = useUriListForPermissions();
|
||||
const permissionRequestData: PermissionsToCheck = {
|
||||
[targetUris.processModelShowPath]: ['PUT'],
|
||||
[targetUris.processModelFileShowPath]: ['POST', 'GET', 'PUT', 'DELETE'],
|
||||
};
|
||||
const permissionRequestData: PermissionsToCheck = {};
|
||||
|
||||
if (diagramType !== 'readonly') {
|
||||
permissionRequestData[targetUris.processModelShowPath] = ['PUT'];
|
||||
permissionRequestData[targetUris.processModelFileShowPath] = [
|
||||
'POST',
|
||||
'GET',
|
||||
'PUT',
|
||||
'DELETE',
|
||||
];
|
||||
}
|
||||
|
||||
const { ability } = usePermissionFetcher(permissionRequestData);
|
||||
const navigate = useNavigate();
|
||||
|
||||
|
|
|
@ -203,14 +203,15 @@ export default function TaskListTable({
|
|||
}
|
||||
rowElements.push(
|
||||
<td>
|
||||
{processInstanceTask.process_instance_status === 'suspended' ? null : (
|
||||
<Button
|
||||
variant="primary"
|
||||
href={taskUrl}
|
||||
hidden={processInstanceTask.process_instance_status === 'suspended'}
|
||||
disabled={!hasAccessToCompleteTask}
|
||||
>
|
||||
Go
|
||||
</Button>
|
||||
)}
|
||||
</td>
|
||||
);
|
||||
return <tr key={processInstanceTask.id}>{rowElements}</tr>;
|
||||
|
|
|
@ -10,7 +10,7 @@ export const useUriListForPermissions = () => {
|
|||
processGroupListPath: '/v1.0/process-groups',
|
||||
processGroupShowPath: `/v1.0/process-groups/${params.process_group_id}`,
|
||||
processInstanceActionPath: `/v1.0/process-instances/${params.process_model_id}/${params.process_instance_id}`,
|
||||
processInstanceCompleteTaskPath: `/v1.0/complete-task/${params.process_model_id}/${params.process_instance_id}`,
|
||||
processInstanceCompleteTaskPath: `/v1.0/task-complete/${params.process_model_id}/${params.process_instance_id}`,
|
||||
processInstanceCreatePath: `/v1.0/process-instances/${params.process_model_id}`,
|
||||
processInstanceErrorEventDetails: `/v1.0/event-error-details/${params.process_model_id}/${params.process_instance_id}`,
|
||||
processInstanceListPath: '/v1.0/process-instances',
|
||||
|
|
|
@ -260,6 +260,10 @@ h1.with-icons {
|
|||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.with-top-margin-for-unit-test-name {
|
||||
margin-top: 11px;
|
||||
}
|
||||
|
||||
.with-large-bottom-margin {
|
||||
margin-bottom: 3em;
|
||||
}
|
||||
|
|
|
@ -2,7 +2,6 @@ import React from 'react';
|
|||
import * as ReactDOMClient from 'react-dom/client';
|
||||
import App from './App';
|
||||
|
||||
import 'bootstrap/dist/css/bootstrap.css';
|
||||
import './index.scss';
|
||||
import './index.css';
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import { useEffect, useState } from 'react';
|
||||
import { Route, Routes, useLocation, useNavigate } from 'react-router-dom';
|
||||
// @ts-ignore
|
||||
import { Tabs, TabList, Tab } from '@carbon/react';
|
||||
import TaskShow from './TaskShow';
|
||||
import MyTasks from './MyTasks';
|
||||
|
|
|
@ -2,8 +2,6 @@ import { useSearchParams } from 'react-router-dom';
|
|||
|
||||
import 'react-datepicker/dist/react-datepicker.css';
|
||||
|
||||
import 'react-bootstrap-typeahead/css/Typeahead.css';
|
||||
import 'react-bootstrap-typeahead/css/Typeahead.bs5.css';
|
||||
import ProcessBreadcrumb from '../components/ProcessBreadcrumb';
|
||||
import ProcessInstanceListTable from '../components/ProcessInstanceListTable';
|
||||
import { getProcessModelFullIdentifierFromSearchParams } from '../helpers';
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { useEffect, useRef, useState } from 'react';
|
||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import {
|
||||
generatePath,
|
||||
useNavigate,
|
||||
|
@ -7,8 +7,8 @@ import {
|
|||
} from 'react-router-dom';
|
||||
import {
|
||||
Button,
|
||||
ButtonSet,
|
||||
Modal,
|
||||
Content,
|
||||
Tabs,
|
||||
TabList,
|
||||
Tab,
|
||||
|
@ -17,10 +17,14 @@ import {
|
|||
TextInput,
|
||||
Grid,
|
||||
Column,
|
||||
// @ts-ignore
|
||||
} from '@carbon/react';
|
||||
import Row from 'react-bootstrap/Row';
|
||||
import Col from 'react-bootstrap/Col';
|
||||
import {
|
||||
SkipForward,
|
||||
SkipBack,
|
||||
PlayOutline,
|
||||
Close,
|
||||
Checkmark,
|
||||
} from '@carbon/icons-react';
|
||||
|
||||
import Editor, { DiffEditor } from '@monaco-editor/react';
|
||||
|
||||
|
@ -125,9 +129,7 @@ export default function ProcessModelEditDiagram() {
|
|||
|
||||
usePrompt('Changes you made may not be saved.', diagramHasChanges);
|
||||
|
||||
useEffect(() => {
|
||||
// Grab all available process models in case we need to search for them.
|
||||
// Taken from the Process Group List
|
||||
const getProcessesCallback = useCallback((onProcessesFetched?: Function) => {
|
||||
const processResults = (result: any) => {
|
||||
const selectionArray = result.map((item: any) => {
|
||||
const label = `${item.display_name} (${item.identifier})`;
|
||||
|
@ -135,13 +137,19 @@ export default function ProcessModelEditDiagram() {
|
|||
return item;
|
||||
});
|
||||
setProcesses(selectionArray);
|
||||
if (onProcessesFetched) {
|
||||
onProcessesFetched(selectionArray);
|
||||
}
|
||||
};
|
||||
HttpService.makeCallToBackend({
|
||||
path: `/processes`,
|
||||
successCallback: processResults,
|
||||
});
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []); // it is critical to only run this once.
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
getProcessesCallback();
|
||||
}, [getProcessesCallback]);
|
||||
|
||||
useEffect(() => {
|
||||
const fileResult = (result: any) => {
|
||||
|
@ -576,7 +584,10 @@ export default function ProcessModelEditDiagram() {
|
|||
|
||||
if (scriptUnitTestResult.context) {
|
||||
errorStringElement = (
|
||||
<span>Unexpected result. Please see the comparison below.</span>
|
||||
<span>
|
||||
Unexpected result. Please see the expected / actual comparison
|
||||
below.
|
||||
</span>
|
||||
);
|
||||
let outputJson = '{}';
|
||||
if (currentScriptUnitTest) {
|
||||
|
@ -634,14 +645,28 @@ export default function ProcessModelEditDiagram() {
|
|||
let scriptUnitTestResultBoolElement = null;
|
||||
if (scriptUnitTestResult) {
|
||||
scriptUnitTestResultBoolElement = (
|
||||
<Col xs={1}>
|
||||
<>
|
||||
{scriptUnitTestResult.result === true && (
|
||||
<span style={{ color: 'green', fontSize: '3em' }}>✓</span>
|
||||
<Button
|
||||
kind="ghost"
|
||||
className="green-icon"
|
||||
renderIcon={Checkmark}
|
||||
iconDescription="Unit tests passed"
|
||||
hasIconOnly
|
||||
size="lg"
|
||||
/>
|
||||
)}
|
||||
{scriptUnitTestResult.result === false && (
|
||||
<span style={{ color: 'red', fontSize: '3em' }}>✘</span>
|
||||
<Button
|
||||
kind="ghost"
|
||||
className="red-icon"
|
||||
renderIcon={Close}
|
||||
iconDescription="Unit tests failed"
|
||||
hasIconOnly
|
||||
size="lg"
|
||||
/>
|
||||
)}
|
||||
</Col>
|
||||
</>
|
||||
);
|
||||
}
|
||||
let inputJson = currentScriptUnitTest.inputJson.value;
|
||||
|
@ -663,51 +688,54 @@ export default function ProcessModelEditDiagram() {
|
|||
|
||||
return (
|
||||
<main>
|
||||
<Content>
|
||||
<Row>
|
||||
<Col xs={8}>
|
||||
<Button variant="link" disabled>
|
||||
<Grid condensed fullWidth>
|
||||
<Column md={4} lg={8} sm={2}>
|
||||
<p className="with-top-margin-for-unit-test-name">
|
||||
Unit Test: {currentScriptUnitTest.id}
|
||||
</Button>
|
||||
</Col>
|
||||
<Col xs={1}>
|
||||
</p>
|
||||
</Column>
|
||||
<Column md={4} lg={8} sm={2}>
|
||||
<ButtonSet>
|
||||
<Button
|
||||
kind="ghost"
|
||||
data-qa="unit-test-previous-button"
|
||||
onClick={setPreviousScriptUnitTest}
|
||||
variant="link"
|
||||
renderIcon={SkipBack}
|
||||
iconDescription="Previous Unit Test"
|
||||
hasIconOnly
|
||||
size="lg"
|
||||
disabled={previousButtonDisable}
|
||||
>
|
||||
«
|
||||
</Button>
|
||||
</Col>
|
||||
<Col xs={1}>
|
||||
onClick={setPreviousScriptUnitTest}
|
||||
/>
|
||||
<Button
|
||||
kind="ghost"
|
||||
data-qa="unit-test-next-button"
|
||||
style={{ fontSize: '1.5em' }}
|
||||
onClick={setNextScriptUnitTest}
|
||||
variant="link"
|
||||
renderIcon={SkipForward}
|
||||
iconDescription="Next Unit Test"
|
||||
hasIconOnly
|
||||
size="lg"
|
||||
disabled={nextButtonDisable}
|
||||
>
|
||||
»
|
||||
</Button>
|
||||
</Col>
|
||||
<Col xs={1}>
|
||||
onClick={setNextScriptUnitTest}
|
||||
/>
|
||||
<Button
|
||||
className="justify-content-end"
|
||||
kind="ghost"
|
||||
data-qa="unit-test-run"
|
||||
style={{ fontSize: '1.5em' }}
|
||||
renderIcon={PlayOutline}
|
||||
iconDescription="Run Unit Test"
|
||||
hasIconOnly
|
||||
size="lg"
|
||||
onClick={runCurrentUnitTest}
|
||||
>
|
||||
Run
|
||||
</Button>
|
||||
</Col>
|
||||
<Col xs={1}>{scriptUnitTestResultBoolElement}</Col>
|
||||
</Row>
|
||||
<Row>
|
||||
<Col>{unitTestFailureElement()}</Col>
|
||||
</Row>
|
||||
<Row>
|
||||
<Col>
|
||||
/>
|
||||
{scriptUnitTestResultBoolElement}
|
||||
</ButtonSet>
|
||||
</Column>
|
||||
</Grid>
|
||||
<Grid condensed fullWidth>
|
||||
<Column md={8} lg={16} sm={4}>
|
||||
{unitTestFailureElement()}
|
||||
</Column>
|
||||
</Grid>
|
||||
<Grid condensed fullWidth>
|
||||
<Column md={4} lg={8} sm={2}>
|
||||
<div>Input Json:</div>
|
||||
<div>
|
||||
<Editor
|
||||
|
@ -719,8 +747,8 @@ export default function ProcessModelEditDiagram() {
|
|||
onChange={handleEditorScriptTestUnitInputChange}
|
||||
/>
|
||||
</div>
|
||||
</Col>
|
||||
<Col>
|
||||
</Column>
|
||||
<Column md={4} lg={8} sm={2}>
|
||||
<div>Expected Output Json:</div>
|
||||
<div>
|
||||
<Editor
|
||||
|
@ -732,9 +760,8 @@ export default function ProcessModelEditDiagram() {
|
|||
onChange={handleEditorScriptTestUnitOutputChange}
|
||||
/>
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
</Content>
|
||||
</Column>
|
||||
</Grid>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
@ -877,6 +904,32 @@ export default function ProcessModelEditDiagram() {
|
|||
};
|
||||
|
||||
const onLaunchBpmnEditor = (processId: string) => {
|
||||
const openProcessModelFileInNewTab = (
|
||||
processReference: ProcessReference
|
||||
) => {
|
||||
const path = generatePath(
|
||||
'/admin/process-models/:process_model_path/files/:file_name',
|
||||
{
|
||||
process_model_path: modifyProcessIdentifierForPathParam(
|
||||
processReference.process_model_id
|
||||
),
|
||||
file_name: processReference.file_name,
|
||||
}
|
||||
);
|
||||
window.open(path);
|
||||
};
|
||||
|
||||
const openFileNameForProcessId = (
|
||||
processesReferences: ProcessReference[]
|
||||
) => {
|
||||
const processRef = processesReferences.find((p) => {
|
||||
return p.identifier === processId;
|
||||
});
|
||||
if (processRef) {
|
||||
openProcessModelFileInNewTab(processRef);
|
||||
}
|
||||
};
|
||||
|
||||
// using the "setState" method with a function gives us access to the
|
||||
// most current state of processes. Otherwise it uses the stale state
|
||||
// when passing the callback to a non-React component like bpmn-js:
|
||||
|
@ -885,17 +938,10 @@ export default function ProcessModelEditDiagram() {
|
|||
const processRef = upToDateProcesses.find((p) => {
|
||||
return p.identifier === processId;
|
||||
});
|
||||
if (processRef) {
|
||||
const path = generatePath(
|
||||
'/admin/process-models/:process_model_path/files/:file_name',
|
||||
{
|
||||
process_model_path: modifyProcessIdentifierForPathParam(
|
||||
processRef.process_model_id
|
||||
),
|
||||
file_name: processRef.file_name,
|
||||
}
|
||||
);
|
||||
window.open(path);
|
||||
if (!processRef) {
|
||||
getProcessesCallback(openFileNameForProcessId);
|
||||
} else {
|
||||
openProcessModelFileInNewTab(processRef);
|
||||
}
|
||||
return upToDateProcesses;
|
||||
});
|
||||
|
|
|
@ -1,14 +1,13 @@
|
|||
import { useState } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
// @ts-ignore
|
||||
import { Stack } from '@carbon/react';
|
||||
import Button from 'react-bootstrap/Button';
|
||||
import Form from 'react-bootstrap/Form';
|
||||
import { Form, TextInput, Button, ButtonSet, Stack } from '@carbon/react';
|
||||
import HttpService from '../services/HttpService';
|
||||
|
||||
export default function SecretNew() {
|
||||
const [value, setValue] = useState('');
|
||||
const [key, setKey] = useState('');
|
||||
const [value, setValue] = useState<string>('');
|
||||
const [key, setKey] = useState<string>('');
|
||||
const [keyIsInvalid, setKeyIsInvalid] = useState<boolean>(false);
|
||||
const [valueIsInvalid, setValueIsInvalid] = useState<boolean>(false);
|
||||
const navigate = useNavigate();
|
||||
|
||||
const navigateToSecret = (_result: any) => {
|
||||
|
@ -19,16 +18,24 @@ export default function SecretNew() {
|
|||
navigate(`/admin/configuration/secrets`);
|
||||
};
|
||||
|
||||
const changeSpacesToDash = (someString: string) => {
|
||||
// change spaces to `-`
|
||||
let s1 = someString.replace(' ', '-');
|
||||
// remove any trailing `-`
|
||||
s1 = s1.replace(/-$/, '');
|
||||
return s1;
|
||||
};
|
||||
|
||||
const addSecret = (event: any) => {
|
||||
event.preventDefault();
|
||||
|
||||
let hasErrors = false;
|
||||
setKeyIsInvalid(false);
|
||||
if (!key.match(/^[\w-]+$/)) {
|
||||
setKeyIsInvalid(true);
|
||||
hasErrors = true;
|
||||
}
|
||||
setValueIsInvalid(false);
|
||||
if (value.trim().length < 1) {
|
||||
setValueIsInvalid(true);
|
||||
hasErrors = true;
|
||||
}
|
||||
if (hasErrors) {
|
||||
return;
|
||||
}
|
||||
|
||||
HttpService.makeCallToBackend({
|
||||
path: `/secrets`,
|
||||
successCallback: navigateToSecret,
|
||||
|
@ -40,41 +47,41 @@ export default function SecretNew() {
|
|||
});
|
||||
};
|
||||
|
||||
const warningStyle = {
|
||||
color: 'red',
|
||||
};
|
||||
|
||||
return (
|
||||
<main style={{ padding: '1rem 0' }}>
|
||||
<h1>Add Secret</h1>
|
||||
<Form onSubmit={addSecret}>
|
||||
<Form.Group className="mb-3" controlId="formDisplayName">
|
||||
<Form.Label>
|
||||
Key: <span style={warningStyle}>No Spaces</span>
|
||||
</Form.Label>
|
||||
<Form.Control
|
||||
type="text"
|
||||
<Stack gap={5}>
|
||||
<TextInput
|
||||
id="secret-key"
|
||||
labelText="Key*"
|
||||
value={key}
|
||||
onChange={(e) => setKey(changeSpacesToDash(e.target.value))}
|
||||
invalid={keyIsInvalid}
|
||||
invalidText="The key must be alphanumeric characters and underscores"
|
||||
onChange={(e: any) => setKey(e.target.value)}
|
||||
/>
|
||||
</Form.Group>
|
||||
<Form.Group className="mb-3" controlId="formIdentifier">
|
||||
<Form.Label>Value:</Form.Label>
|
||||
<Form.Control
|
||||
type="text"
|
||||
<TextInput
|
||||
id="secret-value"
|
||||
labelText="Value*"
|
||||
value={value}
|
||||
onChange={(e) => {
|
||||
invalid={valueIsInvalid}
|
||||
invalidText="The value must be set"
|
||||
onChange={(e: any) => {
|
||||
setValue(e.target.value);
|
||||
}}
|
||||
/>
|
||||
</Form.Group>
|
||||
<Stack orientation="horizontal" gap={3}>
|
||||
<Button variant="primary" type="submit">
|
||||
<ButtonSet>
|
||||
<Button kind="primary" type="submit">
|
||||
Submit
|
||||
</Button>
|
||||
<Button variant="danger" type="button" onClick={navigateToSecrets}>
|
||||
<Button
|
||||
kind=""
|
||||
className="button-white-background"
|
||||
onClick={navigateToSecrets}
|
||||
>
|
||||
Cancel
|
||||
</Button>
|
||||
</ButtonSet>
|
||||
</Stack>
|
||||
</Form>
|
||||
</main>
|
||||
|
|