File

projects/netgrif-components-core/src/lib/task/services/delegate-task.service.ts

Description

Service that handles the logic of delegating a task.

Extends

TaskHandlingService

Index

Methods

Constructor

constructor(_log: LoggerService, _sideMenuService: SideMenuService, _taskResourceService: TaskResourceService, _snackBar: SnackBarService, _translate: TranslateService, _taskState: TaskRequestStateService, _taskEvent: TaskEventService, _taskDataService: TaskDataService, _eventQueue: EventQueueService, _eventService: EventService, _changedFieldsService: ChangedFieldsService, _taskOperations: TaskOperations, _userAssignComponent: any, _selectedCaseService: SelectedCaseService, _taskContentService: TaskContentService)
Parameters :
Name Type Optional
_log LoggerService No
_sideMenuService SideMenuService No
_taskResourceService TaskResourceService No
_snackBar SnackBarService No
_translate TranslateService No
_taskState TaskRequestStateService No
_taskEvent TaskEventService No
_taskDataService TaskDataService No
_eventQueue EventQueueService No
_eventService EventService No
_changedFieldsService ChangedFieldsService No
_taskOperations TaskOperations No
_userAssignComponent any No
_selectedCaseService SelectedCaseService No
_taskContentService TaskContentService No

Methods

Protected completeActions
completeActions(afterAction: AfterAction, nextEvent: AfterAction, result: boolean, outcome?: TaskEventOutcome)

Completes all the action streams and sends the notification, with the provided result

Parameters :
Name Type Optional
afterAction AfterAction No
nextEvent AfterAction No
result boolean No
outcome TaskEventOutcome Yes
Returns : void
Protected completeSuccess
completeSuccess(afterAction: AfterAction, nextEvent: AfterAction, outcome?: TaskEventOutcome)

Reloads the task and emits true to the afterAction stream

Parameters :
Name Type Optional
afterAction AfterAction No
nextEvent AfterAction No
outcome TaskEventOutcome Yes
Returns : void
Public delegate
delegate(afterAction: AfterAction)

Performs the 'delegate' operation on the task held by TaskContentService.

Doesn't send any requests if the loading indicator is in it's active state. Otherwise sets the indicator to the active state and disables it once the request response is received.

The argument can be used to chain operations together, or to execute code conditionally based on the success state of the delegate operation.

If the task held within the TaskContentService changes before a response is received, the response will be ignored and the afterAction will not be executed.

Parameters :
Name Type Optional Default value Description
afterAction AfterAction No new AfterAction()

if delegate completes successfully true will be emitted into this Subject, otherwise false will be emitted

Returns : void
Protected performDelegateRequest
performDelegateRequest(afterAction: AfterAction, delegatedTaskId: string, delegatedUserId: any, nextEvent: AfterAction)

Performs a delegate request on the task currently stored in the taskContent service

Parameters :
Name Type Optional Description
afterAction AfterAction No

the action that should be performed after the request is processed

delegatedTaskId string No

id of the task that is being delegated

delegatedUserId any No

id of the user whom the task is being delegated

nextEvent AfterAction No

indicates to the event queue that the next event can be processed

Returns : void
Protected sendNotification
sendNotification(success: boolean, outcome?: TaskEventOutcome)

Publishes a delegate notification to the TaskEventService

Parameters :
Name Type Optional Description
success boolean No

whether the delegate operation was successful or not

outcome TaskEventOutcome Yes
Returns : void
Protected isTaskPresent
isTaskPresent()
Inherited from TaskHandlingService
Returns : boolean

true if a {

Protected isTaskRelevant
isTaskRelevant(requestedTaskId: string)
Inherited from TaskHandlingService

Checks whether the current state of the TaskContentService and optionally if the SelectedCaseService, is still relevant to the task that was requested.

This method is useful if you use UnlimitedTaskContentService, or a similar implementation. It is possible for the currently "selected" task to change in-between a backend request was sent and the response was received. In that case the response is no longer relevant and should be discarded, otherwise an illegal task state could be achieved on frontend.

Parameters :
Name Type Optional Description
requestedTaskId string No

the stringId of the requested task

Returns : boolean

true if the requested task is still relevant to the state of the frontend. Returns false otherwise.

import {Inject, Injectable, Optional} from '@angular/core';
import {SideMenuSize} from '../../side-menu/models/side-menu-size';
import {LoggerService} from '../../logger/services/logger.service';
import {SideMenuService} from '../../side-menu/services/side-menu.service';
import {TaskResourceService} from '../../resources/engine-endpoint/task-resource.service';
import {TaskContentService} from '../../task-content/services/task-content.service';
import {SnackBarService} from '../../snack-bar/services/snack-bar.service';
import {TranslateService} from '@ngx-translate/core';
import {TaskRequestStateService} from './task-request-state.service';
import {TaskHandlingService} from './task-handling-service';
import {NAE_TASK_OPERATIONS} from '../models/task-operations-injection-token';
import {TaskOperations} from '../interfaces/task-operations';
import {UserListInjectedData} from '../../side-menu/content-components/user-assign/model/user-list-injected-data';
import {UserValue} from '../../data-fields/user-field/models/user-value';
import {SelectedCaseService} from './selected-case.service';
import {NAE_USER_ASSIGN_COMPONENT} from '../../side-menu/content-components/injection-tokens';
import {createTaskEventNotification} from '../../task-content/model/task-event-notification';
import {TaskEvent} from '../../task-content/model/task-event';
import {TaskEventService} from '../../task-content/services/task-event.service';
import {TaskDataService} from './task-data.service';
import {take} from 'rxjs/operators';
import {DelegateTaskEventOutcome} from '../../event/model/event-outcomes/task-outcomes/delegate-task-event-outcome';
import {EventOutcomeMessageResource} from '../../resources/interface/message-resource';
import {EventQueueService} from '../../event-queue/services/event-queue.service';
import {QueuedEvent} from '../../event-queue/model/queued-event';
import {AfterAction} from '../../utility/call-chain/after-action';
import {ChangedFieldsService} from '../../changed-fields/services/changed-fields.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';


/**
 * Service that handles the logic of delegating a task.
 */
@Injectable()
export class DelegateTaskService extends TaskHandlingService {

    constructor(protected _log: LoggerService,
                protected _sideMenuService: SideMenuService,
                protected _taskResourceService: TaskResourceService,
                protected _snackBar: SnackBarService,
                protected _translate: TranslateService,
                protected _taskState: TaskRequestStateService,
                protected _taskEvent: TaskEventService,
                protected _taskDataService: TaskDataService,
                protected _eventQueue: EventQueueService,
                protected _eventService: EventService,
                protected _changedFieldsService: ChangedFieldsService,
                @Inject(NAE_TASK_OPERATIONS) protected _taskOperations: TaskOperations,
                @Optional() @Inject(NAE_USER_ASSIGN_COMPONENT) protected _userAssignComponent: any,
                @Optional() _selectedCaseService: SelectedCaseService,
                _taskContentService: TaskContentService) {
        super(_taskContentService, _selectedCaseService);
    }

    /**
     * Performs the 'delegate' operation on the task held by {@link TaskContentService}.
     *
     * Doesn't send any requests if the loading indicator is in it's active state.
     * Otherwise sets the indicator to the active state and disables it once the request response is received.
     *
     * The argument can be used to chain operations together,
     * or to execute code conditionally based on the success state of the delegate operation.
     *
     * If the task held within the {@link TaskContentService} changes before a response is received, the response will be ignored
     * and the `afterAction` will not be executed.
     * @param afterAction if delegate completes successfully `true` will be emitted into this Subject, otherwise `false` will be emitted
     */
    public delegate(afterAction: AfterAction = new AfterAction()) {
        const delegatedTaskId = this._safeTask.stringId;

        if (this._taskState.isLoading(delegatedTaskId)) {
            return;
        }
        this._sideMenuService.open(this._userAssignComponent, SideMenuSize.MEDIUM,
            {
                roles: Object.keys(this._safeTask.roles).filter(role =>
                    this._safeTask.roles[role]['assign'] !== undefined && this._safeTask.roles[role]['assign']),
                value: !this._safeTask.user ? undefined : new UserValue(
                    this._safeTask.user.id, this._safeTask.user.name, this._safeTask.user.surname, this._safeTask.user.email
                ),
                negativeRoles: Object.keys(this._safeTask.roles).filter(role =>
                    this._safeTask.roles[role]['assign'] !== undefined && !this._safeTask.roles[role]['assign'])
            } as UserListInjectedData).onClose.subscribe(event => {

            this._log.debug('Delegate sidemenu event:' + event);
            if (event.data === undefined) {
                return;
            }

            this._eventQueue.scheduleEvent(new QueuedEvent(
                () => {
                    const result = this.isTaskRelevant(delegatedTaskId);
                    if (!result) {
                        this._log.debug('current task changed before the delegate side menu data was received, discarding...');
                    }
                    return result;
                },
                nextEvent => {
                    this.performDelegateRequest(afterAction, delegatedTaskId, event.data.id, nextEvent);
                }
            ));
        });
    }

    /**
     * Performs a `delegate` request on the task currently stored in the `taskContent` service
     * @param afterAction the action that should be performed after the request is processed
     * @param delegatedTaskId id of the task that is being delegated
     * @param delegatedUserId id of the user whom the task is being delegated
     * @param nextEvent indicates to the event queue that the next event can be processed
     */
    protected performDelegateRequest(afterAction: AfterAction, delegatedTaskId: string, delegatedUserId: any, nextEvent: AfterAction) {
        this._taskState.startLoading(delegatedTaskId);
        this._taskResourceService.delegateTask(this._safeTask.stringId, delegatedUserId).pipe(take(1)).subscribe(
            (outcomeResource: EventOutcomeMessageResource) => {
            this._taskState.stopLoading(delegatedTaskId);
            if (!this.isTaskRelevant(delegatedTaskId)) {
                this._log.debug('current task changed before the delegate response could be received, discarding...');
                nextEvent.resolve(false);
                return;
            }

            if (outcomeResource.success) {
                this._taskContentService.updateStateData(outcomeResource.outcome as DelegateTaskEventOutcome);
                const changedFieldsMap: ChangedFieldsMap = this._eventService
                    .parseChangedFieldsFromOutcomeTree(outcomeResource.outcome);
                if (!!changedFieldsMap) {
                    this._changedFieldsService.emitChangedFields(changedFieldsMap);
                }
                this.completeSuccess(afterAction, nextEvent, outcomeResource.outcome as DelegateTaskEventOutcome);
            } else if (outcomeResource.error) {
                this._snackBar.openErrorSnackBar(outcomeResource.error);
                this.completeActions(afterAction, nextEvent, false);
            }
        }, error => {
            this._taskState.stopLoading(delegatedTaskId);
            this._log.debug('getting task data failed', error);

            if (!this.isTaskRelevant(delegatedTaskId)) {
                this._log.debug('current task changed before the delegate error could be received');
                nextEvent.resolve(false);
                return;
            }

            this._snackBar.openErrorSnackBar(`${this._translate.instant('tasks.snackbar.assignTask')}
                     ${this._task} ${this._translate.instant('tasks.snackbar.failed')}`);
            this.completeActions(afterAction, nextEvent, false);
        });
    }

    /**
     * Reloads the task and emits `true` to the `afterAction` stream
     */
    protected completeSuccess(afterAction: AfterAction, nextEvent: AfterAction, outcome?: TaskEventOutcome): void {
        this._taskOperations.reload();
        this.completeActions(afterAction, nextEvent, true, outcome);
    }

    /**
     * Completes all the action streams and sends the notification, with the provided result
     */
    protected completeActions(afterAction: AfterAction, nextEvent: AfterAction, result: boolean, outcome?: TaskEventOutcome) {
        this.sendNotification(result, outcome);
        afterAction.resolve(result);
        nextEvent.resolve(result);
    }

    /**
     * Publishes a delegate notification to the {@link TaskEventService}
     * @param success whether the delegate operation was successful or not
     * @param outcome
     */
    protected sendNotification(success: boolean, outcome?: TaskEventOutcome): void {
        this._taskEvent.publishTaskEvent(createTaskEventNotification(this._safeTask, TaskEvent.DELEGATE, success, outcome));
    }
}

result-matching ""

    No results matching ""