merged in main and resolved conflicts w/ burnettk

This commit is contained in:
jasquat 2023-07-07 11:04:11 -04:00
commit 19d7a008d9
7 changed files with 65 additions and 32 deletions

View File

@ -1700,14 +1700,14 @@ files = [
[[package]]
name = "pygments"
version = "2.14.0"
version = "2.15.1"
description = "Pygments is a syntax highlighting package written in Python."
category = "dev"
optional = false
python-versions = ">=3.6"
python-versions = ">=3.7"
files = [
{file = "Pygments-2.14.0-py3-none-any.whl", hash = "sha256:fa7bd7bd2771287c0de303af8bfdfc731f51bd2c6a47ab69d117138893b82717"},
{file = "Pygments-2.14.0.tar.gz", hash = "sha256:b3ed06a9e8ac9a9aae5a6f5dbe78a8a58655d17b43b93c078f094ddc476ae297"},
{file = "Pygments-2.15.1-py3-none-any.whl", hash = "sha256:db2db3deb4b4179f399a09054b023b6a586b76499d36965813c71aa8ed7b5fd1"},
{file = "Pygments-2.15.1.tar.gz", hash = "sha256:8ace4d3c1dd481894b2005f560ead0f9f19ee64fe983366be1a21e171d12775c"},
]
[package.extras]
@ -2122,7 +2122,8 @@ files = [
{file = "ruamel.yaml.clib-0.2.7-cp310-cp310-win32.whl", hash = "sha256:763d65baa3b952479c4e972669f679fe490eee058d5aa85da483ebae2009d231"},
{file = "ruamel.yaml.clib-0.2.7-cp310-cp310-win_amd64.whl", hash = "sha256:d000f258cf42fec2b1bbf2863c61d7b8918d31ffee905da62dede869254d3b8a"},
{file = "ruamel.yaml.clib-0.2.7-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:045e0626baf1c52e5527bd5db361bc83180faaba2ff586e763d3d5982a876a9e"},
{file = "ruamel.yaml.clib-0.2.7-cp311-cp311-macosx_12_6_arm64.whl", hash = "sha256:721bc4ba4525f53f6a611ec0967bdcee61b31df5a56801281027a3a6d1c2daf5"},
{file = "ruamel.yaml.clib-0.2.7-cp311-cp311-macosx_13_0_arm64.whl", hash = "sha256:1a6391a7cabb7641c32517539ca42cf84b87b667bad38b78d4d42dd23e957c81"},
{file = "ruamel.yaml.clib-0.2.7-cp311-cp311-manylinux2014_aarch64.whl", hash = "sha256:9c7617df90c1365638916b98cdd9be833d31d337dbcd722485597b43c4a215bf"},
{file = "ruamel.yaml.clib-0.2.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:41d0f1fa4c6830176eef5b276af04c89320ea616655d01327d5ce65e50575c94"},
{file = "ruamel.yaml.clib-0.2.7-cp311-cp311-win32.whl", hash = "sha256:f6d3d39611ac2e4f62c3128a9eed45f19a6608670c5a2f4f07f24e8de3441d38"},
{file = "ruamel.yaml.clib-0.2.7-cp311-cp311-win_amd64.whl", hash = "sha256:da538167284de58a52109a9b89b8f6a53ff8437dd6dc26d33b57bf6699153122"},

View File

@ -713,7 +713,11 @@ def _find_process_instance_for_me_or_raise(
)
.filter(
or_(
# you were allowed to complete it
HumanTaskUserModel.id.is_not(None),
# or you completed it (which admins can do even if it wasn't assigned via HumanTaskUserModel)
HumanTaskModel.completed_by_user_id == g.user.id,
# or you started it
ProcessInstanceModel.process_initiator_id == g.user.id,
)
)

View File

@ -1095,6 +1095,7 @@ class ProcessInstanceProcessor:
event_type = ProcessInstanceEventType.task_skipped.value
start_time = time.time()
# manual actually means any human task
if spiff_task.task_spec.manual:
# Executing or not executing a human task results in the same state.
current_app.logger.info(

View File

@ -244,7 +244,9 @@ class ProcessInstanceReportService:
return results
@classmethod
def add_human_task_fields(cls, process_instance_dicts: list[dict]) -> list[dict]:
def add_human_task_fields(
cls, process_instance_dicts: list[dict], restrict_human_tasks_to_user: UserModel | None = None
) -> list[dict]:
fields_to_return = [
"task_id",
"task_title",
@ -264,6 +266,10 @@ class ProcessInstanceReportService:
.outerjoin(assigned_user, assigned_user.id == HumanTaskUserModel.user_id)
.outerjoin(GroupModel, GroupModel.id == HumanTaskModel.lane_assignment_id)
)
if restrict_human_tasks_to_user is not None:
human_task_query = human_task_query.filter(
HumanTaskUserModel.user_id == restrict_human_tasks_to_user.id
)
potential_owner_usernames_from_group_concat_or_similar = cls._get_potential_owner_usernames(assigned_user)
human_task = (
human_task_query.add_columns(
@ -371,6 +377,7 @@ class ProcessInstanceReportService:
# Always join that hot user table for good performance at serialization time.
process_instance_query = process_instance_query.options(selectinload(ProcessInstanceModel.process_initiator))
filters = report_metadata["filter_by"]
restrict_human_tasks_to_user = None
for value in cls.check_filter_value(filters, "process_model_identifier"):
process_model = ProcessModelService.get_process_model(
@ -483,6 +490,7 @@ class ProcessInstanceReportService:
and_(HumanTaskUserModel.human_task_id == HumanTaskModel.id, HumanTaskUserModel.user_id == user.id),
)
human_task_already_joined = True
restrict_human_tasks_to_user = user
if user_group_identifier is not None:
group_model_join_conditions = [GroupModel.id == HumanTaskModel.lane_assignment_id]
@ -573,7 +581,7 @@ class ProcessInstanceReportService:
for value in cls.check_filter_value(filters, "with_oldest_open_task"):
if value is True:
results = cls.add_human_task_fields(results)
results = cls.add_human_task_fields(results, restrict_human_tasks_to_user=restrict_human_tasks_to_user)
report_metadata["filter_by"] = filters
response_json = {

View File

@ -1,36 +1,51 @@
import { useEffect, useState } from 'react';
import HttpService from '../services/HttpService';
import {
encodeBase64,
refreshAtInterval,
REFRESH_TIMEOUT_SECONDS,
} from '../helpers';
import { User } from '../interfaces';
import { refreshAtInterval, REFRESH_TIMEOUT_SECONDS } from '../helpers';
async function sha256(message: string) {
// encode as UTF-8
const msgBuffer = new TextEncoder().encode(message);
// hash the message
const hashBuffer = await crypto.subtle.digest('SHA-256', msgBuffer);
// convert ArrayBuffer to Array
const hashArray = Array.from(new Uint8Array(hashBuffer));
// convert bytes to hex string
return hashArray.map((b) => b.toString(16).padStart(2, '0')).join('');
}
export default function ActiveUsers() {
// Handles getting and displaying active users.
const [activeUsers, setActiveUsers] = useState<User[]>([]);
const lastVisitedIdentifier = encodeBase64(window.location.pathname);
useEffect(() => {
const updateActiveUsers = () => {
HttpService.makeCallToBackend({
path: `/active-users/updates/${lastVisitedIdentifier}`,
successCallback: setActiveUsers,
httpMethod: 'POST',
});
};
const unregisterUser = () => {
HttpService.makeCallToBackend({
path: `/active-users/unregister/${lastVisitedIdentifier}`,
successCallback: setActiveUsers,
httpMethod: 'POST',
});
const makeCall = (lastVisitedIdentifier: any) => {
HttpService.makeCallToBackend({
path: `/active-users/updates/${lastVisitedIdentifier}`,
successCallback: setActiveUsers,
httpMethod: 'POST',
});
};
sha256(window.location.pathname).then(makeCall);
};
updateActiveUsers();
const unregisterUser = () => {
const makeCall = (lastVisitedIdentifier: any) => {
HttpService.makeCallToBackend({
path: `/active-users/unregister/${lastVisitedIdentifier}`,
successCallback: setActiveUsers,
httpMethod: 'POST',
});
};
sha256(window.location.pathname).then(makeCall);
};
return refreshAtInterval(
15,
REFRESH_TIMEOUT_SECONDS,

View File

@ -425,11 +425,7 @@ export default function ReactDiagramEditor({
}
const canvas = (modeler as any).get('canvas');
// only get the canvas if the dmn active viewer is actually
// a Modeler and not an Editor which is what it will be when we are
// actively editing a decision table
canvas.zoom(FitViewport, 'auto');
canvas.zoom(FitViewport, 'auto'); // Concerned this might bug out somehow.
// highlighting a field
// Option 3 at:

View File

@ -114,7 +114,15 @@ export default function TypeaheadWidget({
onInputChange={typeaheadSearch}
onChange={(event: any) => {
setSelectedItem(event.selectedItem);
onChange(JSON.stringify(event.selectedItem));
let valueToUse = event.selectedItem;
// if the value is not truthy then do not stringify it
// otherwise things like null becomes "null"
if (valueToUse) {
valueToUse = JSON.stringify(valueToUse);
}
onChange(valueToUse);
}}
id={id}
items={items}