mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-07 01:54:15 +00:00
Merge remote-tracking branch 'atmire/w2p-98211_advanced-workflow-actions-7.2' into w2p-98211_advanced-workflow-actions-main
# Conflicts: # src/app/my-dspace-page/my-dspace-search.module.ts # src/app/shared/mydspace-actions/claimed-task/claimed-task-actions.component.html # src/app/shared/object-list/my-dspace-result-list-element/claimed-search-result/claimed-approved-search-result/claimed-approved-search-result-list-element.component.html # src/app/shared/object-list/my-dspace-result-list-element/claimed-search-result/claimed-approved-search-result/claimed-approved-search-result-list-element.component.spec.ts # src/app/shared/object-list/my-dspace-result-list-element/claimed-search-result/claimed-declined-search-result/claimed-declined-search-result-list-element.component.html # src/app/shared/object-list/my-dspace-result-list-element/claimed-search-result/claimed-declined-search-result/claimed-declined-search-result-list-element.component.spec.ts
This commit is contained in:
@@ -37,12 +37,30 @@ enum SubKey {
|
||||
SearchResultsDTO,
|
||||
}
|
||||
|
||||
/**
|
||||
* The layout config of the buttons in the last column
|
||||
*/
|
||||
export interface EPersonActionConfig {
|
||||
/**
|
||||
* The css classes that should be added to the button
|
||||
*/
|
||||
css?: string;
|
||||
/**
|
||||
* Whether the button should be disabled
|
||||
*/
|
||||
disabled: boolean;
|
||||
/**
|
||||
* The Font Awesome icon that should be used
|
||||
*/
|
||||
icon: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* The {@link EPersonActionConfig} that should be used to display the button. The remove config will be used when the
|
||||
* {@link EPerson} is already a member of the {@link Group} and the remove config will be used otherwise.
|
||||
*
|
||||
* *See {@link actionConfig} for an example*
|
||||
*/
|
||||
export interface EPersonListActionConfig {
|
||||
add: EPersonActionConfig;
|
||||
remove: EPersonActionConfig;
|
||||
|
@@ -25,6 +25,7 @@ import { ThemedItemListPreviewComponent } from '../shared/object-list/my-dspace-
|
||||
import { MyDSpaceItemStatusComponent } from '../shared/object-collection/shared/mydspace-item-status/my-dspace-item-status.component';
|
||||
import { JournalEntitiesModule } from '../entity-groups/journal-entities/journal-entities.module';
|
||||
import { MyDSpaceActionsModule } from '../shared/mydspace-actions/mydspace-actions.module';
|
||||
import { ClaimedDeclinedTaskSearchResultListElementComponent } from '../shared/object-list/my-dspace-result-list-element/claimed-search-result/claimed-declined-task-search-result/claimed-declined-task-search-result-list-element.component';
|
||||
|
||||
const ENTRY_COMPONENTS = [
|
||||
WorkspaceItemSearchResultListElementComponent,
|
||||
@@ -32,6 +33,7 @@ const ENTRY_COMPONENTS = [
|
||||
ClaimedSearchResultListElementComponent,
|
||||
ClaimedApprovedSearchResultListElementComponent,
|
||||
ClaimedDeclinedSearchResultListElementComponent,
|
||||
ClaimedDeclinedTaskSearchResultListElementComponent,
|
||||
PoolSearchResultListElementComponent,
|
||||
ItemSearchResultDetailElementComponent,
|
||||
WorkspaceItemSearchResultDetailElementComponent,
|
||||
|
@@ -7,8 +7,8 @@ import { getAdvancedWorkflowRoute } from '../../../../workflowitems-edit-page/wo
|
||||
/**
|
||||
* Abstract component for rendering an advanced claimed task's action
|
||||
* To create a child-component for a new option:
|
||||
* - Set the "option" and "workflowType" of the component
|
||||
* - Add a @rendersWorkflowTaskOption annotation to your component providing the same enum value
|
||||
* - Set the "{@link option}" and "{@link workflowType}" of the component
|
||||
* - Add a @{@link rendersWorkflowTaskOption} annotation to your component providing the same enum value
|
||||
*/
|
||||
@Component({
|
||||
selector: 'ds-advanced-claimed-task-action-abstract',
|
||||
|
@@ -1,8 +0,0 @@
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'ds-advanced-workflow-action-abstract',
|
||||
template: '',
|
||||
})
|
||||
export abstract class AdvancedWorkflowActionAbstractComponent {
|
||||
}
|
@@ -12,12 +12,5 @@
|
||||
[routerLink]="[getWorkflowItemViewRoute(workflowitem)]">
|
||||
<i class="fa fa-info-circle"></i> {{"submission.workflow.generic.view" | translate}}
|
||||
</button>
|
||||
|
||||
<ds-claimed-task-actions-loader [item]="item"
|
||||
[option]="returnToPoolOption"
|
||||
[object]="object"
|
||||
[workflowitem]="workflowitem"
|
||||
(processCompleted)="this.processCompleted.emit($event)">
|
||||
</ds-claimed-task-actions-loader>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
@@ -14,7 +14,6 @@ import { RequestService } from '../../../core/data/request.service';
|
||||
import { SearchService } from '../../../core/shared/search/search.service';
|
||||
import { WorkflowAction } from '../../../core/tasks/models/workflow-action-object.model';
|
||||
import { WorkflowActionDataService } from '../../../core/data/workflow-action-data.service';
|
||||
import { WORKFLOW_TASK_OPTION_RETURN_TO_POOL } from './return-to-pool/claimed-task-actions-return-to-pool.component';
|
||||
import { getWorkflowItemViewRoute } from '../../../workflowitems-edit-page/workflowitems-edit-page-routing-paths';
|
||||
import { Item } from '../../../core/shared/item.model';
|
||||
|
||||
@@ -48,12 +47,6 @@ export class ClaimedTaskActionsComponent extends MyDSpaceActionsComponent<Claime
|
||||
*/
|
||||
public actionRD$: Observable<RemoteData<WorkflowAction>>;
|
||||
|
||||
/**
|
||||
* The option used to render the "return to pool" component
|
||||
* Every claimed task contains this option
|
||||
*/
|
||||
public returnToPoolOption = WORKFLOW_TASK_OPTION_RETURN_TO_POOL;
|
||||
|
||||
/**
|
||||
* Initialize instance variables
|
||||
*
|
||||
|
@@ -6,6 +6,12 @@ import { NotificationsService } from '../../../notifications/notifications.servi
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { SearchService } from '../../../../core/shared/search/search.service';
|
||||
import { RequestService } from '../../../../core/data/request.service';
|
||||
import { DSpaceObject } from '../../../../core/shared/dspace-object.model';
|
||||
import {
|
||||
ClaimedDeclinedTaskTaskSearchResult
|
||||
} from '../../../object-collection/shared/claimed-declined-task-task-search-result.model';
|
||||
import { Observable, of as observableOf } from 'rxjs';
|
||||
import { RemoteData } from 'src/app/core/data/remote-data';
|
||||
|
||||
export const WORKFLOW_TASK_OPTION_DECLINE_TASK = 'submit_decline_task';
|
||||
|
||||
@@ -31,4 +37,14 @@ export class ClaimedTaskActionsDeclineTaskComponent extends ClaimedTaskActionsAb
|
||||
super(injector, router, notificationsService, translate, searchService, requestService);
|
||||
}
|
||||
|
||||
reloadObjectExecution(): Observable<RemoteData<DSpaceObject> | DSpaceObject> {
|
||||
return observableOf(this.object);
|
||||
}
|
||||
|
||||
convertReloadedObject(dso: DSpaceObject): DSpaceObject {
|
||||
return Object.assign(new ClaimedDeclinedTaskTaskSearchResult(), dso, {
|
||||
indexableObject: dso
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -2,7 +2,7 @@ import { ClaimedTask } from '../../../core/tasks/models/claimed-task-object.mode
|
||||
import { SearchResult } from '../../search/models/search-result.model';
|
||||
|
||||
/**
|
||||
* Represents a search result object of a Declined ClaimedTask object
|
||||
* Represents a search result object of a Declined/Rejected ClaimedTask object (sent back to the submitter)
|
||||
*/
|
||||
export class ClaimedDeclinedTaskSearchResult extends SearchResult<ClaimedTask> {
|
||||
}
|
||||
|
@@ -0,0 +1,8 @@
|
||||
import { ClaimedTask } from '../../../core/tasks/models/claimed-task-object.model';
|
||||
import { SearchResult } from '../../search/models/search-result.model';
|
||||
|
||||
/**
|
||||
* Represents a search result object of a Declined ClaimedTask object (sent back to the Review Managers)
|
||||
*/
|
||||
export class ClaimedDeclinedTaskTaskSearchResult extends SearchResult<ClaimedTask> {
|
||||
}
|
@@ -6,4 +6,5 @@ export enum MyDspaceItemStatusType {
|
||||
ARCHIVED = 'mydspace.status.archived',
|
||||
DECLINED = 'mydspace.status.declined',
|
||||
APPROVED = 'mydspace.status.approved',
|
||||
DECLINED_TASk = 'mydspace.status.declined-task',
|
||||
}
|
||||
|
@@ -1,6 +1,6 @@
|
||||
<ng-container *ngVar="(workflowitemRD$ | async)?.payload as workflowitem">
|
||||
<div class="alert alert-success w-100" role="alert">
|
||||
<h4 class="alert-heading">Approved</h4>
|
||||
<h4 class="alert-heading mb-0">{{ 'claimed-approved-search-result-list-element.title' | translate }}</h4>
|
||||
<ds-themed-item-list-preview *ngIf="workflowitem"
|
||||
[item]="(workflowitem?.item | async)?.payload"
|
||||
[object]="object"
|
||||
|
@@ -19,6 +19,7 @@ import { DSONameService } from '../../../../../core/breadcrumbs/dso-name.service
|
||||
import { DSONameServiceMock } from '../../../../mocks/dso-name.service.mock';
|
||||
import { APP_CONFIG } from '../../../../../../config/app-config.interface';
|
||||
import { environment } from '../../../../../../environments/environment';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
|
||||
let component: ClaimedApprovedSearchResultListElementComponent;
|
||||
let fixture: ComponentFixture<ClaimedApprovedSearchResultListElementComponent>;
|
||||
@@ -64,7 +65,10 @@ const linkService = getMockLinkService();
|
||||
describe('ClaimedApprovedSearchResultListElementComponent', () => {
|
||||
beforeEach(waitForAsync(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [NoopAnimationsModule],
|
||||
imports: [
|
||||
TranslateModule.forRoot(),
|
||||
NoopAnimationsModule,
|
||||
],
|
||||
declarations: [ClaimedApprovedSearchResultListElementComponent, VarDirective],
|
||||
providers: [
|
||||
{ provide: TruncatableService, useValue: {} },
|
||||
|
@@ -1,6 +1,6 @@
|
||||
<ng-container *ngVar="(workflowitemRD$ | async)?.payload as workflowitem">
|
||||
<div class="alert alert-secondary w-100" role="alert">
|
||||
<h4 class="alert-heading">Declined</h4>
|
||||
<h4 class="alert-heading mb-0">{{ 'claimed-declined-search-result-list-element.title' | translate }}</h4>
|
||||
<ds-themed-item-list-preview *ngIf="workflowitem"
|
||||
[item]="(workflowitem?.item | async)?.payload"
|
||||
[object]="object"
|
||||
|
@@ -19,6 +19,7 @@ import { DSONameService } from '../../../../../core/breadcrumbs/dso-name.service
|
||||
import { DSONameServiceMock } from '../../../../mocks/dso-name.service.mock';
|
||||
import { APP_CONFIG } from '../../../../../../config/app-config.interface';
|
||||
import { environment } from '../../../../../../environments/environment';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
|
||||
let component: ClaimedDeclinedSearchResultListElementComponent;
|
||||
let fixture: ComponentFixture<ClaimedDeclinedSearchResultListElementComponent>;
|
||||
@@ -64,7 +65,10 @@ const linkService = getMockLinkService();
|
||||
describe('ClaimedDeclinedSearchResultListElementComponent', () => {
|
||||
beforeEach(waitForAsync(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [NoopAnimationsModule],
|
||||
imports: [
|
||||
TranslateModule.forRoot(),
|
||||
NoopAnimationsModule,
|
||||
],
|
||||
declarations: [ClaimedDeclinedSearchResultListElementComponent, VarDirective],
|
||||
providers: [
|
||||
{ provide: TruncatableService, useValue: {} },
|
@@ -0,0 +1,11 @@
|
||||
<ng-container *ngVar="(workflowitemRD$ | async)?.payload as workflowitem">
|
||||
<div class="alert alert-warning w-100" role="alert">
|
||||
<h4 class="alert-heading mb-0">{{ 'claimed-declined-task-search-result-list-element.title' | translate }}</h4>
|
||||
<ds-themed-item-list-preview *ngIf="workflowitem"
|
||||
[item]="(workflowitem?.item | async)?.payload"
|
||||
[object]="object"
|
||||
[status]="status"
|
||||
[showSubmitter]="showSubmitter">
|
||||
</ds-themed-item-list-preview>
|
||||
</div>
|
||||
</ng-container>
|
@@ -0,0 +1,109 @@
|
||||
import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core';
|
||||
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { of as observableOf } from 'rxjs';
|
||||
import { ClaimedDeclinedTaskSearchResultListElementComponent } from './claimed-declined-task-search-result-list-element.component';
|
||||
import { ClaimedDeclinedTaskTaskSearchResult } from '../../../../object-collection/shared/claimed-declined-task-task-search-result.model';
|
||||
import { Item } from '../../../../../core/shared/item.model';
|
||||
import { createSuccessfulRemoteDataObject } from '../../../../remote-data.utils';
|
||||
import { WorkflowItem } from '../../../../../core/submission/models/workflowitem.model';
|
||||
import { ClaimedTask } from '../../../../../core/tasks/models/claimed-task-object.model';
|
||||
import { getMockLinkService } from '../../../../mocks/link-service.mock';
|
||||
import { VarDirective } from '../../../../utils/var.directive';
|
||||
import { TruncatableService } from '../../../../truncatable/truncatable.service';
|
||||
import { LinkService } from '../../../../../core/cache/builders/link.service';
|
||||
import { MyDspaceItemStatusType } from '../../../../object-collection/shared/mydspace-item-status/my-dspace-item-status-type';
|
||||
import { DSONameService } from '../../../../../core/breadcrumbs/dso-name.service';
|
||||
import { DSONameServiceMock } from '../../../../mocks/dso-name.service.mock';
|
||||
import { APP_CONFIG } from '../../../../../../config/app-config.interface';
|
||||
import { environment } from '../../../../../../environments/environment';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
|
||||
let component: ClaimedDeclinedTaskSearchResultListElementComponent;
|
||||
let fixture: ComponentFixture<ClaimedDeclinedTaskSearchResultListElementComponent>;
|
||||
|
||||
const mockResultObject: ClaimedDeclinedTaskTaskSearchResult = new ClaimedDeclinedTaskTaskSearchResult();
|
||||
mockResultObject.hitHighlights = {};
|
||||
|
||||
const item = Object.assign(new Item(), {
|
||||
bundles: observableOf({}),
|
||||
metadata: {
|
||||
'dc.title': [
|
||||
{
|
||||
language: 'en_US',
|
||||
value: 'This is just another title'
|
||||
}
|
||||
],
|
||||
'dc.type': [
|
||||
{
|
||||
language: null,
|
||||
value: 'Article'
|
||||
}
|
||||
],
|
||||
'dc.contributor.author': [
|
||||
{
|
||||
language: 'en_US',
|
||||
value: 'Smith, Donald'
|
||||
}
|
||||
],
|
||||
'dc.date.issued': [
|
||||
{
|
||||
language: null,
|
||||
value: '2015-06-26'
|
||||
}
|
||||
]
|
||||
}
|
||||
});
|
||||
const rdItem = createSuccessfulRemoteDataObject(item);
|
||||
const workflowitem = Object.assign(new WorkflowItem(), { item: observableOf(rdItem) });
|
||||
const rdWorkflowitem = createSuccessfulRemoteDataObject(workflowitem);
|
||||
mockResultObject.indexableObject = Object.assign(new ClaimedTask(), { workflowitem: observableOf(rdWorkflowitem) });
|
||||
const linkService = getMockLinkService();
|
||||
|
||||
describe('ClaimedDeclinedTaskSearchResultListElementComponent', () => {
|
||||
beforeEach(waitForAsync(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [
|
||||
NoopAnimationsModule,
|
||||
TranslateModule.forRoot(),
|
||||
],
|
||||
declarations: [ClaimedDeclinedTaskSearchResultListElementComponent, VarDirective],
|
||||
providers: [
|
||||
{ provide: TruncatableService, useValue: {} },
|
||||
{ provide: LinkService, useValue: linkService },
|
||||
{ provide: DSONameService, useClass: DSONameServiceMock },
|
||||
{ provide: APP_CONFIG, useValue: environment },
|
||||
],
|
||||
schemas: [NO_ERRORS_SCHEMA]
|
||||
}).overrideComponent(ClaimedDeclinedTaskSearchResultListElementComponent, {
|
||||
set: { changeDetection: ChangeDetectionStrategy.Default }
|
||||
}).compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(waitForAsync(() => {
|
||||
fixture = TestBed.createComponent(ClaimedDeclinedTaskSearchResultListElementComponent);
|
||||
component = fixture.componentInstance;
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
component.dso = mockResultObject.indexableObject;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should init workflowitem properly', (done) => {
|
||||
component.workflowitemRD$.subscribe((workflowitemRD) => {
|
||||
expect(linkService.resolveLinks).toHaveBeenCalledWith(
|
||||
component.dso,
|
||||
jasmine.objectContaining({ name: 'workflowitem' }),
|
||||
jasmine.objectContaining({ name: 'action' })
|
||||
);
|
||||
expect(workflowitemRD.payload).toEqual(workflowitem);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should have properly status', () => {
|
||||
expect(component.status).toEqual(MyDspaceItemStatusType.DECLINED_TASk);
|
||||
});
|
||||
|
||||
});
|
@@ -0,0 +1,68 @@
|
||||
import { Component, Inject, OnInit } from '@angular/core';
|
||||
import { listableObjectComponent } from '../../../../object-collection/shared/listable-object/listable-object.decorator';
|
||||
import { ClaimedDeclinedTaskTaskSearchResult } from 'src/app/shared/object-collection/shared/claimed-declined-task-task-search-result.model';
|
||||
import { ViewMode } from '../../../../../core/shared/view-mode.model';
|
||||
import { LinkService } from '../../../../../core/cache/builders/link.service';
|
||||
import { TruncatableService } from '../../../../truncatable/truncatable.service';
|
||||
import { MyDspaceItemStatusType } from '../../../../object-collection/shared/mydspace-item-status/my-dspace-item-status-type';
|
||||
import { Observable } from 'rxjs';
|
||||
import { RemoteData } from '../../../../../core/data/remote-data';
|
||||
import { WorkflowItem } from '../../../../../core/submission/models/workflowitem.model';
|
||||
import { followLink } from '../../../../utils/follow-link-config.model';
|
||||
import { SearchResultListElementComponent } from '../../../search-result-list-element/search-result-list-element.component';
|
||||
import { ClaimedTaskSearchResult } from '../../../../object-collection/shared/claimed-task-search-result.model';
|
||||
import { ClaimedTask } from '../../../../../core/tasks/models/claimed-task-object.model';
|
||||
import { DSONameService } from '../../../../../core/breadcrumbs/dso-name.service';
|
||||
import { APP_CONFIG, AppConfig } from '../../../../../../config/app-config.interface';
|
||||
|
||||
/**
|
||||
* This component renders claimed task declined task object for the search result in the list view.
|
||||
*/
|
||||
@Component({
|
||||
selector: 'ds-claimed-declined-task-search-result-list-element',
|
||||
styleUrls: ['../../../search-result-list-element/search-result-list-element.component.scss'],
|
||||
templateUrl: './claimed-declined-task-search-result-list-element.component.html'
|
||||
})
|
||||
@listableObjectComponent(ClaimedDeclinedTaskTaskSearchResult, ViewMode.ListElement)
|
||||
export class ClaimedDeclinedTaskSearchResultListElementComponent extends SearchResultListElementComponent<ClaimedTaskSearchResult, ClaimedTask> implements OnInit {
|
||||
|
||||
/**
|
||||
* A boolean representing if to show submitter information
|
||||
*/
|
||||
public showSubmitter = true;
|
||||
|
||||
/**
|
||||
* Represent item's status
|
||||
*/
|
||||
public status = MyDspaceItemStatusType.DECLINED_TASk;
|
||||
|
||||
/**
|
||||
* The workflowitem object that belonging to the result object
|
||||
*/
|
||||
public workflowitemRD$: Observable<RemoteData<WorkflowItem>>;
|
||||
|
||||
public constructor(
|
||||
protected linkService: LinkService,
|
||||
protected truncatableService: TruncatableService,
|
||||
protected dsoNameService: DSONameService,
|
||||
@Inject(APP_CONFIG) protected appConfig: AppConfig,
|
||||
) {
|
||||
super(truncatableService, dsoNameService, appConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize all instance variables
|
||||
*/
|
||||
ngOnInit() {
|
||||
super.ngOnInit();
|
||||
this.linkService.resolveLinks(this.dso,
|
||||
followLink('workflowitem',
|
||||
{ useCachedVersionIfAvailable: false },
|
||||
followLink('item'),
|
||||
followLink('submitter')
|
||||
),
|
||||
followLink('action'));
|
||||
this.workflowitemRD$ = this.dso.workflowitem as Observable<RemoteData<WorkflowItem>>;
|
||||
}
|
||||
|
||||
}
|
12
src/app/shared/testing/request-service.stub.ts
Normal file
12
src/app/shared/testing/request-service.stub.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import { Observable, of as observableOf } from 'rxjs';
|
||||
|
||||
/**
|
||||
* Stub service for {@link RequestService}.
|
||||
*/
|
||||
export class RequestServiceStub {
|
||||
|
||||
removeByHrefSubstring(_href: string): Observable<boolean> {
|
||||
return observableOf(true);
|
||||
}
|
||||
|
||||
}
|
@@ -7,15 +7,15 @@
|
||||
</p>
|
||||
|
||||
<form (ngSubmit)="performAction()" *ngIf="ratingForm" [formGroup]="ratingForm">
|
||||
<div *ngVar="ratingForm.get('review').touched && !ratingForm.get('review').valid as invalid" class="form-group">
|
||||
<div class="form-group">
|
||||
<label class="control-label">
|
||||
<span>{{ 'advanced-workflow-action.rating.form.review.label' | translate }}</span>
|
||||
<span *ngIf="advancedInfo?.descriptionRequired">*</span>
|
||||
</label>
|
||||
<textarea [ngClass]="invalid ? 'is-invalid' : ''" [required]="advancedInfo?.descriptionRequired"
|
||||
class="form-control" formControlName="review">
|
||||
<textarea [ngClass]="{ 'is-invalid' : isInvalid('review') }"
|
||||
[required]="advancedInfo?.descriptionRequired" class="form-control" formControlName="review">
|
||||
</textarea>
|
||||
<small *ngIf="invalid" class="invalid-feedback d-block">
|
||||
<small *ngIf="isInvalid('review')" class="invalid-feedback d-block">
|
||||
{{ 'advanced-workflow-action.rating.form.review.error' | translate }}
|
||||
</small>
|
||||
</div>
|
||||
@@ -24,8 +24,12 @@
|
||||
<label class="control-label">
|
||||
{{ 'advanced-workflow-action.rating.form.rating.label' | translate }}*
|
||||
</label>
|
||||
<rating [max]="advancedInfo?.maxValue" class="d-block" formControlName="rating">
|
||||
<rating [max]="advancedInfo?.maxValue" [ngClass]="{ 'text-danger': isInvalid('rating') }"
|
||||
class="d-block" formControlName="rating">
|
||||
</rating>
|
||||
<small *ngIf="isInvalid('rating')" class="invalid-feedback d-block">
|
||||
{{ 'advanced-workflow-action.rating.form.rating.error' | translate }}
|
||||
</small>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
|
@@ -26,6 +26,8 @@ import { Item } from '../../../core/shared/item.model';
|
||||
import { NO_ERRORS_SCHEMA } from '@angular/core';
|
||||
import { ProcessTaskResponse } from '../../../core/tasks/models/process-task-response';
|
||||
import { RatingAdvancedWorkflowInfo } from '../../../core/tasks/models/rating-advanced-workflow-info.model';
|
||||
import { RequestService } from '../../../core/data/request.service';
|
||||
import { RequestServiceStub } from '../../../shared/testing/request-service.stub';
|
||||
|
||||
const claimedTaskId = '2';
|
||||
const workflowId = '1';
|
||||
@@ -80,6 +82,7 @@ describe('AdvancedWorkflowActionRatingComponent', () => {
|
||||
{ provide: Router, useValue: new RouterStub() },
|
||||
{ provide: WorkflowActionDataService, useValue: workflowActionDataService },
|
||||
{ provide: WorkflowItemDataService, useValue: workflowItemDataService },
|
||||
{ provide: RequestService, useClass: RequestServiceStub },
|
||||
],
|
||||
schemas: [NO_ERRORS_SCHEMA],
|
||||
}).compileComponents();
|
||||
|
@@ -3,11 +3,9 @@ import {
|
||||
rendersAdvancedWorkflowTaskOption
|
||||
} from '../../../shared/mydspace-actions/claimed-task/switcher/claimed-task-actions-decorator';
|
||||
import { AdvancedWorkflowActionComponent } from '../advanced-workflow-action/advanced-workflow-action.component';
|
||||
import { FormGroup, FormControl } from '@angular/forms';
|
||||
import { FormGroup, FormControl, Validators } from '@angular/forms';
|
||||
import { WorkflowAction } from '../../../core/tasks/models/workflow-action-object.model';
|
||||
import {
|
||||
RatingAdvancedWorkflowInfo
|
||||
} from '../../../core/tasks/models/rating-advanced-workflow-info.model';
|
||||
import { RatingAdvancedWorkflowInfo } from '../../../core/tasks/models/rating-advanced-workflow-info.model';
|
||||
|
||||
export const ADVANCED_WORKFLOW_TASK_OPTION_RATING = 'submit_score';
|
||||
export const ADVANCED_WORKFLOW_ACTION_RATING = 'scorereviewaction';
|
||||
@@ -30,7 +28,7 @@ export class AdvancedWorkflowActionRatingComponent extends AdvancedWorkflowActio
|
||||
super.ngOnInit();
|
||||
this.ratingForm = new FormGroup({
|
||||
review: new FormControl(''),
|
||||
rating: new FormControl(0),
|
||||
rating: new FormControl(0, Validators.min(1)),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -69,4 +67,13 @@ export class AdvancedWorkflowActionRatingComponent extends AdvancedWorkflowActio
|
||||
return workflowAction ? (workflowAction.advancedInfo[0] as RatingAdvancedWorkflowInfo) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the field is valid or not.
|
||||
*
|
||||
* @param formControlName The input field
|
||||
*/
|
||||
isInvalid(formControlName: string): boolean {
|
||||
return this.ratingForm.get(formControlName).touched && !this.ratingForm.get(formControlName).valid;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -23,6 +23,8 @@ import { Item } from '../../../core/shared/item.model';
|
||||
import { EPersonMock, EPersonMock2 } from '../../../shared/testing/eperson.mock';
|
||||
import { ProcessTaskResponse } from '../../../core/tasks/models/process-task-response';
|
||||
import { NO_ERRORS_SCHEMA } from '@angular/core';
|
||||
import { RequestService } from '../../../core/data/request.service';
|
||||
import { RequestServiceStub } from '../../../shared/testing/request-service.stub';
|
||||
|
||||
const claimedTaskId = '2';
|
||||
const workflowId = '1';
|
||||
@@ -73,6 +75,7 @@ describe('AdvancedWorkflowActionSelectReviewerComponent', () => {
|
||||
{ provide: RouteService, useValue: routeServiceStub },
|
||||
{ provide: WorkflowActionDataService, useValue: workflowActionDataService },
|
||||
{ provide: WorkflowItemDataService, useValue: workflowItemDataService },
|
||||
{ provide: RequestService, useClass: RequestServiceStub },
|
||||
],
|
||||
schemas: [NO_ERRORS_SCHEMA],
|
||||
}).compileComponents();
|
||||
|
@@ -19,6 +19,7 @@ import { NotificationsService } from '../../../shared/notifications/notification
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { WorkflowActionDataService } from '../../../core/data/workflow-action-data.service';
|
||||
import { ClaimedTaskDataService } from '../../../core/tasks/claimed-task-data.service';
|
||||
import { RequestService } from 'src/app/core/data/request.service';
|
||||
|
||||
export const ADVANCED_WORKFLOW_TASK_OPTION_SELECT_REVIEWER = 'submit_select_reviewer';
|
||||
export const ADVANCED_WORKFLOW_ACTION_SELECT_REVIEWER = 'selectrevieweraction';
|
||||
@@ -59,8 +60,9 @@ export class AdvancedWorkflowActionSelectReviewerComponent extends AdvancedWorkf
|
||||
protected translationService: TranslateService,
|
||||
protected workflowActionService: WorkflowActionDataService,
|
||||
protected claimedTaskDataService: ClaimedTaskDataService,
|
||||
protected requestService: RequestService,
|
||||
) {
|
||||
super(route, workflowItemService, router, routeService, notificationsService, translationService, workflowActionService, claimedTaskDataService);
|
||||
super(route, workflowItemService, router, routeService, notificationsService, translationService, workflowActionService, claimedTaskDataService, requestService);
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
@@ -130,4 +132,12 @@ export class AdvancedWorkflowActionSelectReviewerComponent extends AdvancedWorkf
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Hardcoded the previous page url because the {@link ReviewersListComponent} changes the previous route when
|
||||
* switching between the different pages
|
||||
*/
|
||||
previousPage(): void {
|
||||
void this.router.navigate(['/mydspace'], { queryParams: { configuration: 'workflow' } });
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -18,6 +18,8 @@ import { TranslateModule } from '@ngx-translate/core';
|
||||
import { WorkflowActionDataServiceStub } from '../../../shared/testing/workflow-action-data-service.stub';
|
||||
import { ProcessTaskResponse } from '../../../core/tasks/models/process-task-response';
|
||||
import { WorkflowItemDataServiceStub } from '../../../shared/testing/workflow-item-data-service.stub';
|
||||
import { RequestService } from '../../../core/data/request.service';
|
||||
import { RequestServiceStub } from '../../../shared/testing/request-service.stub';
|
||||
|
||||
const workflowId = '1';
|
||||
|
||||
@@ -65,6 +67,7 @@ describe('AdvancedWorkflowActionComponent', () => {
|
||||
{ provide: RouteService, useValue: routeServiceStub },
|
||||
{ provide: WorkflowActionDataService, useValue: workflowActionDataService },
|
||||
{ provide: WorkflowItemDataService, useValue: workflowItemDataService },
|
||||
{ provide: RequestService, useClass: RequestServiceStub },
|
||||
],
|
||||
}).compileComponents();
|
||||
});
|
||||
|
@@ -12,12 +12,13 @@ import { getFirstSucceededRemoteDataPayload } from '../../../core/shared/operato
|
||||
import { ClaimedTaskDataService } from '../../../core/tasks/claimed-task-data.service';
|
||||
import { map } from 'rxjs/operators';
|
||||
import { ProcessTaskResponse } from '../../../core/tasks/models/process-task-response';
|
||||
import { RequestService } from '../../../core/data/request.service';
|
||||
|
||||
/**
|
||||
* Abstract component for rendering an advanced claimed task's workflow page
|
||||
* To create a child-component for a new option:
|
||||
* - Set the "getType()" of the component
|
||||
* - Implement the createBody, should always contain at least the ADVANCED_WORKFLOW_TASK_OPTION
|
||||
* - Set the "{@link getType}()" of the component
|
||||
* - Implement the {@link createBody}, should always contain at least the ADVANCED_WORKFLOW_TASK_OPTION_*
|
||||
*/
|
||||
@Component({
|
||||
selector: 'ds-advanced-workflow-action',
|
||||
@@ -36,8 +37,9 @@ export abstract class AdvancedWorkflowActionComponent extends WorkflowItemAction
|
||||
protected translationService: TranslateService,
|
||||
protected workflowActionService: WorkflowActionDataService,
|
||||
protected claimedTaskDataService: ClaimedTaskDataService,
|
||||
protected requestService: RequestService,
|
||||
) {
|
||||
super(route, workflowItemService, router, routeService, notificationsService, translationService);
|
||||
super(route, workflowItemService, router, routeService, notificationsService, translationService, requestService);
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
|
@@ -16,6 +16,8 @@ import { TranslateLoaderMock } from '../shared/mocks/translate-loader.mock';
|
||||
import { ActivatedRouteStub } from '../shared/testing/active-router.stub';
|
||||
import { RouterStub } from '../shared/testing/router.stub';
|
||||
import { NotificationsServiceStub } from '../shared/testing/notifications-service.stub';
|
||||
import { RequestService } from '../core/data/request.service';
|
||||
import { RequestServiceStub } from '../shared/testing/request-service.stub';
|
||||
|
||||
const type = 'testType';
|
||||
describe('WorkflowItemActionPageComponent', () => {
|
||||
@@ -52,6 +54,7 @@ describe('WorkflowItemActionPageComponent', () => {
|
||||
{ provide: RouteService, useValue: {} },
|
||||
{ provide: NotificationsService, useClass: NotificationsServiceStub },
|
||||
{ provide: WorkflowItemDataService, useValue: wfiService },
|
||||
{ provide: RequestService, useClass: RequestServiceStub },
|
||||
],
|
||||
schemas: [NO_ERRORS_SCHEMA]
|
||||
})
|
||||
@@ -110,8 +113,10 @@ class TestComponent extends WorkflowItemActionPageComponent {
|
||||
protected router: Router,
|
||||
protected routeService: RouteService,
|
||||
protected notificationsService: NotificationsService,
|
||||
protected translationService: TranslateService) {
|
||||
super(route, workflowItemService, router, routeService, notificationsService, translationService);
|
||||
protected translationService: TranslateService,
|
||||
protected requestService: RequestService,
|
||||
) {
|
||||
super(route, workflowItemService, router, routeService, notificationsService, translationService, requestService);
|
||||
}
|
||||
|
||||
getType(): string {
|
||||
|
@@ -1,16 +1,17 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { Observable } from 'rxjs';
|
||||
import { Observable, forkJoin } from 'rxjs';
|
||||
import { map, switchMap, take } from 'rxjs/operators';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { WorkflowItem } from '../core/submission/models/workflowitem.model';
|
||||
import { Item } from '../core/shared/item.model';
|
||||
import { ActivatedRoute, Data, Router } from '@angular/router';
|
||||
import { ActivatedRoute, Data, Router, Params } from '@angular/router';
|
||||
import { WorkflowItemDataService } from '../core/submission/workflowitem-data.service';
|
||||
import { RouteService } from '../core/services/route.service';
|
||||
import { NotificationsService } from '../shared/notifications/notifications.service';
|
||||
import { RemoteData } from '../core/data/remote-data';
|
||||
import { getAllSucceededRemoteData, getRemoteDataPayload } from '../core/shared/operators';
|
||||
import { isEmpty } from '../shared/empty.util';
|
||||
import { RequestService } from '../core/data/request.service';
|
||||
|
||||
/**
|
||||
* Abstract component representing a page to perform an action on a workflow item
|
||||
@@ -29,7 +30,9 @@ export abstract class WorkflowItemActionPageComponent implements OnInit {
|
||||
protected router: Router,
|
||||
protected routeService: RouteService,
|
||||
protected notificationsService: NotificationsService,
|
||||
protected translationService: TranslateService) {
|
||||
protected translationService: TranslateService,
|
||||
protected requestService: RequestService,
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -45,9 +48,9 @@ export abstract class WorkflowItemActionPageComponent implements OnInit {
|
||||
* Performs the action and shows a notification based on the outcome of the action
|
||||
*/
|
||||
performAction() {
|
||||
this.wfi$.pipe(
|
||||
forkJoin([this.wfi$, this.requestService.removeByHrefSubstring('/discover')]).pipe(
|
||||
take(1),
|
||||
switchMap((wfi: WorkflowItem) => this.sendRequest(wfi.id))
|
||||
switchMap(([wfi]) => this.sendRequest(wfi.id))
|
||||
).subscribe((successful: boolean) => {
|
||||
if (successful) {
|
||||
const title = this.translationService.get('workflow-item.' + this.type + '.notification.success.title');
|
||||
@@ -72,7 +75,13 @@ export abstract class WorkflowItemActionPageComponent implements OnInit {
|
||||
if (isEmpty(url)) {
|
||||
url = '/mydspace';
|
||||
}
|
||||
this.router.navigateByUrl(url);
|
||||
const params: Params = {};
|
||||
if (url.split('?').length > 1) {
|
||||
for (const param of url.split('?')[1].split('&')) {
|
||||
params[param.split('=')[0]] = param.split('=')[1];
|
||||
}
|
||||
}
|
||||
void this.router.navigate([url.split('?')[0]], { queryParams: params });
|
||||
}
|
||||
);
|
||||
}
|
||||
|
@@ -27,7 +27,7 @@ export class WorkflowItemDeleteComponent extends WorkflowItemActionPageComponent
|
||||
protected notificationsService: NotificationsService,
|
||||
protected translationService: TranslateService,
|
||||
protected requestService: RequestService) {
|
||||
super(route, workflowItemService, router, routeService, notificationsService, translationService);
|
||||
super(route, workflowItemService, router, routeService, notificationsService, translationService, requestService);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -42,7 +42,6 @@ export class WorkflowItemDeleteComponent extends WorkflowItemActionPageComponent
|
||||
* @param id The id of the WorkflowItem
|
||||
*/
|
||||
sendRequest(id: string): Observable<boolean> {
|
||||
this.requestService.removeByHrefSubstring('/discover');
|
||||
return this.workflowItemService.delete(id).pipe(
|
||||
getFirstCompletedRemoteData(),
|
||||
map((response: RemoteData<NoContent>) => response.hasSucceeded)
|
||||
|
@@ -23,7 +23,7 @@ export class WorkflowItemSendBackComponent extends WorkflowItemActionPageCompone
|
||||
protected notificationsService: NotificationsService,
|
||||
protected translationService: TranslateService,
|
||||
protected requestService: RequestService) {
|
||||
super(route, workflowItemService, router, routeService, notificationsService, translationService);
|
||||
super(route, workflowItemService, router, routeService, notificationsService, translationService, requestService);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -38,7 +38,6 @@ export class WorkflowItemSendBackComponent extends WorkflowItemActionPageCompone
|
||||
* @param id The id of the WorkflowItem
|
||||
*/
|
||||
sendRequest(id: string): Observable<boolean> {
|
||||
this.requestService.removeByHrefSubstring('/discover');
|
||||
return this.workflowItemService.sendBack(id);
|
||||
}
|
||||
}
|
||||
|
@@ -582,6 +582,8 @@
|
||||
|
||||
"advanced-workflow-action.rating.form.rating.label": "Rating",
|
||||
|
||||
"advanced-workflow-action.rating.form.rating.error": "You must rate the item",
|
||||
|
||||
"advanced-workflow-action.rating.form.review.label": "Review",
|
||||
|
||||
"advanced-workflow-action.rating.form.review.error": "You must enter a review to submit this rating",
|
||||
@@ -845,6 +847,12 @@
|
||||
"chips.remove": "Remove chip",
|
||||
|
||||
|
||||
"claimed-approved-search-result-list-element.title": "Approved",
|
||||
|
||||
"claimed-declined-search-result-list-element.title": "Rejected, sent back to submitter",
|
||||
|
||||
"claimed-declined-task-search-result-list-element.title": "Declined, sent back to Review Manager's workflow",
|
||||
|
||||
|
||||
"collection.create.head": "Create a Collection",
|
||||
|
||||
|
@@ -231,7 +231,6 @@ const DECLARATIONS = [
|
||||
],
|
||||
declarations: DECLARATIONS,
|
||||
exports: [
|
||||
FullItemPageComponent,
|
||||
CommunityPageSubCollectionListComponent
|
||||
]
|
||||
})
|
||||
|
Reference in New Issue
Block a user