diff --git a/src/app/shared/mydspace-actions/claimed-task/abstract/claimed-task-actions-abstract.component.ts b/src/app/shared/mydspace-actions/claimed-task/abstract/claimed-task-actions-abstract.component.ts index f1b486a075..1ff55cefd6 100644 --- a/src/app/shared/mydspace-actions/claimed-task/abstract/claimed-task-actions-abstract.component.ts +++ b/src/app/shared/mydspace-actions/claimed-task/abstract/claimed-task-actions-abstract.component.ts @@ -10,11 +10,11 @@ import { RequestService } from '../../../../core/data/request.service'; import { Observable } from 'rxjs'; import { RemoteData } from '../../../../core/data/remote-data'; import { WorkflowItem } from '../../../../core/submission/models/workflowitem.model'; -import { switchMap, take } from 'rxjs/operators'; +import { take } from 'rxjs/operators'; import { CLAIMED_TASK } from '../../../../core/tasks/models/claimed-task-object.resource-type'; -import { getFirstSucceededRemoteDataPayload } from '../../../../core/shared/operators'; import { Item } from '../../../../core/shared/item.model'; import { MyDSpaceReloadableActionsComponent } from '../../mydspace-reloadable-actions'; +import { isEmpty } from '../../../empty.util'; /** * Abstract component for rendering a claimed task's action @@ -36,6 +36,11 @@ export abstract class ClaimedTaskActionsAbstractComponent extends MyDSpaceReload object: ClaimedTask; + /** + * The item object that belonging to the ClaimedTask object + */ + item: Item; + /** * Anchor used to reload the pool task. */ @@ -43,6 +48,11 @@ export abstract class ClaimedTaskActionsAbstractComponent extends MyDSpaceReload subs = []; + /** + * The workflowitem object that belonging to the ClaimedTask object + */ + workflowitem: WorkflowItem; + protected constructor(protected injector: Injector, protected router: Router, protected notificationsService: NotificationsService, @@ -85,16 +95,10 @@ export abstract class ClaimedTaskActionsAbstractComponent extends MyDSpaceReload * Retrieve the itemUuid. */ initReloadAnchor() { - if (!(this.object as any).workflowitem) { + if (isEmpty(this.item)) { return; } - this.subs.push(this.object.workflowitem.pipe( - getFirstSucceededRemoteDataPayload(), - switchMap((workflowItem: WorkflowItem) => workflowItem.item.pipe(getFirstSucceededRemoteDataPayload()) - )) - .subscribe((item: Item) => { - this.itemUuid = item.uuid; - })); + this.itemUuid = this.item.uuid; } ngOnDestroy() { diff --git a/src/app/shared/mydspace-actions/claimed-task/claimed-task-actions.component.html b/src/app/shared/mydspace-actions/claimed-task/claimed-task-actions.component.html index 47ae8cdb8e..34932f47bf 100644 --- a/src/app/shared/mydspace-actions/claimed-task/claimed-task-actions.component.html +++ b/src/app/shared/mydspace-actions/claimed-task/claimed-task-actions.component.html @@ -1,16 +1,23 @@
- + - +
diff --git a/src/app/shared/mydspace-actions/claimed-task/claimed-task-actions.component.spec.ts b/src/app/shared/mydspace-actions/claimed-task/claimed-task-actions.component.spec.ts index 6f7970d71f..a2e0b14134 100644 --- a/src/app/shared/mydspace-actions/claimed-task/claimed-task-actions.component.spec.ts +++ b/src/app/shared/mydspace-actions/claimed-task/claimed-task-actions.component.spec.ts @@ -3,7 +3,6 @@ import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; import { Router } from '@angular/router'; import { of as observableOf } from 'rxjs'; -import { cold } from 'jasmine-marbles'; import { TranslateLoader, TranslateModule } from '@ngx-translate/core'; import { TranslateLoaderMock } from '../../mocks/translate-loader.mock'; @@ -123,7 +122,9 @@ describe('ClaimedTaskActionsComponent', () => { beforeEach(() => { fixture = TestBed.createComponent(ClaimedTaskActionsComponent); component = fixture.componentInstance; + component.item = item; component.object = mockObject; + component.workflowitem = workflowitem; notificationsServiceStub = TestBed.inject(NotificationsService as any); router = TestBed.inject(Router as any); fixture.detectChanges(); @@ -133,11 +134,11 @@ describe('ClaimedTaskActionsComponent', () => { component.object = null; component.initObjects(mockObject); + expect(component.item).toEqual(item); + expect(component.object).toEqual(mockObject); - expect(component.workflowitem$).toBeObservable(cold('(b|)', { - b: rdWorkflowitem.payload - })); + expect(component.workflowitem).toEqual(workflowitem); }); it('should reload page on process completed', waitForAsync(() => { diff --git a/src/app/shared/mydspace-actions/claimed-task/claimed-task-actions.component.ts b/src/app/shared/mydspace-actions/claimed-task/claimed-task-actions.component.ts index f9bf22fa86..dc57105a4e 100644 --- a/src/app/shared/mydspace-actions/claimed-task/claimed-task-actions.component.ts +++ b/src/app/shared/mydspace-actions/claimed-task/claimed-task-actions.component.ts @@ -2,12 +2,10 @@ import { Component, Injector, Input, OnInit } from '@angular/core'; import { Router } from '@angular/router'; import { Observable } from 'rxjs'; -import { filter, map, take } from 'rxjs/operators'; import { TranslateService } from '@ngx-translate/core'; import { ClaimedTaskDataService } from '../../../core/tasks/claimed-task-data.service'; import { ClaimedTask } from '../../../core/tasks/models/claimed-task-object.model'; -import { isNotUndefined } from '../../empty.util'; import { WorkflowItem } from '../../../core/submission/models/workflowitem.model'; import { RemoteData } from '../../../core/data/remote-data'; import { MyDSpaceActionsComponent } from '../mydspace-actions'; @@ -18,6 +16,7 @@ import { WorkflowAction } from '../../../core/tasks/models/workflow-action-objec 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'; /** * This component represents actions related to ClaimedTask object. @@ -34,10 +33,15 @@ export class ClaimedTaskActionsComponent extends MyDSpaceActionsComponent; + @Input() workflowitem: WorkflowItem; /** * The workflow action available for this task @@ -87,11 +91,6 @@ export class ClaimedTaskActionsComponent extends MyDSpaceActionsComponent>).pipe( - filter((rd: RemoteData) => ((!rd.isRequestPending) && isNotUndefined(rd.payload))), - map((rd: RemoteData) => rd.payload), - take(1)); } /** diff --git a/src/app/shared/mydspace-actions/claimed-task/switcher/claimed-task-actions-loader.component.spec.ts b/src/app/shared/mydspace-actions/claimed-task/switcher/claimed-task-actions-loader.component.spec.ts index 6de2056fe8..95e31f5523 100644 --- a/src/app/shared/mydspace-actions/claimed-task/switcher/claimed-task-actions-loader.component.spec.ts +++ b/src/app/shared/mydspace-actions/claimed-task/switcher/claimed-task-actions-loader.component.spec.ts @@ -1,5 +1,5 @@ import { ClaimedTaskActionsLoaderComponent } from './claimed-task-actions-loader.component'; -import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing'; +import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; import { ChangeDetectionStrategy, Injector, NO_ERRORS_SCHEMA } from '@angular/core'; import { ClaimedTaskActionsDirective } from './claimed-task-actions.directive'; import { ClaimedTask } from '../../../../core/tasks/models/claimed-task-object.model'; @@ -15,6 +15,8 @@ import { RequestService } from '../../../../core/data/request.service'; import { PoolTaskDataService } from '../../../../core/tasks/pool-task-data.service'; import { getMockSearchService } from '../../../mocks/search-service.mock'; import { getMockRequestService } from '../../../mocks/request.service.mock'; +import { Item } from '../../../../core/shared/item.model'; +import { WorkflowItem } from '../../../../core/submission/models/workflowitem.model'; const searchService = getMockSearchService(); @@ -27,6 +29,37 @@ describe('ClaimedTaskActionsLoaderComponent', () => { const option = 'test_option'; const object = Object.assign(new ClaimedTask(), { id: 'claimed-task-1' }); + const item = Object.assign(new Item(), { + 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 workflowitem = Object.assign(new WorkflowItem(), { id: '333' }); + beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ imports: [TranslateModule.forRoot()], @@ -52,8 +85,10 @@ describe('ClaimedTaskActionsLoaderComponent', () => { beforeEach(waitForAsync(() => { fixture = TestBed.createComponent(ClaimedTaskActionsLoaderComponent); comp = fixture.componentInstance; + comp.item = item; comp.object = object; comp.option = option; + comp.workflowitem = workflowitem; spyOn(comp, 'getComponentByWorkflowTaskOption').and.returnValue(ClaimedTaskActionsEditMetadataComponent); fixture.detectChanges(); diff --git a/src/app/shared/mydspace-actions/claimed-task/switcher/claimed-task-actions-loader.component.ts b/src/app/shared/mydspace-actions/claimed-task/switcher/claimed-task-actions-loader.component.ts index 68c597a41c..6a14aeb5bc 100644 --- a/src/app/shared/mydspace-actions/claimed-task/switcher/claimed-task-actions-loader.component.ts +++ b/src/app/shared/mydspace-actions/claimed-task/switcher/claimed-task-actions-loader.component.ts @@ -15,6 +15,8 @@ import { ClaimedTaskActionsAbstractComponent } from '../abstract/claimed-task-ac import { hasValue } from '../../../empty.util'; import { Subscription } from 'rxjs'; import { MyDSpaceActionsResult } from '../../mydspace-actions'; +import { Item } from '../../../../core/shared/item.model'; +import { WorkflowItem } from '../../../../core/submission/models/workflowitem.model'; @Component({ selector: 'ds-claimed-task-actions-loader', @@ -25,6 +27,11 @@ import { MyDSpaceActionsResult } from '../../mydspace-actions'; * Passes on the ClaimedTask to the component and subscribes to the processCompleted output */ export class ClaimedTaskActionsLoaderComponent implements OnInit, OnDestroy { + /** + * The item object that belonging to the ClaimedTask object + */ + @Input() item: Item; + /** * The ClaimedTask object */ @@ -36,6 +43,11 @@ export class ClaimedTaskActionsLoaderComponent implements OnInit, OnDestroy { */ @Input() option: string; + /** + * The workflowitem object that belonging to the ClaimedTask object + */ + @Input() workflowitem: WorkflowItem; + /** * Emits the success or failure of a processed action */ @@ -69,7 +81,9 @@ export class ClaimedTaskActionsLoaderComponent implements OnInit, OnDestroy { const componentRef = viewContainerRef.createComponent(componentFactory); const componentInstance = (componentRef.instance as ClaimedTaskActionsAbstractComponent); + componentInstance.item = this.item; componentInstance.object = this.object; + componentInstance.workflowitem = this.workflowitem; if (hasValue(componentInstance.processCompleted)) { this.subs.push(componentInstance.processCompleted.subscribe((result) => this.processCompleted.emit(result))); } diff --git a/src/app/shared/mydspace-actions/mydspace-reloadable-actions.spec.ts b/src/app/shared/mydspace-actions/mydspace-reloadable-actions.spec.ts index 30c7db3c4b..fe9d955287 100644 --- a/src/app/shared/mydspace-actions/mydspace-reloadable-actions.spec.ts +++ b/src/app/shared/mydspace-actions/mydspace-reloadable-actions.spec.ts @@ -12,10 +12,7 @@ import { RouterStub } from '../testing/router.stub'; import { getMockSearchService } from '../mocks/search-service.mock'; import { getMockRequestService } from '../mocks/request.service.mock'; import { Item } from '../../core/shared/item.model'; -import { - createFailedRemoteDataObject, - createSuccessfulRemoteDataObject -} from '../remote-data.utils'; +import { createFailedRemoteDataObject, createSuccessfulRemoteDataObject } from '../remote-data.utils'; import { WorkflowItem } from '../../core/submission/models/workflowitem.model'; import { TranslateLoaderMock } from '../mocks/translate-loader.mock'; import { NotificationsService } from '../notifications/notifications.service'; @@ -103,7 +100,9 @@ describe('MyDSpaceReloadableActionsComponent', () => { beforeEach(() => { fixture = TestBed.createComponent(PoolTaskActionsComponent); component = fixture.componentInstance; + component.item = item; component.object = mockObject; + component.workflowitem = workflowitem; notificationsServiceStub = TestBed.get(NotificationsService); router = TestBed.get(Router); fixture.detectChanges(); diff --git a/src/app/shared/mydspace-actions/pool-task/pool-task-actions.component.html b/src/app/shared/mydspace-actions/pool-task/pool-task-actions.component.html index 57617d8151..9d63a42d03 100644 --- a/src/app/shared/mydspace-actions/pool-task/pool-task-actions.component.html +++ b/src/app/shared/mydspace-actions/pool-task/pool-task-actions.component.html @@ -8,6 +8,6 @@ diff --git a/src/app/shared/mydspace-actions/pool-task/pool-task-actions.component.spec.ts b/src/app/shared/mydspace-actions/pool-task/pool-task-actions.component.spec.ts index 8c0de55138..385dea73f3 100644 --- a/src/app/shared/mydspace-actions/pool-task/pool-task-actions.component.spec.ts +++ b/src/app/shared/mydspace-actions/pool-task/pool-task-actions.component.spec.ts @@ -4,7 +4,6 @@ import { Router } from '@angular/router'; import { By } from '@angular/platform-browser'; import { of as observableOf } from 'rxjs'; -import { cold } from 'jasmine-marbles'; import { TranslateLoader, TranslateModule } from '@ngx-translate/core'; import { TranslateLoaderMock } from '../../mocks/translate-loader.mock'; @@ -105,7 +104,9 @@ describe('PoolTaskActionsComponent', () => { beforeEach(() => { fixture = TestBed.createComponent(PoolTaskActionsComponent); component = fixture.componentInstance; + component.item = item; component.object = mockObject; + component.workflowitem = workflowitem; notificationsServiceStub = TestBed.inject(NotificationsService as any); router = TestBed.inject(Router as any); fixture.detectChanges(); @@ -120,11 +121,11 @@ describe('PoolTaskActionsComponent', () => { component.object = null; component.initObjects(mockObject); + expect(component.item).toEqual(item); + expect(component.object).toEqual(mockObject); - expect(component.workflowitem$).toBeObservable(cold('(b|)', { - b: rdWorkflowitem.payload - })); + expect(component.workflowitem).toEqual(workflowitem); }); it('should display claim task button', () => { diff --git a/src/app/shared/mydspace-actions/pool-task/pool-task-actions.component.ts b/src/app/shared/mydspace-actions/pool-task/pool-task-actions.component.ts index 193739ec0d..c8dcd87a33 100644 --- a/src/app/shared/mydspace-actions/pool-task/pool-task-actions.component.ts +++ b/src/app/shared/mydspace-actions/pool-task/pool-task-actions.component.ts @@ -2,19 +2,17 @@ import { Component, Injector, Input, OnDestroy } from '@angular/core'; import { Router } from '@angular/router'; import { Observable } from 'rxjs'; -import { filter, map, switchMap, take } from 'rxjs/operators'; +import { switchMap, take } from 'rxjs/operators'; import { TranslateService } from '@ngx-translate/core'; import { WorkflowItem } from '../../../core/submission/models/workflowitem.model'; import { RemoteData } from '../../../core/data/remote-data'; import { PoolTask } from '../../../core/tasks/models/pool-task-object.model'; import { PoolTaskDataService } from '../../../core/tasks/pool-task-data.service'; -import { isNotUndefined } from '../../empty.util'; import { NotificationsService } from '../../notifications/notifications.service'; import { RequestService } from '../../../core/data/request.service'; import { SearchService } from '../../../core/shared/search/search.service'; import { ClaimedTaskDataService } from '../../../core/tasks/claimed-task-data.service'; -import { getFirstSucceededRemoteDataPayload } from '../../../core/shared/operators'; import { Item } from '../../../core/shared/item.model'; import { DSpaceObject } from '../../../core/shared/dspace-object.model'; import { MyDSpaceReloadableActionsComponent } from '../mydspace-reloadable-actions'; @@ -36,10 +34,15 @@ export class PoolTaskActionsComponent extends MyDSpaceReloadableActionsComponent */ @Input() object: PoolTask; + /** + * The item object that belonging to the PoolTask object + */ + @Input() item: Item; + /** * The workflowitem object that belonging to the PoolTask object */ - public workflowitem$: Observable; + @Input() workflowitem: WorkflowItem; /** * Anchor used to reload the pool task. @@ -83,10 +86,6 @@ export class PoolTaskActionsComponent extends MyDSpaceReloadableActionsComponent */ initObjects(object: PoolTask) { this.object = object; - this.workflowitem$ = (this.object.workflowitem as Observable>).pipe( - filter((rd: RemoteData) => ((!rd.isRequestPending) && isNotUndefined(rd.payload))), - map((rd: RemoteData) => rd.payload), - take(1)); } actionExecution(): Observable { @@ -104,13 +103,7 @@ export class PoolTaskActionsComponent extends MyDSpaceReloadableActionsComponent * Retrieve the itemUuid. */ initReloadAnchor() { - (this.object as any).workflowitem.pipe( - getFirstSucceededRemoteDataPayload(), - switchMap((workflowItem: WorkflowItem) => workflowItem.item.pipe(getFirstSucceededRemoteDataPayload()) - )) - .subscribe((item: Item) => { - this.itemUuid = item.uuid; - }); + this.itemUuid = this.item.uuid; } ngOnDestroy() { diff --git a/src/app/shared/object-detail/my-dspace-result-detail-element/claimed-task-search-result/claimed-task-search-result-detail-element.component.html b/src/app/shared/object-detail/my-dspace-result-detail-element/claimed-task-search-result/claimed-task-search-result-detail-element.component.html index 1d8f599e65..3695f4714d 100644 --- a/src/app/shared/object-detail/my-dspace-result-detail-element/claimed-task-search-result/claimed-task-search-result-detail-element.component.html +++ b/src/app/shared/object-detail/my-dspace-result-detail-element/claimed-task-search-result/claimed-task-search-result-detail-element.component.html @@ -1,10 +1,12 @@ - - + - + diff --git a/src/app/shared/object-detail/my-dspace-result-detail-element/claimed-task-search-result/claimed-task-search-result-detail-element.component.spec.ts b/src/app/shared/object-detail/my-dspace-result-detail-element/claimed-task-search-result/claimed-task-search-result-detail-element.component.spec.ts index a6a3e2020b..b2bbb69ef4 100644 --- a/src/app/shared/object-detail/my-dspace-result-detail-element/claimed-task-search-result/claimed-task-search-result-detail-element.component.spec.ts +++ b/src/app/shared/object-detail/my-dspace-result-detail-element/claimed-task-search-result/claimed-task-search-result-detail-element.component.spec.ts @@ -1,5 +1,5 @@ import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; -import { ComponentFixture, TestBed, tick, waitForAsync, fakeAsync} from '@angular/core/testing'; +import { ComponentFixture, fakeAsync, flush, TestBed, tick, waitForAsync } from '@angular/core/testing'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { of as observableOf } from 'rxjs'; @@ -7,7 +7,9 @@ import { of as observableOf } from 'rxjs'; import { Item } from '../../../../core/shared/item.model'; import { ClaimedTaskSearchResultDetailElementComponent } from './claimed-task-search-result-detail-element.component'; import { ClaimedTask } from '../../../../core/tasks/models/claimed-task-object.model'; -import { MyDspaceItemStatusType } from '../../../object-collection/shared/mydspace-item-status/my-dspace-item-status-type'; +import { + MyDspaceItemStatusType +} from '../../../object-collection/shared/mydspace-item-status/my-dspace-item-status-type'; import { WorkflowItem } from '../../../../core/submission/models/workflowitem.model'; import { createSuccessfulRemoteDataObject } from '../../../remote-data.utils'; import { ClaimedTaskSearchResult } from '../../../object-collection/shared/claimed-task-search-result.model'; @@ -15,6 +17,7 @@ import { VarDirective } from '../../../utils/var.directive'; import { LinkService } from '../../../../core/cache/builders/link.service'; import { getMockLinkService } from '../../../mocks/link-service.mock'; import { By } from '@angular/platform-browser'; +import { ObjectCacheService } from '../../../../core/cache/object-cache.service'; let component: ClaimedTaskSearchResultDetailElementComponent; let fixture: ComponentFixture; @@ -58,6 +61,9 @@ const workflowitem = Object.assign(new WorkflowItem(), { item: observableOf(rdIt const rdWorkflowitem = createSuccessfulRemoteDataObject(workflowitem); mockResultObject.indexableObject = Object.assign(new ClaimedTask(), { workflowitem: observableOf(rdWorkflowitem) }); const linkService = getMockLinkService(); +const objectCacheServiceMock = jasmine.createSpyObj('ObjectCacheService', { + remove: jasmine.createSpy('remove') +}); describe('ClaimedTaskSearchResultDetailElementComponent', () => { beforeEach(waitForAsync(() => { @@ -65,7 +71,8 @@ describe('ClaimedTaskSearchResultDetailElementComponent', () => { imports: [NoopAnimationsModule], declarations: [ClaimedTaskSearchResultDetailElementComponent, VarDirective], providers: [ - { provide: LinkService, useValue: linkService } + { provide: LinkService, useValue: linkService }, + { provide: ObjectCacheService, useValue: objectCacheServiceMock } ], schemas: [NO_ERRORS_SCHEMA] }).overrideComponent(ClaimedTaskSearchResultDetailElementComponent, { @@ -83,18 +90,16 @@ describe('ClaimedTaskSearchResultDetailElementComponent', () => { fixture.detectChanges(); }); - it('should init workflowitem properly', (done) => { - component.workflowitemRD$.subscribe((workflowitemRD) => { - // Make sure the necessary links are being resolved - expect(linkService.resolveLinks).toHaveBeenCalledWith( - component.dso, - jasmine.objectContaining({ name: 'workflowitem' }), - jasmine.objectContaining({ name: 'action' }) - ); - expect(workflowitemRD.payload).toEqual(workflowitem); - done(); - }); - }); + it('should init workflowitem properly', fakeAsync(() => { + flush(); + expect(linkService.resolveLinks).toHaveBeenCalledWith( + component.dso, + jasmine.objectContaining({ name: 'workflowitem' }), + jasmine.objectContaining({ name: 'action' }) + ); + expect(component.workflowitem$.value).toEqual(workflowitem); + expect(component.item$.value).toEqual(item); + })); it('should have properly status', () => { expect(component.status).toEqual(MyDspaceItemStatusType.VALIDATION); diff --git a/src/app/shared/object-detail/my-dspace-result-detail-element/claimed-task-search-result/claimed-task-search-result-detail-element.component.ts b/src/app/shared/object-detail/my-dspace-result-detail-element/claimed-task-search-result/claimed-task-search-result-detail-element.component.ts index 74411d2341..2ee661ef38 100644 --- a/src/app/shared/object-detail/my-dspace-result-detail-element/claimed-task-search-result/claimed-task-search-result-detail-element.component.ts +++ b/src/app/shared/object-detail/my-dspace-result-detail-element/claimed-task-search-result/claimed-task-search-result-detail-element.component.ts @@ -1,17 +1,24 @@ -import { Component } from '@angular/core'; +import { Component, OnDestroy, OnInit } from '@angular/core'; -import { Observable } from 'rxjs'; +import { BehaviorSubject, EMPTY, Observable } from 'rxjs'; +import { mergeMap, tap } from 'rxjs/operators'; import { RemoteData } from '../../../../core/data/remote-data'; import { ViewMode } from '../../../../core/shared/view-mode.model'; import { WorkflowItem } from '../../../../core/submission/models/workflowitem.model'; import { ClaimedTask } from '../../../../core/tasks/models/claimed-task-object.model'; import { SearchResultDetailElementComponent } from '../search-result-detail-element.component'; -import { MyDspaceItemStatusType } from '../../../object-collection/shared/mydspace-item-status/my-dspace-item-status-type'; +import { + MyDspaceItemStatusType +} from '../../../object-collection/shared/mydspace-item-status/my-dspace-item-status-type'; import { listableObjectComponent } from '../../../object-collection/shared/listable-object/listable-object.decorator'; import { ClaimedTaskSearchResult } from '../../../object-collection/shared/claimed-task-search-result.model'; import { followLink } from '../../../utils/follow-link-config.model'; import { LinkService } from '../../../../core/cache/builders/link.service'; +import { Item } from '../../../../core/shared/item.model'; +import { getFirstCompletedRemoteData } from '../../../../core/shared/operators'; +import { isNotEmpty } from '../../../empty.util'; +import { ObjectCacheService } from '../../../../core/cache/object-cache.service'; /** * This component renders claimed task object for the search result in the detail view. @@ -23,7 +30,12 @@ import { LinkService } from '../../../../core/cache/builders/link.service'; }) @listableObjectComponent(ClaimedTaskSearchResult, ViewMode.DetailedListElement) -export class ClaimedTaskSearchResultDetailElementComponent extends SearchResultDetailElementComponent { +export class ClaimedTaskSearchResultDetailElementComponent extends SearchResultDetailElementComponent implements OnInit, OnDestroy { + + /** + * The item object that belonging to the result object + */ + public item$: BehaviorSubject = new BehaviorSubject(null); /** * A boolean representing if to show submitter information @@ -38,9 +50,9 @@ export class ClaimedTaskSearchResultDetailElementComponent extends SearchResultD /** * The workflowitem object that belonging to the result object */ - public workflowitemRD$: Observable>; + public workflowitem$: BehaviorSubject = new BehaviorSubject(null); - constructor(protected linkService: LinkService) { + constructor(protected linkService: LinkService, protected objectCache: ObjectCacheService) { super(); } @@ -53,7 +65,30 @@ export class ClaimedTaskSearchResultDetailElementComponent extends SearchResultD followLink('item', {}, followLink('bundles')), followLink('submitter') ), followLink('action')); - this.workflowitemRD$ = this.dso.workflowitem as Observable>; + + (this.dso.workflowitem as Observable>).pipe( + getFirstCompletedRemoteData(), + mergeMap((wfiRD: RemoteData) => { + if (wfiRD.hasSucceeded) { + this.workflowitem$.next(wfiRD.payload); + return (wfiRD.payload.item as Observable>).pipe( + getFirstCompletedRemoteData() + ); + } else { + return EMPTY; + } + }), + tap((itemRD: RemoteData) => { + if (isNotEmpty(itemRD) && itemRD.hasSucceeded) { + this.item$.next(itemRD.payload); + } + }) + ).subscribe(); + } + + ngOnDestroy() { + // This ensures the object is removed from cache, when action is performed on task + this.objectCache.remove(this.dso._links.workflowitem.href); } } diff --git a/src/app/shared/object-detail/my-dspace-result-detail-element/pool-search-result/pool-search-result-detail-element.component.html b/src/app/shared/object-detail/my-dspace-result-detail-element/pool-search-result/pool-search-result-detail-element.component.html index 232b54d4d9..c9165b416a 100644 --- a/src/app/shared/object-detail/my-dspace-result-detail-element/pool-search-result/pool-search-result-detail-element.component.html +++ b/src/app/shared/object-detail/my-dspace-result-detail-element/pool-search-result/pool-search-result-detail-element.component.html @@ -1,9 +1,12 @@ - - + - + + diff --git a/src/app/shared/object-detail/my-dspace-result-detail-element/pool-search-result/pool-search-result-detail-element.component.spec.ts b/src/app/shared/object-detail/my-dspace-result-detail-element/pool-search-result/pool-search-result-detail-element.component.spec.ts index 8e0458d49f..59725233ba 100644 --- a/src/app/shared/object-detail/my-dspace-result-detail-element/pool-search-result/pool-search-result-detail-element.component.spec.ts +++ b/src/app/shared/object-detail/my-dspace-result-detail-element/pool-search-result/pool-search-result-detail-element.component.spec.ts @@ -1,12 +1,14 @@ import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; -import { waitForAsync, ComponentFixture, TestBed, fakeAsync, tick } from '@angular/core/testing'; +import { ComponentFixture, fakeAsync, flush, TestBed, tick, waitForAsync } from '@angular/core/testing'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { of as observableOf } from 'rxjs'; import { Item } from '../../../../core/shared/item.model'; import { PoolTask } from '../../../../core/tasks/models/pool-task-object.model'; -import { MyDspaceItemStatusType } from '../../../object-collection/shared/mydspace-item-status/my-dspace-item-status-type'; +import { + MyDspaceItemStatusType +} from '../../../object-collection/shared/mydspace-item-status/my-dspace-item-status-type'; import { WorkflowItem } from '../../../../core/submission/models/workflowitem.model'; import { createSuccessfulRemoteDataObject } from '../../../remote-data.utils'; import { PoolSearchResultDetailElementComponent } from './pool-search-result-detail-element.component'; @@ -15,8 +17,7 @@ import { VarDirective } from '../../../utils/var.directive'; import { LinkService } from '../../../../core/cache/builders/link.service'; import { getMockLinkService } from '../../../mocks/link-service.mock'; import { By } from '@angular/platform-browser'; -import { DSONameService } from '../../../../core/breadcrumbs/dso-name.service'; -import { DSONameServiceMock } from '../../../mocks/dso-name.service.mock'; +import { ObjectCacheService } from '../../../../core/cache/object-cache.service'; let component: PoolSearchResultDetailElementComponent; let fixture: ComponentFixture; @@ -60,6 +61,9 @@ const workflowitem = Object.assign(new WorkflowItem(), { item: observableOf(rdIt const rdWorkflowitem = createSuccessfulRemoteDataObject(workflowitem); mockResultObject.indexableObject = Object.assign(new PoolTask(), { workflowitem: observableOf(rdWorkflowitem) }); const linkService = getMockLinkService(); +const objectCacheServiceMock = jasmine.createSpyObj('ObjectCacheService', { + remove: jasmine.createSpy('remove') +}); describe('PoolSearchResultDetailElementComponent', () => { beforeEach(waitForAsync(() => { @@ -70,7 +74,7 @@ describe('PoolSearchResultDetailElementComponent', () => { { provide: 'objectElementProvider', useValue: (mockResultObject) }, { provide: 'indexElementProvider', useValue: (compIndex) }, { provide: LinkService, useValue: linkService }, - { provide: DSONameService, useClass: DSONameServiceMock }, + { provide: ObjectCacheService, useValue: objectCacheServiceMock } ], schemas: [NO_ERRORS_SCHEMA] }).overrideComponent(PoolSearchResultDetailElementComponent, { @@ -88,17 +92,16 @@ describe('PoolSearchResultDetailElementComponent', () => { 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 init workflowitem properly', fakeAsync(() => { + flush(); + expect(linkService.resolveLinks).toHaveBeenCalledWith( + component.dso, + jasmine.objectContaining({ name: 'workflowitem' }), + jasmine.objectContaining({ name: 'action' }) + ); + expect(component.workflowitem$.value).toEqual(workflowitem); + expect(component.item$.value).toEqual(item); + })); it('should have properly status', () => { expect(component.status).toEqual(MyDspaceItemStatusType.WAITING_CONTROLLER); diff --git a/src/app/shared/object-detail/my-dspace-result-detail-element/pool-search-result/pool-search-result-detail-element.component.ts b/src/app/shared/object-detail/my-dspace-result-detail-element/pool-search-result/pool-search-result-detail-element.component.ts index df27abd42e..6dec14f9cb 100644 --- a/src/app/shared/object-detail/my-dspace-result-detail-element/pool-search-result/pool-search-result-detail-element.component.ts +++ b/src/app/shared/object-detail/my-dspace-result-detail-element/pool-search-result/pool-search-result-detail-element.component.ts @@ -1,16 +1,24 @@ -import { Component } from '@angular/core'; +import { Component, OnDestroy, OnInit } from '@angular/core'; + +import { BehaviorSubject, EMPTY, Observable } from 'rxjs'; +import { mergeMap, tap } from 'rxjs/operators'; -import { Observable } from 'rxjs'; import { RemoteData } from '../../../../core/data/remote-data'; import { PoolTask } from '../../../../core/tasks/models/pool-task-object.model'; import { SearchResultDetailElementComponent } from '../search-result-detail-element.component'; -import { MyDspaceItemStatusType } from '../../../object-collection/shared/mydspace-item-status/my-dspace-item-status-type'; +import { + MyDspaceItemStatusType +} from '../../../object-collection/shared/mydspace-item-status/my-dspace-item-status-type'; import { WorkflowItem } from '../../../../core/submission/models/workflowitem.model'; import { ViewMode } from '../../../../core/shared/view-mode.model'; import { listableObjectComponent } from '../../../object-collection/shared/listable-object/listable-object.decorator'; import { PoolTaskSearchResult } from '../../../object-collection/shared/pool-task-search-result.model'; import { followLink } from '../../../utils/follow-link-config.model'; import { LinkService } from '../../../../core/cache/builders/link.service'; +import { Item } from '../../../../core/shared/item.model'; +import { getFirstCompletedRemoteData } from '../../../../core/shared/operators'; +import { isNotEmpty } from '../../../empty.util'; +import { ObjectCacheService } from '../../../../core/cache/object-cache.service'; /** * This component renders pool task object for the search result in the detail view. @@ -22,7 +30,12 @@ import { LinkService } from '../../../../core/cache/builders/link.service'; }) @listableObjectComponent(PoolTaskSearchResult, ViewMode.DetailedListElement) -export class PoolSearchResultDetailElementComponent extends SearchResultDetailElementComponent { +export class PoolSearchResultDetailElementComponent extends SearchResultDetailElementComponent implements OnInit, OnDestroy { + + /** + * The item object that belonging to the result object + */ + public item$: BehaviorSubject = new BehaviorSubject(null); /** * A boolean representing if to show submitter information @@ -37,9 +50,9 @@ export class PoolSearchResultDetailElementComponent extends SearchResultDetailEl /** * The workflowitem object that belonging to the result object */ - public workflowitemRD$: Observable>; + public workflowitem$: BehaviorSubject = new BehaviorSubject(null); - constructor(protected linkService: LinkService) { + constructor(protected linkService: LinkService, protected objectCache: ObjectCacheService) { super(); } @@ -52,7 +65,31 @@ export class PoolSearchResultDetailElementComponent extends SearchResultDetailEl followLink('item', {}, followLink('bundles')), followLink('submitter') ), followLink('action')); - this.workflowitemRD$ = this.dso.workflowitem as Observable>; + + (this.dso.workflowitem as Observable>).pipe( + getFirstCompletedRemoteData(), + mergeMap((wfiRD: RemoteData) => { + if (wfiRD.hasSucceeded) { + this.workflowitem$.next(wfiRD.payload); + return (wfiRD.payload.item as Observable>).pipe( + getFirstCompletedRemoteData() + ); + } else { + return EMPTY; + } + }), + tap((itemRD: RemoteData) => { + if (isNotEmpty(itemRD) && itemRD.hasSucceeded) { + this.item$.next(itemRD.payload); + } + }) + ).subscribe(); + + } + + ngOnDestroy() { + // This ensures the object is removed from cache, when action is performed on task + this.objectCache.remove(this.dso._links.workflowitem.href); } } diff --git a/src/app/shared/object-list/my-dspace-result-list-element/claimed-search-result/claimed-search-result-list-element.component.html b/src/app/shared/object-list/my-dspace-result-list-element/claimed-search-result/claimed-search-result-list-element.component.html index 2cee94ce20..5e98b00926 100644 --- a/src/app/shared/object-list/my-dspace-result-list-element/claimed-search-result/claimed-search-result-list-element.component.html +++ b/src/app/shared/object-list/my-dspace-result-list-element/claimed-search-result/claimed-search-result-list-element.component.html @@ -1,18 +1,15 @@ - + + -
-
- +
+
+ +
-
- - - - - + diff --git a/src/app/shared/object-list/my-dspace-result-list-element/claimed-search-result/claimed-search-result-list-element.component.spec.ts b/src/app/shared/object-list/my-dspace-result-list-element/claimed-search-result/claimed-search-result-list-element.component.spec.ts index c5383a2e31..4ea716cc2a 100644 --- a/src/app/shared/object-list/my-dspace-result-list-element/claimed-search-result/claimed-search-result-list-element.component.spec.ts +++ b/src/app/shared/object-list/my-dspace-result-list-element/claimed-search-result/claimed-search-result-list-element.component.spec.ts @@ -104,6 +104,7 @@ describe('ClaimedSearchResultListElementComponent', () => { jasmine.objectContaining({ name: 'action' }) ); expect(component.workflowitem$.value).toEqual(workflowitem); + expect(component.item$.value).toEqual(item); })); it('should have properly status', () => { diff --git a/src/app/shared/object-list/my-dspace-result-list-element/claimed-search-result/claimed-search-result-list-element.component.ts b/src/app/shared/object-list/my-dspace-result-list-element/claimed-search-result/claimed-search-result-list-element.component.ts index c1458043a7..237a5f516e 100644 --- a/src/app/shared/object-list/my-dspace-result-list-element/claimed-search-result/claimed-search-result-list-element.component.ts +++ b/src/app/shared/object-list/my-dspace-result-list-element/claimed-search-result/claimed-search-result-list-element.component.ts @@ -8,7 +8,7 @@ import { TruncatableService } from '../../../truncatable/truncatable.service'; import { MyDspaceItemStatusType } from '../../../object-collection/shared/mydspace-item-status/my-dspace-item-status-type'; -import { BehaviorSubject, Observable } from 'rxjs'; +import { BehaviorSubject, EMPTY, 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'; @@ -20,6 +20,9 @@ import { DSONameService } from '../../../../core/breadcrumbs/dso-name.service'; import { APP_CONFIG, AppConfig } from '../../../../../config/app-config.interface'; import { ObjectCacheService } from '../../../../core/cache/object-cache.service'; import { getFirstCompletedRemoteData } from '../../../../core/shared/operators'; +import { Item } from '../../../../core/shared/item.model'; +import { mergeMap, tap } from 'rxjs/operators'; +import { isNotEmpty } from '../../../empty.util'; @Component({ selector: 'ds-claimed-search-result-list-element', @@ -39,6 +42,11 @@ export class ClaimedSearchResultListElementComponent extends SearchResultListEle */ public status = MyDspaceItemStatusType.VALIDATION; + /** + * The item object that belonging to the result object + */ + public item$: BehaviorSubject = new BehaviorSubject(null); + /** * The workflowitem object that belonging to the result object */ @@ -65,15 +73,29 @@ export class ClaimedSearchResultListElementComponent extends SearchResultListEle ngOnInit() { super.ngOnInit(); this.linkService.resolveLinks(this.dso, followLink('workflowitem', {}, - followLink('item'), followLink('submitter') + followLink('item', {}, followLink('bundles')), + followLink('submitter') ), followLink('action')); + (this.dso.workflowitem as Observable>).pipe( - getFirstCompletedRemoteData() - ).subscribe((wfiRD: RemoteData) => { - if (wfiRD.hasSucceeded) { - this.workflowitem$.next(wfiRD.payload); - } - }); + getFirstCompletedRemoteData(), + mergeMap((wfiRD: RemoteData) => { + if (wfiRD.hasSucceeded) { + this.workflowitem$.next(wfiRD.payload); + return (wfiRD.payload.item as Observable>).pipe( + getFirstCompletedRemoteData() + ); + } else { + return EMPTY; + } + }), + tap((itemRD: RemoteData) => { + if (isNotEmpty(itemRD) && itemRD.hasSucceeded) { + this.item$.next(itemRD.payload); + } + }) + ).subscribe(); + this.showThumbnails = this.appConfig.browseBy.showThumbnails; } diff --git a/src/app/shared/object-list/my-dspace-result-list-element/pool-search-result/pool-search-result-list-element.component.html b/src/app/shared/object-list/my-dspace-result-list-element/pool-search-result/pool-search-result-list-element.component.html index 6a6e729dea..4f0d6f774a 100644 --- a/src/app/shared/object-list/my-dspace-result-list-element/pool-search-result/pool-search-result-list-element.component.html +++ b/src/app/shared/object-list/my-dspace-result-list-element/pool-search-result/pool-search-result-list-element.component.html @@ -1,12 +1,15 @@ - -
-
- + + +
+
+ +
-
+ diff --git a/src/app/shared/object-list/my-dspace-result-list-element/pool-search-result/pool-search-result-list-element.component.spec.ts b/src/app/shared/object-list/my-dspace-result-list-element/pool-search-result/pool-search-result-list-element.component.spec.ts index ab5652138e..0e5b2eaa6f 100644 --- a/src/app/shared/object-list/my-dspace-result-list-element/pool-search-result/pool-search-result-list-element.component.spec.ts +++ b/src/app/shared/object-list/my-dspace-result-list-element/pool-search-result/pool-search-result-list-element.component.spec.ts @@ -110,6 +110,7 @@ describe('PoolSearchResultListElementComponent', () => { jasmine.objectContaining({ name: 'action' }) ); expect(component.workflowitem$.value).toEqual(workflowitem); + expect(component.item$.value).toEqual(item); })); it('should have properly status', () => { diff --git a/src/app/shared/object-list/my-dspace-result-list-element/pool-search-result/pool-search-result-list-element.component.ts b/src/app/shared/object-list/my-dspace-result-list-element/pool-search-result/pool-search-result-list-element.component.ts index a42b3d04d6..046763eb98 100644 --- a/src/app/shared/object-list/my-dspace-result-list-element/pool-search-result/pool-search-result-list-element.component.ts +++ b/src/app/shared/object-list/my-dspace-result-list-element/pool-search-result/pool-search-result-list-element.component.ts @@ -1,6 +1,7 @@ import { Component, Inject, OnDestroy, OnInit } from '@angular/core'; -import { BehaviorSubject, Observable } from 'rxjs'; +import { BehaviorSubject, EMPTY, Observable } from 'rxjs'; +import { mergeMap, tap } from 'rxjs/operators'; import { ViewMode } from '../../../../core/shared/view-mode.model'; import { RemoteData } from '../../../../core/data/remote-data'; @@ -21,6 +22,8 @@ import { DSONameService } from '../../../../core/breadcrumbs/dso-name.service'; import { APP_CONFIG, AppConfig } from '../../../../../config/app-config.interface'; import { ObjectCacheService } from '../../../../core/cache/object-cache.service'; import { getFirstCompletedRemoteData } from '../../../../core/shared/operators'; +import { Item } from '../../../../core/shared/item.model'; +import { isNotEmpty } from '../../../empty.util'; /** * This component renders pool task object for the search result in the list view. @@ -44,6 +47,11 @@ export class PoolSearchResultListElementComponent extends SearchResultListElemen */ public status = MyDspaceItemStatusType.WAITING_CONTROLLER; + /** + * The item object that belonging to the result object + */ + public item$: BehaviorSubject = new BehaviorSubject(null); + /** * The workflowitem object that belonging to the result object */ @@ -75,15 +83,29 @@ export class PoolSearchResultListElementComponent extends SearchResultListElemen ngOnInit() { super.ngOnInit(); this.linkService.resolveLinks(this.dso, followLink('workflowitem', {}, - followLink('item'), followLink('submitter') + followLink('item', {}, followLink('bundles')), + followLink('submitter') ), followLink('action')); + (this.dso.workflowitem as Observable>).pipe( - getFirstCompletedRemoteData() - ).subscribe((wfiRD: RemoteData) => { - if (wfiRD.hasSucceeded) { - this.workflowitem$.next(wfiRD.payload); - } - }); + getFirstCompletedRemoteData(), + mergeMap((wfiRD: RemoteData) => { + if (wfiRD.hasSucceeded) { + this.workflowitem$.next(wfiRD.payload); + return (wfiRD.payload.item as Observable>).pipe( + getFirstCompletedRemoteData() + ); + } else { + return EMPTY; + } + }), + tap((itemRD: RemoteData) => { + if (isNotEmpty(itemRD) && itemRD.hasSucceeded) { + this.item$.next(itemRD.payload); + } + }) + ).subscribe(); + this.showThumbnails = this.appConfig.browseBy.showThumbnails; }