Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ import {ChangedFieldsService} from '../../changed-fields/services/changed-fields
import {EventService} from '../../event/services/event.service';
import {ChangedFieldsMap} from '../../event/services/interfaces/changed-fields-map';
import {TaskEventOutcome} from '../../event/model/event-outcomes/task-outcomes/task-event-outcome';
import {FrontActionService} from '../../actions/services/front-action.service';
import {FrontAction} from '../../data-fields/models/changed-fields';


/**
Expand All @@ -42,6 +44,7 @@ export class AssignTaskService extends TaskHandlingService {
protected _eventQueue: EventQueueService,
protected _eventService: EventService,
protected _changedFieldsService: ChangedFieldsService,
protected _frontActionService: FrontActionService,
@Inject(NAE_TASK_OPERATIONS) protected _taskOperations: TaskOperations,
@Optional() _selectedCaseService: SelectedCaseService,
@Optional() protected _taskViewService: TaskViewService,
Expand Down Expand Up @@ -121,9 +124,15 @@ export class AssignTaskService extends TaskHandlingService {
this._taskContentService.updateStateData(outcomeResource.outcome as AssignTaskEventOutcome);
const changedFieldsMap: ChangedFieldsMap = this._eventService
.parseChangedFieldsFromOutcomeTree(outcomeResource.outcome);
const frontActions: Array<FrontAction> = this._eventService.parseFrontActionsFromOutcomeTree(outcomeResource.outcome);

if (!!changedFieldsMap) {
this._changedFieldsService.emitChangedFields(changedFieldsMap);
}
if (frontActions?.length > 0) {
this._frontActionService.runAll(frontActions);
}
Comment on lines +127 to +134
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Verify error handling and consistency with error path.

The front-action execution logic is well-structured with safe optional chaining on line 132. However, two aspects need verification:

  1. Error handling: Confirm that FrontActionService.runAll handles errors internally and won't throw unhandled exceptions that could disrupt the assign workflow.

  2. Error path consistency: The error path (lines 145-148) emits changed fields but does not parse or execute front actions. Verify this is intentional—should front actions also be executed when outcomeResource.error is true but an outcome is present?

Run the following script to examine the error handling in FrontActionService.runAll:


🏁 Script executed:

#!/bin/bash
# Description: Check FrontActionService.runAll implementation for error handling

# Find and display the runAll method implementation
ast-grep --pattern $'class FrontActionService {
  $$$
  runAll($$$) {
    $$$
  }
  $$$
}'

Length of output: 0


🏁 Script executed:

#!/bin/bash
# Locate the FrontActionService class declaration
rg -nP 'class\s+FrontActionService' -C3 -g '*.ts'

# Locate the runAll method within the codebase
rg -nP '\brunAll\s*\(' -C3 -g '*.ts'

Length of output: 5238


🏁 Script executed:

#!/bin/bash
# Display FrontActionService implementation
sed -n '1,200p' projects/netgrif-components-core/src/lib/actions/services/front-action.service.ts

# Locate run method definition
rg -nP 'public\s+run\(' -C3 -g projects/netgrif-components-core/src/lib/actions/services/front-action.service.ts

# Display assign-task.service.ts around error path
sed -n '120,200p' projects/netgrif-components-core/src/lib/task/services/assign-task.service.ts

Length of output: 5347


Add error handling to front action execution and ensure error path consistency

  • FrontActionService.runAll/run does not catch exceptions or guard against undefined handlers—wrap each call in try/catch and return early if get(...) returns no function to prevent uncaught errors.
  • In assign-task.service.ts error branch (L145–148), frontActions aren’t parsed or executed—confirm whether front actions should also run when outcomeResource.error is true.
🤖 Prompt for AI Agents
In projects/netgrif-components-core/src/lib/task/services/assign-task.service.ts
around lines 127 to 134, update front action execution to be defensive and add
consistent error-path handling: change the runAll invocation so each front
action call is checked for a valid handler (return early or skip if get(...)
yields undefined) and wrap each handler invocation in try/catch to prevent
exceptions from bubbling; additionally, in the error branch around lines 145–148
parse frontActions from outcomeResource.outcome the same way and execute them
(with the same guarded try/catch/handler-existence checks) so front actions are
consistently processed whether outcomeResource.error is true or false.


forceReload ? this._taskOperations.forceReload() : this._taskOperations.reload();
this.completeActions(afterAction, nextEvent, true, outcomeResource.outcome as AssignTaskEventOutcome);
this._snackBar.openSuccessSnackBar(!!outcomeResource.outcome.message
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,11 @@ import {QueuedEvent} from '../../event-queue/model/queued-event';
import {AfterAction} from '../../utility/call-chain/after-action';
import {PermissionService} from '../../authorization/permission/permission.service';
import {ChangedFieldsService} from '../../changed-fields/services/changed-fields.service';
import { EventService} from '../../event/services/event.service';
import {EventService} from '../../event/services/event.service';
import {ChangedFieldsMap} from '../../event/services/interfaces/changed-fields-map';
import {TaskEventOutcome} from '../../event/model/event-outcomes/task-outcomes/task-event-outcome';

import {FrontActionService} from '../../actions/services/front-action.service';
import {FrontAction} from '../../data-fields/models/changed-fields';
/**
* Service that handles the logic of canceling a task.
*/
Expand All @@ -49,7 +50,9 @@ export class CancelTaskService extends TaskHandlingService {
@Optional() _selectedCaseService: SelectedCaseService,
@Optional() protected _taskViewService: TaskViewService,
_taskContentService: TaskContentService,
protected permissionService: PermissionService) {
protected permissionService: PermissionService,
protected _frontActionService: FrontActionService
) {
super(_taskContentService, _selectedCaseService);
}

Expand Down Expand Up @@ -123,9 +126,15 @@ export class CancelTaskService extends TaskHandlingService {
this._taskContentService.updateStateData(outcomeResource.outcome as CancelTaskEventOutcome);
const changedFieldsMap: ChangedFieldsMap = this._eventService
.parseChangedFieldsFromOutcomeTree(outcomeResource.outcome);
const frontActions: Array<FrontAction> = this._eventService.parseFrontActionsFromOutcomeTree(outcomeResource.outcome);

if (!!changedFieldsMap) {
this._changedFieldsService.emitChangedFields(changedFieldsMap);
}
if (frontActions?.length > 0) {
this._frontActionService.runAll(frontActions);
}

forceReload ? this._taskOperations.forceReload() : this._taskOperations.reload();
this.completeActions(afterAction, nextEvent, true, outcomeResource.outcome as CancelTaskEventOutcome);
} else if (outcomeResource.error !== undefined) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ import {ChangedFieldsService} from '../../changed-fields/services/changed-fields
import {EventService} from '../../event/services/event.service';
import {ChangedFieldsMap} from '../../event/services/interfaces/changed-fields-map';
import {TaskEventOutcome} from '../../event/model/event-outcomes/task-outcomes/task-event-outcome';

import {FrontActionService} from '../../actions/services/front-action.service';
import {FrontAction} from '../../data-fields/models/changed-fields';

/**
* Service that handles the logic of finishing a task.
Expand All @@ -45,7 +46,8 @@ export class FinishTaskService extends TaskHandlingService {
protected _changedFieldsService: ChangedFieldsService,
@Inject(NAE_TASK_OPERATIONS) protected _taskOperations: TaskOperations,
@Optional() _selectedCaseService: SelectedCaseService,
_taskContentService: TaskContentService) {
_taskContentService: TaskContentService,
protected _frontActionService: FrontActionService) {
super(_taskContentService, _selectedCaseService);
}

Expand Down Expand Up @@ -136,9 +138,15 @@ export class FinishTaskService extends TaskHandlingService {
this._taskContentService.updateStateData(outcomeResource.outcome as FinishTaskEventOutcome);
const changedFieldsMap: ChangedFieldsMap = this._eventService
.parseChangedFieldsFromOutcomeTree(outcomeResource.outcome);
const frontActions: Array<FrontAction> = this._eventService.parseFrontActionsFromOutcomeTree(outcomeResource.outcome);

if (!!changedFieldsMap) {
this._changedFieldsService.emitChangedFields(changedFieldsMap);
}
if (frontActions?.length > 0) {
this._frontActionService.runAll(frontActions);
}

this._taskOperations.reload();
this.completeActions(afterAction, nextEvent, true, outcomeResource.outcome as FinishTaskEventOutcome);
this._taskOperations.close();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -489,7 +489,7 @@ export class TaskDataService extends TaskHandlingService implements OnDestroy {
if (Object.keys(changedFieldsMap).length > 0) {
this._changedFieldsService.emitChangedFields(changedFieldsMap);
}
if (!!frontActions && frontActions.length > 0) {
if (frontActions?.length > 0) {
this._frontActionService.runAll(frontActions);
}
Comment on lines +492 to 494
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

🧩 Analysis chain

LGTM! Optional chaining provides safe front action execution.

The optional chaining operator correctly handles cases where parseFrontActionsFromOutcomeTree may return undefined or null, preventing potential runtime errors. The execution order (after changed-fields emission, before cleanup) aligns with the integration pattern described in the PR objectives.

To confirm the optional chaining is necessary, verify whether parseFrontActionsFromOutcomeTree can return undefined or null:


🏁 Script executed:

#!/bin/bash
# Description: Check the return type and implementation of parseFrontActionsFromOutcomeTree

# Search for the method definition and its return type
ast-grep --pattern $'parseFrontActionsFromOutcomeTree($$$) {
  $$$
}'

# Also search for the method signature/declaration
rg -nP --type=ts -A 10 'parseFrontActionsFromOutcomeTree\s*\(' | head -50

Length of output: 6399


Remove unnecessary optional chaining on frontActions (task-data.service.ts:492–494)
parseFrontActionsFromOutcomeTree always returns an array, so frontActions is never undefined or null. Change

if (frontActions?.length > 0) {
    this._frontActionService.runAll(frontActions);
}

to

if (frontActions.length > 0) {
    this._frontActionService.runAll(frontActions);
}
🤖 Prompt for AI Agents
In projects/netgrif-components-core/src/lib/task/services/task-data.service.ts
around lines 492–494, remove the unnecessary optional chaining on frontActions
because parseFrontActionsFromOutcomeTree always returns an array; change the
conditional to check frontActions.length > 0 and call
this._frontActionService.runAll(frontActions) when true so the code uses a
direct length check instead of frontActions?.length.

this.clearWaitingForResponseFlag(context.body);
Expand Down
Loading