Skip to content

Commit

Permalink
Merge 7996555 into 521b0d3
Browse files Browse the repository at this point in the history
  • Loading branch information
benbosman committed Mar 27, 2020
2 parents 521b0d3 + 7996555 commit 4b24fed
Show file tree
Hide file tree
Showing 39 changed files with 723 additions and 404 deletions.
6 changes: 5 additions & 1 deletion src/app/core/core.module.ts
Expand Up @@ -146,6 +146,8 @@ import { VersionDataService } from './data/version-data.service';
import { VersionHistoryDataService } from './data/version-history-data.service';
import { Version } from './shared/version.model';
import { VersionHistory } from './shared/version-history.model';
import { WorkflowActionDataService } from './data/workflow-action-data.service';
import { WorkflowAction } from './tasks/models/workflow-action-object.model';

/**
* When not in production, endpoint responses can be mocked for testing purposes
Expand Down Expand Up @@ -263,6 +265,7 @@ const PROVIDERS = [
VersionHistoryDataService,
LicenseDataService,
ItemTypeDataService,
WorkflowActionDataService,
// register AuthInterceptor as HttpInterceptor
{
provide: HTTP_INTERCEPTORS,
Expand Down Expand Up @@ -312,7 +315,8 @@ export const models =
ExternalSource,
ExternalSourceEntry,
Version,
VersionHistory
VersionHistory,
WorkflowAction
];

@NgModule({
Expand Down
41 changes: 41 additions & 0 deletions src/app/core/data/workflow-action-data.service.ts
@@ -0,0 +1,41 @@
import { DataService } from './data.service';
import { WorkflowAction } from '../tasks/models/workflow-action-object.model';
import { RequestService } from './request.service';
import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service';
import { Store } from '@ngrx/store';
import { CoreState } from '../core.reducers';
import { ObjectCacheService } from '../cache/object-cache.service';
import { HALEndpointService } from '../shared/hal-endpoint.service';
import { NotificationsService } from '../../shared/notifications/notifications.service';
import { HttpClient } from '@angular/common/http';
import { DefaultChangeAnalyzer } from './default-change-analyzer.service';
import { FindListOptions } from './request.models';
import { Observable } from 'rxjs/internal/Observable';
import { Injectable } from '@angular/core';
import { dataService } from '../cache/builders/build-decorators';
import { WORKFLOW_ACTION } from '../tasks/models/workflow-action-object.resource-type';

/**
* A service responsible for fetching/sending data from/to the REST API on the workflowactions endpoint
*/
@Injectable()
@dataService(WORKFLOW_ACTION)
export class WorkflowActionDataService extends DataService<WorkflowAction> {
protected linkPath = 'workflowactions';

constructor(
protected requestService: RequestService,
protected rdbService: RemoteDataBuildService,
protected store: Store<CoreState>,
protected objectCache: ObjectCacheService,
protected halService: HALEndpointService,
protected notificationsService: NotificationsService,
protected http: HttpClient,
protected comparator: DefaultChangeAnalyzer<WorkflowAction>) {
super();
}

getBrowseEndpoint(options: FindListOptions, linkPath?: string): Observable<string> {
return this.halService.getEndpoint(this.linkPath);
}
}
25 changes: 2 additions & 23 deletions src/app/core/tasks/claimed-task-data.service.spec.ts
Expand Up @@ -52,8 +52,7 @@ describe('ClaimedTaskDataService', () => {
options.headers = headers;
});

describe('approveTask', () => {

describe('submitTask', () => {
it('should call postToEndpoint method', () => {
const scopeId = '1234';
const body = {
Expand All @@ -63,33 +62,13 @@ describe('ClaimedTaskDataService', () => {
spyOn(service, 'postToEndpoint');
requestService.uriEncodeBody.and.returnValue(body);

service.approveTask(scopeId);

expect(service.postToEndpoint).toHaveBeenCalledWith(linkPath, body, scopeId, options);
});
});

describe('rejectTask', () => {

it('should call postToEndpoint method', () => {
const scopeId = '1234';
const reason = 'test reject';
const body = {
submit_reject: 'true',
reason
};

spyOn(service, 'postToEndpoint');
requestService.uriEncodeBody.and.returnValue(body);

service.rejectTask(reason, scopeId);
service.submitTask(scopeId, body);

expect(service.postToEndpoint).toHaveBeenCalledWith(linkPath, body, scopeId, options);
});
});

describe('returnToPoolTask', () => {

it('should call deleteById method', () => {
const scopeId = '1234';

Expand Down
28 changes: 4 additions & 24 deletions src/app/core/tasks/claimed-task-data.service.ts
Expand Up @@ -35,7 +35,6 @@ export class ClaimedTaskDataService extends TasksService<ClaimedTask> {
*
* @param {RequestService} requestService
* @param {RemoteDataBuildService} rdbService
* @param {NormalizedObjectBuildService} linkService
* @param {Store<CoreState>} store
* @param {ObjectCacheService} objectCache
* @param {HALEndpointService} halService
Expand All @@ -56,35 +55,16 @@ export class ClaimedTaskDataService extends TasksService<ClaimedTask> {
}

/**
* Make a request to approve the given task
* Make a request for the given task
*
* @param scopeId
* The task id
* @param body
* The request body
* @return {Observable<ProcessTaskResponse>}
* Emit the server response
*/
public approveTask(scopeId: string): Observable<ProcessTaskResponse> {
const body = {
submit_approve: 'true'
};
return this.postToEndpoint(this.linkPath, this.requestService.uriEncodeBody(body), scopeId, this.makeHttpOptions());
}

/**
* Make a request to reject the given task
*
* @param reason
* The reason of reject
* @param scopeId
* The task id
* @return {Observable<ProcessTaskResponse>}
* Emit the server response
*/
public rejectTask(reason: string, scopeId: string): Observable<ProcessTaskResponse> {
const body = {
submit_reject: 'true',
reason
};
public submitTask(scopeId: string, body: any): Observable<ProcessTaskResponse> {
return this.postToEndpoint(this.linkPath, this.requestService.uriEncodeBody(body), scopeId, this.makeHttpOptions());
}

Expand Down
16 changes: 10 additions & 6 deletions src/app/core/tasks/models/task-object.model.ts
Expand Up @@ -13,6 +13,8 @@ import { HALLink } from '../../shared/hal-link.model';
import { WorkflowItem } from '../../submission/models/workflowitem.model';
import { TASK_OBJECT } from './task-object.resource-type';
import { WORKFLOWITEM } from '../../eperson/models/workflowitem.resource-type';
import { WORKFLOW_ACTION } from './workflow-action-object.resource-type';
import { WorkflowAction } from './workflow-action-object.model';

/**
* An abstract model class for a TaskObject.
Expand All @@ -34,12 +36,6 @@ export class TaskObject extends DSpaceObject implements CacheableObject {
@autoserialize
step: string;

/**
* The task action type
*/
@autoserialize
action: string;

/**
* The {@link HALLink}s for this TaskObject
*/
Expand All @@ -49,6 +45,7 @@ export class TaskObject extends DSpaceObject implements CacheableObject {
owner: HALLink;
group: HALLink;
workflowitem: HALLink;
action: HALLink;
};

/**
Expand All @@ -72,4 +69,11 @@ export class TaskObject extends DSpaceObject implements CacheableObject {
@link(WORKFLOWITEM)
workflowitem?: Observable<RemoteData<WorkflowItem>> | WorkflowItem;

/**
* The task action type
* Will be undefined unless the group {@link HALLink} has been resolved.
*/
@link(WORKFLOW_ACTION, false, 'action')
action: Observable<RemoteData<WorkflowAction>>;

}
25 changes: 25 additions & 0 deletions src/app/core/tasks/models/workflow-action-object.model.ts
@@ -0,0 +1,25 @@
import { inheritSerialization, autoserialize } from 'cerialize';
import { typedObject } from '../../cache/builders/build-decorators';
import { DSpaceObject } from '../../shared/dspace-object.model';
import { WORKFLOW_ACTION } from './workflow-action-object.resource-type';

/**
* A model class for a WorkflowAction
*/
@typedObject
@inheritSerialization(DSpaceObject)
export class WorkflowAction extends DSpaceObject {
static type = WORKFLOW_ACTION;

/**
* The workflow action's identifier
*/
@autoserialize
id: string;

/**
* The options available for this workflow action
*/
@autoserialize
options: string[];
}
@@ -0,0 +1,9 @@
import { ResourceType } from '../../shared/resource-type';

/**
* The resource type for WorkflowAction
*
* Needs to be in a separate file to prevent circular
* dependencies in webpack.
*/
export const WORKFLOW_ACTION = new ResourceType('workflowaction');
@@ -0,0 +1,61 @@
import { EventEmitter, Input, Output } from '@angular/core';
import { ClaimedTask } from '../../../../core/tasks/models/claimed-task-object.model';
import { BehaviorSubject } from 'rxjs/internal/BehaviorSubject';
import { ClaimedTaskDataService } from '../../../../core/tasks/claimed-task-data.service';
import { ProcessTaskResponse } from '../../../../core/tasks/models/process-task-response';

/**
* Abstract component for rendering a claimed task's action
* To create a child-component for a new option:
* - Set the "option" of the component
* - Add a @rendersWorkflowTaskOption annotation to your component providing the same enum value
* - Optionally overwrite createBody if the request body requires more than just the option
*/
export abstract class ClaimedTaskActionsAbstractComponent {
/**
* The workflow task option the child component represents
*/
abstract option: string;

/**
* The Claimed Task to display an action for
*/
@Input() object: ClaimedTask;

/**
* Emits the success or failure of a processed action
*/
@Output() processCompleted: EventEmitter<boolean> = new EventEmitter<boolean>();

/**
* A boolean representing if the operation is pending
*/
processing$ = new BehaviorSubject<boolean>(false);

constructor(protected claimedTaskService: ClaimedTaskDataService) {
}

/**
* Create a request body for submitting the task
* Overwrite this method in the child component if the body requires more than just the option
*/
createbody(): any {
return {
[this.option]: 'true'
};
}

/**
* Submit the task for this option
* While the task is submitting, processing$ is set to true and processCompleted emits the response's status when
* completed
*/
submitTask() {
this.processing$.next(true);
this.claimedTaskService.submitTask(this.object.id, this.createbody())
.subscribe((res: ProcessTaskResponse) => {
this.processing$.next(false);
this.processCompleted.emit(res.hasSucceeded);
});
}
}
@@ -1,8 +1,8 @@
<button type="button"
[className]="'btn btn-success ' + wrapperClass"
[className]="'btn btn-success'"
ngbTooltip="{{'submission.workflow.tasks.claimed.approve_help' | translate}}"
[disabled]="processingApprove"
(click)="confirmApprove()">
<span *ngIf="processingApprove"><i class='fas fa-circle-notch fa-spin'></i> {{'submission.workflow.tasks.generic.processing' | translate}}</span>
<span *ngIf="!processingApprove"><i class="fa fa-thumbs-up"></i> {{'submission.workflow.tasks.claimed.approve' | translate}}</span>
[disabled]="processing$ | async"
(click)="submitTask()">
<span *ngIf="processing$ | async"><i class='fas fa-circle-notch fa-spin'></i> {{'submission.workflow.tasks.generic.processing' | translate}}</span>
<span *ngIf="!(processing$ | async)"><i class="fa fa-thumbs-up"></i> {{'submission.workflow.tasks.claimed.approve' | translate}}</span>
</button>

0 comments on commit 4b24fed

Please sign in to comment.