diff --git a/src/app/+home-page/top-level-community-list/top-level-community-list.component.ts b/src/app/+home-page/top-level-community-list/top-level-community-list.component.ts index 4986ff9ec9..3be32f5c6e 100644 --- a/src/app/+home-page/top-level-community-list/top-level-community-list.component.ts +++ b/src/app/+home-page/top-level-community-list/top-level-community-list.component.ts @@ -41,7 +41,5 @@ export class TopLevelCommunityListComponent { elementsPerPage: data.pageSize, sort: { field: data.sortField, direction: data.sortDirection } }); - this.cds.getScopedEndpoint('7669c72a-3f2a-451f-a3b9-9210e7a4c02f') - .subscribe((c) => console.log('communities', c)) } } diff --git a/src/app/core/browse/browse.service.spec.ts b/src/app/core/browse/browse.service.spec.ts index 96d0f3eb62..faf9174c21 100644 --- a/src/app/core/browse/browse.service.spec.ts +++ b/src/app/core/browse/browse.service.spec.ts @@ -142,7 +142,7 @@ describe('BrowseService', () => { expect(result).toBeObservable(expected); }); - it('should configure a new BrowseEndpointRequest', (done) => { + it('should configure a new BrowseEndpointRequest', (done: DoneFn) => { const metadatumKey = 'dc.date.issued'; const linkName = 'items'; const expected = new BrowseEndpointRequest(browsesEndpointURL); diff --git a/src/app/core/data/collection-data.service.ts b/src/app/core/data/collection-data.service.ts index 70c50a1f4e..f9f581128b 100644 --- a/src/app/core/data/collection-data.service.ts +++ b/src/app/core/data/collection-data.service.ts @@ -1,25 +1,18 @@ import { Inject, Injectable } from '@angular/core'; import { Store } from '@ngrx/store'; - -import { DataService } from './data.service'; -import { Collection } from '../shared/collection.model'; -import { ResponseCacheService } from '../cache/response-cache.service'; -import { NormalizedCollection } from '../cache/models/normalized-collection.model'; -import { CoreState } from '../core.reducers'; -import { RequestService } from './request.service'; -import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; import { GLOBAL_CONFIG, GlobalConfig } from '../../../config'; -import { Observable } from 'rxjs/Observable'; -import { CommunityDataService } from './community-data.service'; -import { FindByIDRequest } from './request.models'; +import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; +import { NormalizedCollection } from '../cache/models/normalized-collection.model'; import { ObjectCacheService } from '../cache/object-cache.service'; -import { NormalizedCommunity } from '../cache/models/normalized-community.model'; -import { isNotEmpty } from '../../shared/empty.util'; -import { ResponseCacheEntry } from '../cache/response-cache.reducer'; -import { DSOSuccessResponse, RestResponse } from '../cache/response-cache.models'; +import { ResponseCacheService } from '../cache/response-cache.service'; +import { CoreState } from '../core.reducers'; +import { Collection } from '../shared/collection.model'; +import { ComColDataService } from './comcol-data.service'; +import { CommunityDataService } from './community-data.service'; +import { RequestService } from './request.service'; @Injectable() -export class CollectionDataService extends DataService { +export class CollectionDataService extends ComColDataService { protected linkName = 'collections'; constructor( @@ -28,47 +21,9 @@ export class CollectionDataService extends DataService, @Inject(GLOBAL_CONFIG) protected EnvConfig: GlobalConfig, - private cds: CommunityDataService, + protected cds: CommunityDataService, protected objectCache: ObjectCacheService ) { super(NormalizedCollection); } - - /** - * Get the scoped endpoint URL by fetching the object with - * the given scopeID and returning its HAL link with this - * data-service's linkName - * - * @param {string} scopeID - * the id of the scope object - * @return { Observable } - * an Observable containing the scoped URL - */ - public getScopedEndpoint(scopeID: string): Observable { - const scopeCommunityHrefObs = this.cds.getEndpoint() - .flatMap((endpoint: string) => this.cds.getFindByIDHref(endpoint, scopeID)) - .filter((href: string) => isNotEmpty(href)) - .take(1) - .do((href: string) => { - const request = new FindByIDRequest(href, scopeID); - setTimeout(() => { - this.requestService.configure(request); - }, 0); - }); - - const [successResponse, errorResponse] = scopeCommunityHrefObs - .flatMap((href: string) => this.responseCache.get(href)) - .map((entry: ResponseCacheEntry) => entry.response) - .share() - .partition((response: RestResponse) => response.isSuccessful); - - return Observable.merge( - errorResponse.flatMap((response: DSOSuccessResponse) => - Observable.throw(new Error(`The Community with scope ${scopeID} couldn't be retrieved`))), - successResponse - .flatMap((response: DSOSuccessResponse) => this.objectCache.getByUUID(scopeID, NormalizedCommunity)) - .map((nc: NormalizedCommunity) => nc._links[this.linkName]) - .filter((href) => isNotEmpty(href)) - ).distinctUntilChanged(); - } } diff --git a/src/app/core/data/collection-data.service.spec.ts b/src/app/core/data/comcol-data.service.spec.ts similarity index 76% rename from src/app/core/data/collection-data.service.spec.ts rename to src/app/core/data/comcol-data.service.spec.ts index c953fd1166..f96ace4452 100644 --- a/src/app/core/data/collection-data.service.spec.ts +++ b/src/app/core/data/comcol-data.service.spec.ts @@ -1,20 +1,45 @@ -import { CollectionDataService } from './collection-data.service'; -import { ResponseCacheService } from '../cache/response-cache.service'; -import { RequestService } from './request.service'; -import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; -import { CoreState } from '../core.reducers'; import { Store } from '@ngrx/store'; -import { GlobalConfig } from '../../../config'; -import { CommunityDataService } from './community-data.service'; -import { ObjectCacheService } from '../cache/object-cache.service'; import { cold, getTestScheduler, hot } from 'jasmine-marbles'; -import { FindByIDRequest } from './request.models'; -import { NormalizedCommunity } from '../cache/models/normalized-community.model'; import { TestScheduler } from 'rxjs/Rx'; +import { GlobalConfig } from '../../../config'; +import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; +import { NormalizedCommunity } from '../cache/models/normalized-community.model'; +import { CacheableObject } from '../cache/object-cache.reducer'; +import { ObjectCacheService } from '../cache/object-cache.service'; +import { ResponseCacheService } from '../cache/response-cache.service'; +import { CoreState } from '../core.reducers'; +import { ComColDataService } from './comcol-data.service'; +import { CommunityDataService } from './community-data.service'; +import { FindByIDRequest } from './request.models'; +import { RequestService } from './request.service'; -describe('CollectionDataService', () => { +const LINK_NAME = 'test'; + +/* tslint:disable:max-classes-per-file */ +class NormalizedTestObject implements CacheableObject { + self: string; +} + +class TestService extends ComColDataService { + protected linkName = LINK_NAME; + + constructor( + protected responseCache: ResponseCacheService, + protected requestService: RequestService, + protected rdbService: RemoteDataBuildService, + protected store: Store, + protected EnvConfig: GlobalConfig, + protected cds: CommunityDataService, + protected objectCache: ObjectCacheService + ) { + super(NormalizedTestObject); + } +} +/* tslint:enable:max-classes-per-file */ + +describe('ComColDataService', () => { let scheduler: TestScheduler; - let service: CollectionDataService; + let service: TestService; let responseCache: ResponseCacheService; let requestService: RequestService; let cds: CommunityDataService; @@ -27,7 +52,7 @@ describe('CollectionDataService', () => { const scopeID = 'd9d30c0c-69b7-4369-8397-ca67c888974d'; const communitiesEndpoint = 'https://rest.api/core/communities'; const communityEndpoint = `${communitiesEndpoint}/${scopeID}`; - const scopedCollectionsEndpoint = `${communityEndpoint}/collections`; + const scopedEndpoint = `${communityEndpoint}/${LINK_NAME}`; function initMockCommunityDataService(): CommunityDataService { return jasmine.createSpyObj('responseCache', { @@ -53,15 +78,15 @@ describe('CollectionDataService', () => { getByUUID: cold('d-', { d: { _links: { - collections: scopedCollectionsEndpoint + [LINK_NAME]: scopedEndpoint } } }) }); } - function initTestCollectionDataService(): CollectionDataService { - return new CollectionDataService( + function initTestService(): TestService { + return new TestService( responseCache, requestService, rdbService, @@ -77,12 +102,12 @@ describe('CollectionDataService', () => { scheduler = getTestScheduler(); }); - it('should configure a new FindByIDRequest for the scope Community', (done) => { + it('should configure a new FindByIDRequest for the scope Community', (done: DoneFn) => { cds = initMockCommunityDataService(); requestService = initMockRequestService(); objectCache = initMockObjectCacheService(); responseCache = initMockResponceCacheService(true); - service = initTestCollectionDataService(); + service = initTestService(); const expected = new FindByIDRequest(communityEndpoint, scopeID); @@ -101,7 +126,7 @@ describe('CollectionDataService', () => { requestService = initMockRequestService(); objectCache = initMockObjectCacheService(); responseCache = initMockResponceCacheService(true); - service = initTestCollectionDataService(); + service = initTestService(); }); it('should fetch the scope Community from the cache', () => { @@ -110,9 +135,9 @@ describe('CollectionDataService', () => { expect(objectCache.getByUUID).toHaveBeenCalledWith(scopeID, NormalizedCommunity); }); - it('should return the endpoint to fetch collections within the given scope', () => { + it('should return the endpoint to fetch resources within the given scope', () => { const result = service.getScopedEndpoint(scopeID); - const expected = cold('--e-', { e: scopedCollectionsEndpoint }); + const expected = cold('--e-', { e: scopedEndpoint }); expect(result).toBeObservable(expected); }); @@ -124,7 +149,7 @@ describe('CollectionDataService', () => { requestService = initMockRequestService(); objectCache = initMockObjectCacheService(); responseCache = initMockResponceCacheService(false); - service = initTestCollectionDataService(); + service = initTestService(); }); it('should throw an error', () => { diff --git a/src/app/core/data/comcol-data.service.ts b/src/app/core/data/comcol-data.service.ts new file mode 100644 index 0000000000..3917499914 --- /dev/null +++ b/src/app/core/data/comcol-data.service.ts @@ -0,0 +1,54 @@ +import { Observable } from 'rxjs/Observable'; +import { isNotEmpty } from '../../shared/empty.util'; +import { NormalizedCommunity } from '../cache/models/normalized-community.model'; +import { CacheableObject } from '../cache/object-cache.reducer'; +import { DSOSuccessResponse, RestResponse } from '../cache/response-cache.models'; +import { ResponseCacheEntry } from '../cache/response-cache.reducer'; +import { CommunityDataService } from './community-data.service'; + +import { DataService } from './data.service'; +import { FindByIDRequest } from './request.models'; +import { ObjectCacheService } from '../cache/object-cache.service'; + +export abstract class ComColDataService extends DataService { + protected abstract cds: CommunityDataService; + protected abstract objectCache: ObjectCacheService; + + /** + * Get the scoped endpoint URL by fetching the object with + * the given scopeID and returning its HAL link with this + * data-service's linkName + * + * @param {string} scopeID + * the id of the scope object + * @return { Observable } + * an Observable containing the scoped URL + */ + public getScopedEndpoint(scopeID: string): Observable { + const scopeCommunityHrefObs = this.cds.getEndpoint() + .flatMap((endpoint: string) => this.cds.getFindByIDHref(endpoint, scopeID)) + .filter((href: string) => isNotEmpty(href)) + .take(1) + .do((href: string) => { + const request = new FindByIDRequest(href, scopeID); + setTimeout(() => { + this.requestService.configure(request); + }, 0); + }); + + const [successResponse, errorResponse] = scopeCommunityHrefObs + .flatMap((href: string) => this.responseCache.get(href)) + .map((entry: ResponseCacheEntry) => entry.response) + .share() + .partition((response: RestResponse) => response.isSuccessful); + + return Observable.merge( + errorResponse.flatMap((response: DSOSuccessResponse) => + Observable.throw(new Error(`The Community with scope ${scopeID} couldn't be retrieved`))), + successResponse + .flatMap((response: DSOSuccessResponse) => this.objectCache.getByUUID(scopeID, NormalizedCommunity)) + .map((nc: NormalizedCommunity) => nc._links[this.linkName]) + .filter((href) => isNotEmpty(href)) + ).distinctUntilChanged(); + } +} diff --git a/src/app/core/data/community-data.service.ts b/src/app/core/data/community-data.service.ts index 5fdf3f4026..bbee96ab47 100644 --- a/src/app/core/data/community-data.service.ts +++ b/src/app/core/data/community-data.service.ts @@ -1,23 +1,20 @@ import { Inject, Injectable } from '@angular/core'; import { Store } from '@ngrx/store'; - -import { DataService } from './data.service'; -import { Community } from '../shared/community.model'; -import { ResponseCacheService } from '../cache/response-cache.service'; -import { NormalizedCommunity } from '../cache/models/normalized-community.model'; -import { CoreState } from '../core.reducers'; -import { RequestService } from './request.service'; -import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; import { GLOBAL_CONFIG, GlobalConfig } from '../../../config'; -import { Observable } from 'rxjs/Observable'; -import { isNotEmpty } from '../../shared/empty.util'; -import { FindByIDRequest } from './request.models'; +import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; +import { NormalizedCommunity } from '../cache/models/normalized-community.model'; import { ObjectCacheService } from '../cache/object-cache.service'; +import { ResponseCacheService } from '../cache/response-cache.service'; +import { CoreState } from '../core.reducers'; +import { Community } from '../shared/community.model'; +import { ComColDataService } from './comcol-data.service'; +import { RequestService } from './request.service'; @Injectable() -export class CommunityDataService extends DataService { +export class CommunityDataService extends ComColDataService { protected linkName = 'communities'; + protected cds = this; constructor( protected responseCache: ResponseCacheService, @@ -29,33 +26,4 @@ export class CommunityDataService extends DataService } - * an Observable containing the scoped URL - */ - public getScopedEndpoint(scopeID: string): Observable { - this.getEndpoint() - .map((endpoint: string) => this.getFindByIDHref(endpoint, scopeID)) - .filter((href: string) => isNotEmpty(href)) - .take(1) - .subscribe((href: string) => { - const request = new FindByIDRequest(href, scopeID); - setTimeout(() => { - this.requestService.configure(request); - }, 0); - }); - - return this.objectCache.getByUUID(scopeID, NormalizedCommunity) - .map((nc: NormalizedCommunity) => nc._links[this.linkName]) - .filter((href) => isNotEmpty(href)) - .distinctUntilChanged(); - } - } diff --git a/src/app/core/data/data.service.ts b/src/app/core/data/data.service.ts index 77b2a44814..ed9d84f04a 100644 --- a/src/app/core/data/data.service.ts +++ b/src/app/core/data/data.service.ts @@ -21,7 +21,7 @@ export abstract class DataService protected abstract EnvConfig: GlobalConfig; constructor( - private normalizedResourceType: GenericConstructor, + protected normalizedResourceType: GenericConstructor, ) { super(); }