-
+
diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 2141b06a77..4e029af8ca 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -19,7 +19,7 @@ import variables from '../styles/_exposed_variables.scss'; import { CSSVariableService } from './shared/sass-helper/sass-helper.service'; import { MenuService } from './shared/menu/menu.service'; import { MenuID } from './shared/menu/initial-menus-state'; -import { combineLatest as combineLatestObservable, Observable, of } from 'rxjs'; +import { BehaviorSubject, combineLatest as combineLatestObservable, Observable, of } from 'rxjs'; import { slideSidebarPadding } from './shared/animations/slide'; import { HostWindowService } from './shared/host-window.service'; import { Theme } from '../config/theme.inferface'; @@ -38,7 +38,7 @@ export const LANG_COOKIE = 'language_cookie'; animations: [slideSidebarPadding] }) export class AppComponent implements OnInit, AfterViewInit { - isLoading = true; + isLoading$: BehaviorSubject = new BehaviorSubject(true); sidebarVisible: Observable; slideSidebarOver: Observable; collapsedSidebarWidth: Observable; @@ -131,12 +131,12 @@ export class AppComponent implements OnInit, AfterViewInit { delay(0) ).subscribe((event) => { if (event instanceof NavigationStart) { - this.isLoading = true; + this.isLoading$.next(true); } else if ( event instanceof NavigationEnd || event instanceof NavigationCancel ) { - this.isLoading = false; + this.isLoading$.next(false); } }); } diff --git a/src/app/core/cache/server-sync-buffer.effects.ts b/src/app/core/cache/server-sync-buffer.effects.ts index c70f3ad8e1..3a0e801f27 100644 --- a/src/app/core/cache/server-sync-buffer.effects.ts +++ b/src/app/core/cache/server-sync-buffer.effects.ts @@ -2,6 +2,7 @@ import { delay, exhaustMap, map, switchMap, take } from 'rxjs/operators'; import { Inject, Injectable } from '@angular/core'; import { Actions, Effect, ofType } from '@ngrx/effects'; import { coreSelector } from '../core.selectors'; +import { DSpaceSerializer } from '../dspace-rest-v2/dspace.serializer'; import { AddToSSBAction, CommitSSBAction, @@ -18,7 +19,6 @@ import { RequestService } from '../data/request.service'; import { PutRequest } from '../data/request.models'; import { ObjectCacheService } from './object-cache.service'; import { ApplyPatchObjectCacheAction } from './object-cache.actions'; -import { NormalizedObjectSerializer } from '../dspace-rest-v2/normalized-object.serializer'; import { GenericConstructor } from '../shared/generic-constructor'; import { hasValue, isNotEmpty, isNotUndefined } from '../../shared/empty.util'; import { Observable } from 'rxjs/internal/Observable'; @@ -100,7 +100,7 @@ export class ServerSyncBufferEffects { return patchObject.pipe( map((object) => { - const serializedObject = new NormalizedObjectSerializer(object.constructor as GenericConstructor<{}>).serialize(object); + const serializedObject = new DSpaceSerializer(object.constructor as GenericConstructor<{}>).serialize(object); this.requestService.configure(new PutRequest(this.requestService.generateRequestId(), href, serializedObject)); diff --git a/src/app/core/data/base-response-parsing.service.ts b/src/app/core/data/base-response-parsing.service.ts index ab81e2dd8d..c9bc58b5d7 100644 --- a/src/app/core/data/base-response-parsing.service.ts +++ b/src/app/core/data/base-response-parsing.service.ts @@ -1,6 +1,5 @@ import { hasNoValue, hasValue, isNotEmpty } from '../../shared/empty.util'; import { DSpaceSerializer } from '../dspace-rest-v2/dspace.serializer'; -import { NormalizedObjectSerializer } from '../dspace-rest-v2/normalized-object.serializer'; import { CacheableObject } from '../cache/object-cache.reducer'; import { Serializer } from '../serializer'; import { PageInfo } from '../shared/page-info.model'; @@ -129,7 +128,7 @@ export abstract class BaseResponseParsingService { processPageInfo(payload: any): PageInfo { if (hasValue(payload.page)) { const pageObj = Object.assign({}, payload.page, { _links: payload._links }); - const pageInfoObject = new NormalizedObjectSerializer(PageInfo).deserialize(pageObj); + const pageInfoObject = new DSpaceSerializer(PageInfo).deserialize(pageObj); if (pageInfoObject.currentPage >= 0) { Object.assign(pageInfoObject, { currentPage: pageInfoObject.currentPage + 1 }); } diff --git a/src/app/core/data/collection-data.service.ts b/src/app/core/data/collection-data.service.ts index 6db87e59ef..5238b51f5a 100644 --- a/src/app/core/data/collection-data.service.ts +++ b/src/app/core/data/collection-data.service.ts @@ -17,8 +17,8 @@ import { SearchParam } from '../cache/models/search-param.model'; import { ObjectCacheService } from '../cache/object-cache.service'; import { ContentSourceSuccessResponse, RestResponse } from '../cache/response.models'; import { CoreState } from '../core.reducers'; -import { NormalizedObjectSerializer } from '../dspace-rest-v2/normalized-object.serializer'; import { HttpOptions } from '../dspace-rest-v2/dspace-rest-v2.service'; +import { DSpaceSerializer } from '../dspace-rest-v2/dspace.serializer'; import { Collection } from '../shared/collection.model'; import { COLLECTION } from '../shared/collection.resource-type'; import { ContentSource } from '../shared/content-source.model'; @@ -153,7 +153,7 @@ export class CollectionDataService extends ComColDataService { */ updateContentSource(collectionId: string, contentSource: ContentSource): Observable { const requestId = this.requestService.generateRequestId(); - const serializedContentSource = new NormalizedObjectSerializer(ContentSource).serialize(contentSource); + const serializedContentSource = new DSpaceSerializer(ContentSource).serialize(contentSource); const request$ = this.getHarvesterEndpoint(collectionId).pipe( take(1), map((href: string) => { diff --git a/src/app/core/data/content-source-response-parsing.service.ts b/src/app/core/data/content-source-response-parsing.service.ts index 0d76ea1ef7..95e25db613 100644 --- a/src/app/core/data/content-source-response-parsing.service.ts +++ b/src/app/core/data/content-source-response-parsing.service.ts @@ -1,11 +1,11 @@ import { Injectable } from '@angular/core'; -import { ResponseParsingService } from './parsing.service'; -import { RestRequest } from './request.models'; -import { DSpaceRESTV2Response } from '../dspace-rest-v2/dspace-rest-v2-response.model'; import { ContentSourceSuccessResponse, RestResponse } from '../cache/response.models'; -import { NormalizedObjectSerializer } from '../dspace-rest-v2/normalized-object.serializer'; +import { DSpaceRESTV2Response } from '../dspace-rest-v2/dspace-rest-v2-response.model'; +import { DSpaceSerializer } from '../dspace-rest-v2/dspace.serializer'; import { ContentSource } from '../shared/content-source.model'; import { MetadataConfig } from '../shared/metadata-config.model'; +import { ResponseParsingService } from './parsing.service'; +import { RestRequest } from './request.models'; @Injectable() /** @@ -17,11 +17,11 @@ export class ContentSourceResponseParsingService implements ResponseParsingServi parse(request: RestRequest, data: DSpaceRESTV2Response): RestResponse { const payload = data.payload; - const deserialized = new NormalizedObjectSerializer(ContentSource).deserialize(payload); + const deserialized = new DSpaceSerializer(ContentSource).deserialize(payload); let metadataConfigs = []; if (payload._embedded && payload._embedded.harvestermetadata && payload._embedded.harvestermetadata.configs) { - metadataConfigs = new NormalizedObjectSerializer(MetadataConfig).serializeArray(payload._embedded.harvestermetadata.configs); + metadataConfigs = new DSpaceSerializer(MetadataConfig).serializeArray(payload._embedded.harvestermetadata.configs); } deserialized.metadataConfigs = metadataConfigs; diff --git a/src/app/core/data/data.service.ts b/src/app/core/data/data.service.ts index e8335a2bdc..489fbad371 100644 --- a/src/app/core/data/data.service.ts +++ b/src/app/core/data/data.service.ts @@ -27,7 +27,7 @@ import { CacheableObject } from '../cache/object-cache.reducer'; import { ObjectCacheService } from '../cache/object-cache.service'; import { ErrorResponse, RestResponse } from '../cache/response.models'; import { CoreState } from '../core.reducers'; -import { NormalizedObjectSerializer } from '../dspace-rest-v2/normalized-object.serializer'; +import { DSpaceSerializer } from '../dspace-rest-v2/dspace.serializer'; import { DSpaceObject } from '../shared/dspace-object.model'; import { HALEndpointService } from '../shared/hal-endpoint.service'; import { @@ -334,7 +334,7 @@ export abstract class DataService { ); const normalizedObject: NormalizedObject = this.dataBuildService.normalize(dso); - const serializedDso = new NormalizedObjectSerializer(getMapsToType((dso as any).type)).serialize(normalizedObject); + const serializedDso = new DSpaceSerializer(getMapsToType((dso as any).type)).serialize(normalizedObject); const request$ = endpoint$.pipe( take(1), diff --git a/src/app/core/data/facet-config-response-parsing.service.ts b/src/app/core/data/facet-config-response-parsing.service.ts index 1cc5e86b3e..3fc14b6495 100644 --- a/src/app/core/data/facet-config-response-parsing.service.ts +++ b/src/app/core/data/facet-config-response-parsing.service.ts @@ -1,17 +1,14 @@ import { Inject, Injectable } from '@angular/core'; -import { - FacetConfigSuccessResponse, - RestResponse -} from '../cache/response.models'; +import { GLOBAL_CONFIG } from '../../../config'; +import { GlobalConfig } from '../../../config/global-config.interface'; +import { SearchFilterConfig } from '../../shared/search/search-filter-config.model'; +import { ObjectCacheService } from '../cache/object-cache.service'; +import { FacetConfigSuccessResponse, RestResponse } from '../cache/response.models'; +import { DSpaceRESTV2Response } from '../dspace-rest-v2/dspace-rest-v2-response.model'; +import { DSpaceSerializer } from '../dspace-rest-v2/dspace.serializer'; +import { BaseResponseParsingService } from './base-response-parsing.service'; import { ResponseParsingService } from './parsing.service'; import { RestRequest } from './request.models'; -import { DSpaceRESTV2Response } from '../dspace-rest-v2/dspace-rest-v2-response.model'; -import { NormalizedObjectSerializer } from '../dspace-rest-v2/normalized-object.serializer'; -import { SearchFilterConfig } from '../../shared/search/search-filter-config.model'; -import { BaseResponseParsingService } from './base-response-parsing.service'; -import { ObjectCacheService } from '../cache/object-cache.service'; -import { GlobalConfig } from '../../../config/global-config.interface'; -import { GLOBAL_CONFIG } from '../../../config'; @Injectable() export class FacetConfigResponseParsingService extends BaseResponseParsingService implements ResponseParsingService { @@ -24,7 +21,7 @@ export class FacetConfigResponseParsingService extends BaseResponseParsingServic parse(request: RestRequest, data: DSpaceRESTV2Response): RestResponse { const config = data.payload._embedded.facets; - const serializer = new NormalizedObjectSerializer(SearchFilterConfig); + const serializer = new DSpaceSerializer(SearchFilterConfig); const facetConfig = serializer.deserializeArray(config); return new FacetConfigSuccessResponse(facetConfig, data.statusCode, data.statusText); } diff --git a/src/app/core/data/facet-value-map-response-parsing.service.ts b/src/app/core/data/facet-value-map-response-parsing.service.ts index 51e97d2092..8c8c12dff7 100644 --- a/src/app/core/data/facet-value-map-response-parsing.service.ts +++ b/src/app/core/data/facet-value-map-response-parsing.service.ts @@ -1,19 +1,19 @@ import { Inject, Injectable } from '@angular/core'; +import { GLOBAL_CONFIG } from '../../../config'; +import { GlobalConfig } from '../../../config/global-config.interface'; +import { FacetValue } from '../../shared/search/facet-value.model'; +import { ObjectCacheService } from '../cache/object-cache.service'; import { FacetValueMap, FacetValueMapSuccessResponse, FacetValueSuccessResponse, RestResponse } from '../cache/response.models'; +import { DSpaceRESTV2Response } from '../dspace-rest-v2/dspace-rest-v2-response.model'; +import { DSpaceSerializer } from '../dspace-rest-v2/dspace.serializer'; +import { BaseResponseParsingService } from './base-response-parsing.service'; import { ResponseParsingService } from './parsing.service'; import { RestRequest } from './request.models'; -import { DSpaceRESTV2Response } from '../dspace-rest-v2/dspace-rest-v2-response.model'; -import { NormalizedObjectSerializer } from '../dspace-rest-v2/normalized-object.serializer'; -import { FacetValue } from '../../shared/search/facet-value.model'; -import { BaseResponseParsingService } from './base-response-parsing.service'; -import { ObjectCacheService } from '../cache/object-cache.service'; -import { GlobalConfig } from '../../../config/global-config.interface'; -import { GLOBAL_CONFIG } from '../../../config'; @Injectable() export class FacetValueMapResponseParsingService extends BaseResponseParsingService implements ResponseParsingService { @@ -30,7 +30,7 @@ export class FacetValueMapResponseParsingService extends BaseResponseParsingServ const payload = data.payload; const facetMap: FacetValueMap = new FacetValueMap(); - const serializer = new NormalizedObjectSerializer(FacetValue); + const serializer = new DSpaceSerializer(FacetValue); payload._embedded.facets.map((facet) => { const values = facet._embedded.values.map((value) => {value.search = value._links.search.href; return value;}); const facetValues = serializer.deserializeArray(values); diff --git a/src/app/core/data/facet-value-response-parsing.service.ts b/src/app/core/data/facet-value-response-parsing.service.ts index ac83176acc..c9ff93a1ae 100644 --- a/src/app/core/data/facet-value-response-parsing.service.ts +++ b/src/app/core/data/facet-value-response-parsing.service.ts @@ -1,14 +1,14 @@ import { Inject, Injectable } from '@angular/core'; -import { FacetValueSuccessResponse, RestResponse } from '../cache/response.models'; -import { ResponseParsingService } from './parsing.service'; -import { RestRequest } from './request.models'; -import { DSpaceRESTV2Response } from '../dspace-rest-v2/dspace-rest-v2-response.model'; -import { NormalizedObjectSerializer } from '../dspace-rest-v2/normalized-object.serializer'; -import { FacetValue } from '../../shared/search/facet-value.model'; -import { BaseResponseParsingService } from './base-response-parsing.service'; -import { ObjectCacheService } from '../cache/object-cache.service'; import { GLOBAL_CONFIG } from '../../../config'; import { GlobalConfig } from '../../../config/global-config.interface'; +import { FacetValue } from '../../shared/search/facet-value.model'; +import { ObjectCacheService } from '../cache/object-cache.service'; +import { FacetValueSuccessResponse, RestResponse } from '../cache/response.models'; +import { DSpaceRESTV2Response } from '../dspace-rest-v2/dspace-rest-v2-response.model'; +import { DSpaceSerializer } from '../dspace-rest-v2/dspace.serializer'; +import { BaseResponseParsingService } from './base-response-parsing.service'; +import { ResponseParsingService } from './parsing.service'; +import { RestRequest } from './request.models'; @Injectable() export class FacetValueResponseParsingService extends BaseResponseParsingService implements ResponseParsingService { @@ -21,7 +21,7 @@ export class FacetValueResponseParsingService extends BaseResponseParsingService parse(request: RestRequest, data: DSpaceRESTV2Response): RestResponse { const payload = data.payload; - const serializer = new NormalizedObjectSerializer(FacetValue); + const serializer = new DSpaceSerializer(FacetValue); // const values = payload._embedded.values.map((value) => {value.search = value._links.search.href; return value;}); const facetValues = serializer.deserializeArray(payload._embedded.values); diff --git a/src/app/core/data/metadatafield-parsing.service.ts b/src/app/core/data/metadatafield-parsing.service.ts index bc5ea1e199..08f7892ac7 100644 --- a/src/app/core/data/metadatafield-parsing.service.ts +++ b/src/app/core/data/metadatafield-parsing.service.ts @@ -1,10 +1,10 @@ -import { NormalizedObjectSerializer } from '../dspace-rest-v2/normalized-object.serializer'; -import { DSpaceRESTV2Response } from '../dspace-rest-v2/dspace-rest-v2-response.model'; -import { RestRequest } from './request.models'; -import { ResponseParsingService } from './parsing.service'; import { Injectable } from '@angular/core'; import { MetadatafieldSuccessResponse, RestResponse } from '../cache/response.models'; +import { DSpaceRESTV2Response } from '../dspace-rest-v2/dspace-rest-v2-response.model'; +import { DSpaceSerializer } from '../dspace-rest-v2/dspace.serializer'; import { MetadataField } from '../metadata/metadata-field.model'; +import { ResponseParsingService } from './parsing.service'; +import { RestRequest } from './request.models'; /** * A service responsible for parsing DSpaceRESTV2Response data related to a single MetadataField to a valid RestResponse @@ -15,7 +15,7 @@ export class MetadatafieldParsingService implements ResponseParsingService { parse(request: RestRequest, data: DSpaceRESTV2Response): RestResponse { const payload = data.payload; - const deserialized = new NormalizedObjectSerializer(MetadataField).deserialize(payload); + const deserialized = new DSpaceSerializer(MetadataField).deserialize(payload); return new MetadatafieldSuccessResponse(deserialized, data.statusCode, data.statusText); } diff --git a/src/app/core/data/metadataschema-parsing.service.ts b/src/app/core/data/metadataschema-parsing.service.ts index 6d9867eb52..f4b90e5dcd 100644 --- a/src/app/core/data/metadataschema-parsing.service.ts +++ b/src/app/core/data/metadataschema-parsing.service.ts @@ -1,10 +1,10 @@ -import { NormalizedObjectSerializer } from '../dspace-rest-v2/normalized-object.serializer'; -import { DSpaceRESTV2Response } from '../dspace-rest-v2/dspace-rest-v2-response.model'; -import { RestRequest } from './request.models'; -import { ResponseParsingService } from './parsing.service'; import { Injectable } from '@angular/core'; import { MetadataschemaSuccessResponse, RestResponse } from '../cache/response.models'; +import { DSpaceRESTV2Response } from '../dspace-rest-v2/dspace-rest-v2-response.model'; +import { DSpaceSerializer } from '../dspace-rest-v2/dspace.serializer'; import { MetadataSchema } from '../metadata/metadata-schema.model'; +import { ResponseParsingService } from './parsing.service'; +import { RestRequest } from './request.models'; @Injectable() export class MetadataschemaParsingService implements ResponseParsingService { @@ -12,7 +12,7 @@ export class MetadataschemaParsingService implements ResponseParsingService { parse(request: RestRequest, data: DSpaceRESTV2Response): RestResponse { const payload = data.payload; - const deserialized = new NormalizedObjectSerializer(MetadataSchema).deserialize(payload); + const deserialized = new DSpaceSerializer(MetadataSchema).deserialize(payload); return new MetadataschemaSuccessResponse(deserialized, data.statusCode, data.statusText); } diff --git a/src/app/core/data/paginated-list.ts b/src/app/core/data/paginated-list.ts index b9de67a34d..9f05ca7889 100644 --- a/src/app/core/data/paginated-list.ts +++ b/src/app/core/data/paginated-list.ts @@ -56,14 +56,14 @@ export class PaginatedList { } set first(first: string) { - this.pageInfo.first = first; + this.pageInfo._links.first = { href: first }; } get prev(): string { return this.pageInfo.prev; } set prev(prev: string) { - this.pageInfo.prev = prev; + this.pageInfo._links.prev = { href: prev }; } get next(): string { @@ -71,7 +71,7 @@ export class PaginatedList { } set next(next: string) { - this.pageInfo.next = next; + this.pageInfo._links.next = { href: next }; } get last(): string { @@ -79,7 +79,7 @@ export class PaginatedList { } set last(last: string) { - this.pageInfo.last = last; + this.pageInfo._links.last = { href: last }; } get self(): string { @@ -87,7 +87,7 @@ export class PaginatedList { } set self(self: string) { - this.pageInfo.self = self; + this.pageInfo._links.self = { href: self }; } protected getPageLength() { diff --git a/src/app/core/data/registry-bitstreamformats-response-parsing.service.ts b/src/app/core/data/registry-bitstreamformats-response-parsing.service.ts index 5391a2a003..1cbcf358e3 100644 --- a/src/app/core/data/registry-bitstreamformats-response-parsing.service.ts +++ b/src/app/core/data/registry-bitstreamformats-response-parsing.service.ts @@ -1,11 +1,11 @@ +import { Injectable } from '@angular/core'; import { RegistryBitstreamformatsSuccessResponse, RestResponse } from '../cache/response.models'; -import { RegistryBitstreamformatsResponse } from '../registry/registry-bitstreamformats-response.model'; -import { NormalizedObjectSerializer } from '../dspace-rest-v2/normalized-object.serializer'; import { DSpaceRESTV2Response } from '../dspace-rest-v2/dspace-rest-v2-response.model'; -import { RestRequest } from './request.models'; +import { DSpaceSerializer } from '../dspace-rest-v2/dspace.serializer'; +import { RegistryBitstreamformatsResponse } from '../registry/registry-bitstreamformats-response.model'; import { DSOResponseParsingService } from './dso-response-parsing.service'; import { ResponseParsingService } from './parsing.service'; -import { Injectable } from '@angular/core'; +import { RestRequest } from './request.models'; @Injectable() export class RegistryBitstreamformatsResponseParsingService implements ResponseParsingService { @@ -18,7 +18,7 @@ export class RegistryBitstreamformatsResponseParsingService implements ResponseP const bitstreamformats = payload._embedded.bitstreamformats; payload.bitstreamformats = bitstreamformats; - const deserialized = new NormalizedObjectSerializer(RegistryBitstreamformatsResponse).deserialize(payload); + const deserialized = new DSpaceSerializer(RegistryBitstreamformatsResponse).deserialize(payload); return new RegistryBitstreamformatsSuccessResponse(deserialized, data.statusCode, data.statusText, this.dsoParser.processPageInfo(data.payload.page)); } diff --git a/src/app/core/data/registry-metadatafields-response-parsing.service.ts b/src/app/core/data/registry-metadatafields-response-parsing.service.ts index 4b826c23f3..cf9484c4c4 100644 --- a/src/app/core/data/registry-metadatafields-response-parsing.service.ts +++ b/src/app/core/data/registry-metadatafields-response-parsing.service.ts @@ -1,15 +1,12 @@ -import { - RegistryMetadatafieldsSuccessResponse, - RestResponse -} from '../cache/response.models'; -import { DSpaceRESTV2Response } from '../dspace-rest-v2/dspace-rest-v2-response.model'; -import { RestRequest } from './request.models'; -import { ResponseParsingService } from './parsing.service'; -import { NormalizedObjectSerializer } from '../dspace-rest-v2/normalized-object.serializer'; -import { DSOResponseParsingService } from './dso-response-parsing.service'; import { Injectable } from '@angular/core'; -import { RegistryMetadatafieldsResponse } from '../registry/registry-metadatafields-response.model'; import { hasValue } from '../../shared/empty.util'; +import { RegistryMetadatafieldsSuccessResponse, RestResponse } from '../cache/response.models'; +import { DSpaceRESTV2Response } from '../dspace-rest-v2/dspace-rest-v2-response.model'; +import { DSpaceSerializer } from '../dspace-rest-v2/dspace.serializer'; +import { RegistryMetadatafieldsResponse } from '../registry/registry-metadatafields-response.model'; +import { DSOResponseParsingService } from './dso-response-parsing.service'; +import { ResponseParsingService } from './parsing.service'; +import { RestRequest } from './request.models'; @Injectable() export class RegistryMetadatafieldsResponseParsingService implements ResponseParsingService { @@ -30,7 +27,7 @@ export class RegistryMetadatafieldsResponseParsingService implements ResponsePar payload.metadatafields = metadatafields; - const deserialized = new NormalizedObjectSerializer(RegistryMetadatafieldsResponse).deserialize(payload); + const deserialized = new DSpaceSerializer(RegistryMetadatafieldsResponse).deserialize(payload); return new RegistryMetadatafieldsSuccessResponse(deserialized, data.statusCode, data.statusText, this.dsoParser.processPageInfo(data.payload)); } diff --git a/src/app/core/data/registry-metadataschemas-response-parsing.service.ts b/src/app/core/data/registry-metadataschemas-response-parsing.service.ts index 9f60c6ec94..416ed19dc2 100644 --- a/src/app/core/data/registry-metadataschemas-response-parsing.service.ts +++ b/src/app/core/data/registry-metadataschemas-response-parsing.service.ts @@ -1,12 +1,12 @@ -import { RegistryMetadataschemasSuccessResponse, RestResponse } from '../cache/response.models'; -import { DSpaceRESTV2Response } from '../dspace-rest-v2/dspace-rest-v2-response.model'; -import { RestRequest } from './request.models'; -import { ResponseParsingService } from './parsing.service'; -import { RegistryMetadataschemasResponse } from '../registry/registry-metadataschemas-response.model'; -import { NormalizedObjectSerializer } from '../dspace-rest-v2/normalized-object.serializer'; -import { DSOResponseParsingService } from './dso-response-parsing.service'; import { Injectable } from '@angular/core'; import { hasValue } from '../../shared/empty.util'; +import { RegistryMetadataschemasSuccessResponse, RestResponse } from '../cache/response.models'; +import { DSpaceRESTV2Response } from '../dspace-rest-v2/dspace-rest-v2-response.model'; +import { DSpaceSerializer } from '../dspace-rest-v2/dspace.serializer'; +import { RegistryMetadataschemasResponse } from '../registry/registry-metadataschemas-response.model'; +import { DSOResponseParsingService } from './dso-response-parsing.service'; +import { ResponseParsingService } from './parsing.service'; +import { RestRequest } from './request.models'; @Injectable() export class RegistryMetadataschemasResponseParsingService implements ResponseParsingService { @@ -22,7 +22,7 @@ export class RegistryMetadataschemasResponseParsingService implements ResponsePa } payload.metadataschemas = metadataschemas; - const deserialized = new NormalizedObjectSerializer(RegistryMetadataschemasResponse).deserialize(payload); + const deserialized = new DSpaceSerializer(RegistryMetadataschemasResponse).deserialize(payload); return new RegistryMetadataschemasSuccessResponse(deserialized, data.statusCode, data.statusText, this.dsoParser.processPageInfo(data.payload)); } diff --git a/src/app/core/data/request.effects.ts b/src/app/core/data/request.effects.ts index 61b99e2b6d..76e6a188e2 100644 --- a/src/app/core/data/request.effects.ts +++ b/src/app/core/data/request.effects.ts @@ -1,12 +1,17 @@ -import { Observable, of as observableOf } from 'rxjs'; import { Inject, Injectable, Injector } from '@angular/core'; import { Actions, Effect, ofType } from '@ngrx/effects'; +import { Observable, of as observableOf } from 'rxjs'; +import { catchError, filter, flatMap, map, take } from 'rxjs/operators'; import { GLOBAL_CONFIG, GlobalConfig } from '../../../config'; import { hasValue, isNotEmpty } from '../../shared/empty.util'; +import { StoreActionTypes } from '../../store.actions'; +import { getMapsToType } from '../cache/builders/build-decorators'; +import { ErrorResponse, RestResponse } from '../cache/response.models'; import { DSpaceRESTV2Response } from '../dspace-rest-v2/dspace-rest-v2-response.model'; import { DSpaceRESTv2Service } from '../dspace-rest-v2/dspace-rest-v2.service'; +import { DSpaceSerializer } from '../dspace-rest-v2/dspace.serializer'; import { RequestActionTypes, RequestCompleteAction, @@ -16,11 +21,6 @@ import { import { RequestError, RestRequest } from './request.models'; import { RequestEntry } from './request.reducer'; import { RequestService } from './request.service'; -import { NormalizedObjectSerializer } from '../dspace-rest-v2/normalized-object.serializer'; -import { catchError, filter, flatMap, map, take, tap } from 'rxjs/operators'; -import { ErrorResponse, RestResponse } from '../cache/response.models'; -import { StoreActionTypes } from '../../store.actions'; -import { getMapsToType } from '../cache/builders/build-decorators'; export const addToResponseCacheAndCompleteAction = (request: RestRequest, envConfig: GlobalConfig) => (source: Observable): Observable => @@ -45,7 +45,7 @@ export class RequestEffects { flatMap((request: RestRequest) => { let body; if (isNotEmpty(request.body)) { - const serializer = new NormalizedObjectSerializer(getMapsToType(request.body.type)); + const serializer = new DSpaceSerializer(getMapsToType(request.body.type)); body = serializer.serialize(request.body); } return this.restApi.request(request.method, request.href, body, request.options).pipe( diff --git a/src/app/core/data/search-response-parsing.service.ts b/src/app/core/data/search-response-parsing.service.ts index f7c20b1eac..5307a0bd94 100644 --- a/src/app/core/data/search-response-parsing.service.ts +++ b/src/app/core/data/search-response-parsing.service.ts @@ -1,13 +1,13 @@ import { Injectable } from '@angular/core'; +import { hasValue } from '../../shared/empty.util'; +import { SearchQueryResponse } from '../../shared/search/search-query-response.model'; import { RestResponse, SearchSuccessResponse } from '../cache/response.models'; +import { DSpaceRESTV2Response } from '../dspace-rest-v2/dspace-rest-v2-response.model'; +import { DSpaceSerializer } from '../dspace-rest-v2/dspace.serializer'; +import { MetadataMap, MetadataValue } from '../shared/metadata.models'; import { DSOResponseParsingService } from './dso-response-parsing.service'; import { ResponseParsingService } from './parsing.service'; import { RestRequest } from './request.models'; -import { DSpaceRESTV2Response } from '../dspace-rest-v2/dspace-rest-v2-response.model'; -import { NormalizedObjectSerializer } from '../dspace-rest-v2/normalized-object.serializer'; -import { hasValue } from '../../shared/empty.util'; -import { SearchQueryResponse } from '../../shared/search/search-query-response.model'; -import { MetadataMap, MetadataValue } from '../shared/metadata.models'; @Injectable() export class SearchResponseParsingService implements ResponseParsingService { @@ -61,7 +61,7 @@ export class SearchResponseParsingService implements ResponseParsingService { hitHighlights: hitHighlights[index], })); payload.objects = objects; - const deserialized = new NormalizedObjectSerializer(SearchQueryResponse).deserialize(payload); + const deserialized = new DSpaceSerializer(SearchQueryResponse).deserialize(payload); return new SearchSuccessResponse(deserialized, data.statusCode, data.statusText, this.dsoParser.processPageInfo(payload)); } } diff --git a/src/app/core/metadata/metadata-field.model.ts b/src/app/core/metadata/metadata-field.model.ts index bb4700e3b8..d4931a127d 100644 --- a/src/app/core/metadata/metadata-field.model.ts +++ b/src/app/core/metadata/metadata-field.model.ts @@ -1,4 +1,4 @@ -import { autoserialize } from 'cerialize'; +import { autoserialize, deserialize } from 'cerialize'; import { isNotEmpty } from '../../shared/empty.util'; import { ListableObject } from '../../shared/object-collection/shared/listable-object.model'; import { link, resourceType } from '../cache/builders/build-decorators'; @@ -9,7 +9,6 @@ import { ResourceType } from '../shared/resource-type'; import { excludeFromEquals } from '../utilities/equals.decorators'; import { METADATA_FIELD } from './metadata-field.resource-type'; import { MetadataSchema } from './metadata-schema.model'; -import { METADATA_SCHEMA } from './metadata-schema.resource-type'; /** * Class the represents a metadata field @@ -28,41 +27,44 @@ export class MetadataField extends ListableObject implements HALResource { /** * The identifier of this metadata field */ + @autoserialize id: number; - /** - * The self link of this metadata field - */ - self: string; - /** * The element of this metadata field */ + @autoserialize element: string; /** * The qualifier of this metadata field */ + @autoserialize qualifier: string; /** * The scope note of this metadata field */ + @autoserialize scopeNote: string; + /** + * The HALLinks for this MetadataField + */ + @deserialize + _links: { + self: HALLink, + schema: HALLink + }; + /** * The MetadataSchema for this MetadataField * Will be undefined unless the schema HALLink has been resolved. */ - @link(METADATA_SCHEMA) - // TODO the responseparsingservice assumes schemas are always embedded. This should be remotedata instead. + // TODO the responseparsingservice assumes schemas are always embedded. This should use remotedata, and be a link instead. + // @link(METADATA_SCHEMA) schema?: MetadataSchema; - _links: { - self: HALLink, - schema: HALLink - }; - /** * Method to print this metadata field as a string * @param separator The separator between the schema, element and qualifier in the string diff --git a/src/app/core/metadata/metadata-schema.model.ts b/src/app/core/metadata/metadata-schema.model.ts index 16fa820837..9adfcc2479 100644 --- a/src/app/core/metadata/metadata-schema.model.ts +++ b/src/app/core/metadata/metadata-schema.model.ts @@ -1,4 +1,4 @@ -import { autoserialize } from 'cerialize'; +import { autoserialize, deserialize } from 'cerialize'; import { ListableObject } from '../../shared/object-collection/shared/listable-object.model'; import { resourceType } from '../cache/builders/build-decorators'; import { GenericConstructor } from '../shared/generic-constructor'; @@ -18,6 +18,7 @@ export class MetadataSchema extends ListableObject implements HALResource { /** * The unique identifier for this metadata schema */ + @autoserialize id: number; /** @@ -30,13 +31,16 @@ export class MetadataSchema extends ListableObject implements HALResource { /** * A unique prefix that defines this schema */ + @autoserialize prefix: string; /** * The namespace of this metadata schema */ + @autoserialize namespace: string; + @deserialize _links: { self: HALLink, }; diff --git a/src/app/core/metadata/normalized-metadata-field.model.ts b/src/app/core/metadata/normalized-metadata-field.model.ts deleted file mode 100644 index 6c7d8601e9..0000000000 --- a/src/app/core/metadata/normalized-metadata-field.model.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { autoserialize, deserialize, inheritSerialization } from 'cerialize'; -import { relationship } from '../cache/builders/build-decorators'; -import { MetadataField } from './metadata-field.model'; -import { NormalizedObject } from '../cache/models/normalized-object.model'; -import { MetadataSchema } from './metadata-schema.model'; - -/** - * Class the represents a normalized metadata field - */ -@inheritSerialization(NormalizedObject) -export class NormalizedMetadataField extends NormalizedObject { - - /** - * The identifier of this normalized metadata field - */ - @autoserialize - id: number; - - /** - * The self link of this normalized metadata field - */ - @autoserialize - self: string; - - /** - * The element of this normalized metadata field - */ - @autoserialize - element: string; - - /** - * The qualifier of this normalized metadata field - */ - @autoserialize - qualifier: string; - - /** - * The scope note of this normalized metadata field - */ - @autoserialize - scopeNote: string; - - /** - * The link to the metadata schema of this normalized metadata field - */ - @deserialize - @relationship(MetadataSchema) - schema: string; -} diff --git a/src/app/core/metadata/normalized-metadata-schema.model.ts b/src/app/core/metadata/normalized-metadata-schema.model.ts deleted file mode 100644 index dc4b012378..0000000000 --- a/src/app/core/metadata/normalized-metadata-schema.model.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { autoserialize, inheritSerialization } from 'cerialize'; -import { NormalizedObject } from '../cache/models/normalized-object.model'; -import { MetadataSchema } from './metadata-schema.model'; - -/** - * Normalized class for a DSpace MetadataSchema - */ -@inheritSerialization(NormalizedObject) -export class NormalizedMetadataSchema extends NormalizedObject { - /** - * The unique identifier for this schema - */ - @autoserialize - id: number; - - /** - * The REST link to itself - */ - @autoserialize - self: string; - - /** - * A unique prefix that defines this schema - */ - @autoserialize - prefix: string; - - /** - * The namespace for this schema - */ - @autoserialize - namespace: string; - -} diff --git a/src/app/core/registry/registry.service.ts b/src/app/core/registry/registry.service.ts index 05495af7eb..7d38365c2e 100644 --- a/src/app/core/registry/registry.service.ts +++ b/src/app/core/registry/registry.service.ts @@ -2,6 +2,7 @@ import { combineLatest as observableCombineLatest, Observable } from 'rxjs'; import { Injectable } from '@angular/core'; import { RemoteData } from '../data/remote-data'; import { PaginatedList } from '../data/paginated-list'; +import { DSpaceSerializer } from '../dspace-rest-v2/dspace.serializer'; import { PageInfo } from '../shared/page-info.model'; import { CreateMetadataFieldRequest, @@ -48,8 +49,6 @@ import { MetadataRegistrySelectSchemaAction } from '../../+admin/admin-registries/metadata-registry/metadata-registry.actions'; import { distinctUntilChanged, flatMap, map, take, tap } from 'rxjs/operators'; -import { NormalizedObjectSerializer } from '../dspace-rest-v2/normalized-object.serializer'; -import { NormalizedMetadataSchema } from '../metadata/normalized-metadata-schema.model'; import { NotificationsService } from '../../shared/notifications/notifications.service'; import { NotificationOptions } from '../../shared/notifications/models/notification-options.model'; import { HttpOptions } from '../dspace-rest-v2/dspace-rest-v2.service'; @@ -400,7 +399,7 @@ export class RegistryService { distinctUntilChanged() ); - const serializedSchema = new NormalizedObjectSerializer(getMapsToType(MetadataSchema.type)).serialize(schema); + const serializedSchema = new DSpaceSerializer(getMapsToType(MetadataSchema.type)).serialize(schema); const request$ = endpoint$.pipe( take(1), diff --git a/src/app/core/shared/content-source.model.ts b/src/app/core/shared/content-source.model.ts index cd53c2d81e..9e93e9d529 100644 --- a/src/app/core/shared/content-source.model.ts +++ b/src/app/core/shared/content-source.model.ts @@ -1,4 +1,6 @@ import { autoserialize, autoserializeAs, deserializeAs, deserialize } from 'cerialize'; +import { HALLink } from './hal-link.model'; +import { HALResource } from './hal-resource.model'; import { MetadataConfig } from './metadata-config.model'; /** @@ -14,7 +16,7 @@ export enum ContentSourceHarvestType { /** * A model class that holds information about the Content Source of a Collection */ -export class ContentSource { +export class ContentSource implements HALResource{ /** * Unique identifier, this is necessary to store the ContentSource in FieldUpdates * Because the ContentSource coming from the REST API doesn't have a UUID, we're using the selflink @@ -53,8 +55,10 @@ export class ContentSource { metadataConfigs: MetadataConfig[]; /** - * The REST link to itself + * The HALLinks for this ContentSource */ @deserialize - self: string; + _links: { + self: HALLink + } } diff --git a/src/app/core/shared/page-info.model.ts b/src/app/core/shared/page-info.model.ts index 273510da60..c077c30b4c 100644 --- a/src/app/core/shared/page-info.model.ts +++ b/src/app/core/shared/page-info.model.ts @@ -1,10 +1,12 @@ -import { autoserialize, autoserializeAs } from 'cerialize'; +import { autoserialize, autoserializeAs, deserialize } from 'cerialize'; import { hasValue } from '../../shared/empty.util'; +import { HALLink } from './hal-link.model'; +import { HALResource } from './hal-resource.model'; /** * Represents the state of a paginated response */ -export class PageInfo { +export class PageInfo implements HALResource { /** * The number of elements on a page @@ -30,20 +32,17 @@ export class PageInfo { @autoserializeAs(Number, 'number') currentPage: number; - @autoserialize - last: string; - - @autoserialize - next: string; - - @autoserialize - prev: string; - - @autoserialize - first: string; - - @autoserialize - self: string; + /** + * The HALLinks for this PageInfo + */ + @deserialize + _links: { + first: HALLink; + prev: HALLink; + next: HALLink; + last: HALLink; + self: HALLink; + }; constructor( options?: { @@ -60,4 +59,41 @@ export class PageInfo { this.currentPage = options.currentPage; } } + + get self() { + return this._links.self.href; + } + + get last(): string { + if (hasValue(this._links.last)) { + return this._links.last.href; + } else { + return undefined; + } + } + + get next(): string { + if (hasValue(this._links.next)) { + return this._links.next.href; + } else { + return undefined; + } + } + + get prev(): string { + if (hasValue(this._links.prev)) { + return this._links.prev.href; + } else { + return undefined; + } + } + + get first(): string { + if (hasValue(this._links.first)) { + return this._links.first.href; + } else { + return undefined; + } + } + } diff --git a/src/app/shared/search/normalized-search-result.model.ts b/src/app/shared/search/normalized-search-result.model.ts deleted file mode 100644 index 3904b4a494..0000000000 --- a/src/app/shared/search/normalized-search-result.model.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { autoserialize, inheritSerialization } from 'cerialize'; -import { MetadataMap } from '../../core/shared/metadata.models'; -import { NormalizedObject } from '../../core/cache/models/normalized-object.model'; - -/** - * Represents a normalized version of a search result object of a certain DSpaceObject - */ -@inheritSerialization(NormalizedObject) -export class NormalizedSearchResult { - /** - * The UUID of the DSpaceObject that was found - */ - @autoserialize - indexableObject: string; - - /** - * The metadata that was used to find this item, hithighlighted - */ - @autoserialize - hitHighlights: MetadataMap; -} From 884e94a08b0489dfba8e445a63f8881b0cba0c20 Mon Sep 17 00:00:00 2001 From: Marie Verdonck Date: Thu, 13 Feb 2020 18:55:06 +0100 Subject: [PATCH 22/38] 68405: test fixes --- .../item-move/item-move.component.spec.ts | 70 ++++---- .../edit-relationship-list.component.spec.ts | 48 +++--- .../edit-relationship.component.spec.ts | 30 ++-- .../item-relationships.component.spec.ts | 56 ++++--- .../core/cache/object-cache.service.spec.ts | 9 +- .../cache/server-sync-buffer.effects.spec.ts | 29 ++-- .../models/config-submission-section.model.ts | 5 +- .../browse-response-parsing.service.spec.ts | 3 - src/app/core/data/data.service.spec.ts | 42 ++--- src/app/core/data/item-data.service.spec.ts | 34 ++-- src/app/core/data/item-data.service.ts | 4 +- .../core/data/relationship.service.spec.ts | 28 ++-- ...tegration-response-parsing.service.spec.ts | 12 +- .../core/registry/registry.service.spec.ts | 156 ++++++++++-------- .../comcol-form/comcol-form.component.spec.ts | 52 +++--- .../comcol-form/comcol-form.component.ts | 42 +++-- .../create-comcol-page.component.ts | 25 ++- src/app/shared/mocks/mock-link-service.ts | 9 + ...arch-result-list-element.component.spec.ts | 18 +- ...arch-result-list-element.component.spec.ts | 15 +- 20 files changed, 379 insertions(+), 308 deletions(-) create mode 100644 src/app/shared/mocks/mock-link-service.ts diff --git a/src/app/+item-page/edit-item-page/item-move/item-move.component.spec.ts b/src/app/+item-page/edit-item-page/item-move/item-move.component.spec.ts index aa84b160a0..add1b39d90 100644 --- a/src/app/+item-page/edit-item-page/item-move/item-move.component.spec.ts +++ b/src/app/+item-page/edit-item-page/item-move/item-move.component.spec.ts @@ -1,23 +1,23 @@ -import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { Item } from '../../../core/shared/item.model'; -import { RouterStub } from '../../../shared/testing/router-stub'; import { CommonModule } from '@angular/common'; -import { RouterTestingModule } from '@angular/router/testing'; -import { TranslateModule } from '@ngx-translate/core'; -import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; -import { ActivatedRoute, Router } from '@angular/router'; -import { ItemMoveComponent } from './item-move.component'; -import { NotificationsServiceStub } from '../../../shared/testing/notifications-service-stub'; -import { NotificationsService } from '../../../shared/notifications/notifications.service'; -import { of as observableOf } from 'rxjs'; -import { FormsModule } from '@angular/forms'; -import { ItemDataService } from '../../../core/data/item-data.service'; -import { RemoteData } from '../../../core/data/remote-data'; -import { PaginatedList } from '../../../core/data/paginated-list'; import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { FormsModule } from '@angular/forms'; +import { ActivatedRoute, Router } from '@angular/router'; +import { RouterTestingModule } from '@angular/router/testing'; +import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; +import { TranslateModule } from '@ngx-translate/core'; +import { of as observableOf } from 'rxjs'; import { RestResponse } from '../../../core/cache/response.models'; +import { ItemDataService } from '../../../core/data/item-data.service'; +import { PaginatedList } from '../../../core/data/paginated-list'; +import { RemoteData } from '../../../core/data/remote-data'; import { Collection } from '../../../core/shared/collection.model'; +import { Item } from '../../../core/shared/item.model'; import { SearchService } from '../../../core/shared/search/search.service'; +import { NotificationsService } from '../../../shared/notifications/notifications.service'; +import { NotificationsServiceStub } from '../../../shared/testing/notifications-service-stub'; +import { RouterStub } from '../../../shared/testing/router-stub'; +import { ItemMoveComponent } from './item-move.component'; describe('ItemMoveComponent', () => { let comp: ItemMoveComponent; @@ -50,16 +50,14 @@ describe('ItemMoveComponent', () => { }) }; - const collection1 = Object.assign(new Collection(),{ + const collection1 = Object.assign(new Collection(), { uuid: 'collection-uuid-1', - name: 'Test collection 1', - self: 'self-link-1', + name: 'Test collection 1' }); - const collection2 = Object.assign(new Collection(),{ + const collection2 = Object.assign(new Collection(), { uuid: 'collection-uuid-2', - name: 'Test collection 2', - self: 'self-link-2', + name: 'Test collection 2' }); const mockSearchService = { @@ -80,23 +78,20 @@ describe('ItemMoveComponent', () => { const notificationsServiceStub = new NotificationsServiceStub(); describe('ItemMoveComponent success', () => { - beforeEach(async(() => { + beforeEach(() => { TestBed.configureTestingModule({ imports: [CommonModule, FormsModule, RouterTestingModule.withRoutes([]), TranslateModule.forRoot(), NgbModule.forRoot()], declarations: [ItemMoveComponent], providers: [ - {provide: ActivatedRoute, useValue: routeStub}, - {provide: Router, useValue: routerStub}, - {provide: ItemDataService, useValue: mockItemDataService}, - {provide: NotificationsService, useValue: notificationsServiceStub}, - {provide: SearchService, useValue: mockSearchService}, + { provide: ActivatedRoute, useValue: routeStub }, + { provide: Router, useValue: routerStub }, + { provide: ItemDataService, useValue: mockItemDataService }, + { provide: NotificationsService, useValue: notificationsServiceStub }, + { provide: SearchService, useValue: mockSearchService }, ], schemas: [ CUSTOM_ELEMENTS_SCHEMA ] }).compileComponents(); - })); - - beforeEach(() => { fixture = TestBed.createComponent(ItemMoveComponent); comp = fixture.componentInstance; fixture.detectChanges(); @@ -141,23 +136,20 @@ describe('ItemMoveComponent', () => { }); describe('ItemMoveComponent fail', () => { - beforeEach(async(() => { + beforeEach(() => { TestBed.configureTestingModule({ imports: [CommonModule, FormsModule, RouterTestingModule.withRoutes([]), TranslateModule.forRoot(), NgbModule.forRoot()], declarations: [ItemMoveComponent], providers: [ - {provide: ActivatedRoute, useValue: routeStub}, - {provide: Router, useValue: routerStub}, - {provide: ItemDataService, useValue: mockItemDataServiceFail}, - {provide: NotificationsService, useValue: notificationsServiceStub}, - {provide: SearchService, useValue: mockSearchService}, + { provide: ActivatedRoute, useValue: routeStub }, + { provide: Router, useValue: routerStub }, + { provide: ItemDataService, useValue: mockItemDataServiceFail }, + { provide: NotificationsService, useValue: notificationsServiceStub }, + { provide: SearchService, useValue: mockSearchService }, ], schemas: [ CUSTOM_ELEMENTS_SCHEMA ] }).compileComponents(); - })); - - beforeEach(() => { fixture = TestBed.createComponent(ItemMoveComponent); comp = fixture.componentInstance; fixture.detectChanges(); diff --git a/src/app/+item-page/edit-item-page/item-relationships/edit-relationship-list/edit-relationship-list.component.spec.ts b/src/app/+item-page/edit-item-page/item-relationships/edit-relationship-list/edit-relationship-list.component.spec.ts index cede48e6ee..cef5e82957 100644 --- a/src/app/+item-page/edit-item-page/item-relationships/edit-relationship-list/edit-relationship-list.component.spec.ts +++ b/src/app/+item-page/edit-item-page/item-relationships/edit-relationship-list/edit-relationship-list.component.spec.ts @@ -1,19 +1,19 @@ -import {EditRelationshipListComponent} from './edit-relationship-list.component'; -import {async, ComponentFixture, TestBed} from '@angular/core/testing'; -import {RelationshipType} from '../../../../core/shared/item-relationships/relationship-type.model'; -import {Relationship} from '../../../../core/shared/item-relationships/relationship.model'; -import {of as observableOf} from 'rxjs/internal/observable/of'; -import {RemoteData} from '../../../../core/data/remote-data'; -import {Item} from '../../../../core/shared/item.model'; -import {PaginatedList} from '../../../../core/data/paginated-list'; -import {PageInfo} from '../../../../core/shared/page-info.model'; -import {FieldChangeType} from '../../../../core/data/object-updates/object-updates.actions'; -import {SharedModule} from '../../../../shared/shared.module'; -import {TranslateModule} from '@ngx-translate/core'; -import {ObjectUpdatesService} from '../../../../core/data/object-updates/object-updates.service'; -import {DebugElement, NO_ERRORS_SCHEMA} from '@angular/core'; -import {By} from '@angular/platform-browser'; -import {ItemType} from '../../../../core/shared/item-relationships/item-type.model'; +import { DebugElement, NO_ERRORS_SCHEMA } from '@angular/core'; +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { By } from '@angular/platform-browser'; +import { TranslateModule } from '@ngx-translate/core'; +import { of as observableOf } from 'rxjs/internal/observable/of'; +import { FieldChangeType } from '../../../../core/data/object-updates/object-updates.actions'; +import { ObjectUpdatesService } from '../../../../core/data/object-updates/object-updates.service'; +import { PaginatedList } from '../../../../core/data/paginated-list'; +import { RemoteData } from '../../../../core/data/remote-data'; +import { ItemType } from '../../../../core/shared/item-relationships/item-type.model'; +import { RelationshipType } from '../../../../core/shared/item-relationships/relationship-type.model'; +import { Relationship } from '../../../../core/shared/item-relationships/relationship.model'; +import { Item } from '../../../../core/shared/item.model'; +import { PageInfo } from '../../../../core/shared/page-info.model'; +import { SharedModule } from '../../../../shared/shared.module'; +import { EditRelationshipListComponent } from './edit-relationship-list.component'; let comp: EditRelationshipListComponent; let fixture: ComponentFixture; @@ -57,7 +57,11 @@ describe('EditRelationshipListComponent', () => { }); relationship1 = Object.assign(new Relationship(), { - self: url + '/2', + _links: { + self: { + href: url + '/2' + } + }, id: '2', uuid: '2', leftId: 'author1', @@ -68,7 +72,11 @@ describe('EditRelationshipListComponent', () => { }); relationship2 = Object.assign(new Relationship(), { - self: url + '/3', + _links: { + self: { + href: url + '/3' + } + }, id: '3', uuid: '3', leftId: 'author2', @@ -79,7 +87,9 @@ describe('EditRelationshipListComponent', () => { }); item = Object.assign(new Item(), { - self: 'fake-item-url/publication', + _links: { + self: { href: 'fake-item-url/publication' } + }, id: 'publication', uuid: 'publication', relationships: observableOf(new RemoteData( diff --git a/src/app/+item-page/edit-item-page/item-relationships/edit-relationship/edit-relationship.component.spec.ts b/src/app/+item-page/edit-item-page/item-relationships/edit-relationship/edit-relationship.component.spec.ts index b3c3e773b2..9eca3f270d 100644 --- a/src/app/+item-page/edit-item-page/item-relationships/edit-relationship/edit-relationship.component.spec.ts +++ b/src/app/+item-page/edit-item-page/item-relationships/edit-relationship/edit-relationship.component.spec.ts @@ -1,16 +1,16 @@ -import { async, TestBed } from '@angular/core/testing'; -import { of as observableOf } from 'rxjs/internal/observable/of'; -import { TranslateModule } from '@ngx-translate/core'; -import { ObjectUpdatesService } from '../../../../core/data/object-updates/object-updates.service'; import { NO_ERRORS_SCHEMA } from '@angular/core'; -import { EditRelationshipComponent } from './edit-relationship.component'; +import { async, TestBed } from '@angular/core/testing'; +import { TranslateModule } from '@ngx-translate/core'; +import { of as observableOf } from 'rxjs/internal/observable/of'; +import { FieldChangeType } from '../../../../core/data/object-updates/object-updates.actions'; +import { ObjectUpdatesService } from '../../../../core/data/object-updates/object-updates.service'; +import { PaginatedList } from '../../../../core/data/paginated-list'; +import { RemoteData } from '../../../../core/data/remote-data'; import { RelationshipType } from '../../../../core/shared/item-relationships/relationship-type.model'; import { Relationship } from '../../../../core/shared/item-relationships/relationship.model'; -import { RemoteData } from '../../../../core/data/remote-data'; import { Item } from '../../../../core/shared/item.model'; -import { PaginatedList } from '../../../../core/data/paginated-list'; import { PageInfo } from '../../../../core/shared/page-info.model'; -import { FieldChangeType } from '../../../../core/data/object-updates/object-updates.actions'; +import { EditRelationshipComponent } from './edit-relationship.component'; import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; let objectUpdatesService; @@ -42,7 +42,11 @@ describe('EditRelationshipComponent', () => { }); item = Object.assign(new Item(), { - self: 'fake-item-url/publication', + _links: { + self: { + href: 'fake-item-url/publication' + } + }, id: 'publication', uuid: 'publication', relationships: observableOf(new RemoteData(false, false, true, undefined, new PaginatedList(new PageInfo(), relationships))) @@ -54,7 +58,9 @@ describe('EditRelationshipComponent', () => { relationships = [ Object.assign(new Relationship(), { - self: url + '/2', + _links: { + self: { href: url + '/2' } + }, id: '2', uuid: '2', leftId: 'author1', @@ -64,7 +70,9 @@ describe('EditRelationshipComponent', () => { rightItem: observableOf(new RemoteData(false, false, true, undefined, item)), }), Object.assign(new Relationship(), { - self: url + '/3', + _links: { + self: { href: url + '/3' } + }, id: '3', uuid: '3', leftId: 'author2', diff --git a/src/app/+item-page/edit-item-page/item-relationships/item-relationships.component.spec.ts b/src/app/+item-page/edit-item-page/item-relationships/item-relationships.component.spec.ts index aa812354b6..731e4885a6 100644 --- a/src/app/+item-page/edit-item-page/item-relationships/item-relationships.component.spec.ts +++ b/src/app/+item-page/edit-item-page/item-relationships/item-relationships.component.spec.ts @@ -1,32 +1,32 @@ -import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { ItemRelationshipsComponent } from './item-relationships.component'; import { ChangeDetectorRef, DebugElement, NO_ERRORS_SCHEMA } from '@angular/core'; -import { INotification, Notification } from '../../../shared/notifications/models/notification.model'; -import { NotificationType } from '../../../shared/notifications/models/notification-type'; -import { RouterStub } from '../../../shared/testing/router-stub'; -import { TestScheduler } from 'rxjs/testing'; -import { SharedModule } from '../../../shared/shared.module'; -import { TranslateModule } from '@ngx-translate/core'; -import { ItemDataService } from '../../../core/data/item-data.service'; -import { ObjectUpdatesService } from '../../../core/data/object-updates/object-updates.service'; +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { ActivatedRoute, Router } from '@angular/router'; -import { NotificationsService } from '../../../shared/notifications/notifications.service'; +import { TranslateModule } from '@ngx-translate/core'; +import { getTestScheduler } from 'jasmine-marbles'; +import { combineLatest as observableCombineLatest, of as observableOf } from 'rxjs'; +import { TestScheduler } from 'rxjs/testing'; import { GLOBAL_CONFIG } from '../../../../config'; +import { ObjectCacheService } from '../../../core/cache/object-cache.service'; +import { RestResponse } from '../../../core/cache/response.models'; +import { EntityTypeService } from '../../../core/data/entity-type.service'; +import { ItemDataService } from '../../../core/data/item-data.service'; +import { FieldChangeType } from '../../../core/data/object-updates/object-updates.actions'; +import { ObjectUpdatesService } from '../../../core/data/object-updates/object-updates.service'; +import { PaginatedList } from '../../../core/data/paginated-list'; +import { RelationshipService } from '../../../core/data/relationship.service'; +import { RemoteData } from '../../../core/data/remote-data'; +import { RequestService } from '../../../core/data/request.service'; +import { ItemType } from '../../../core/shared/item-relationships/item-type.model'; import { RelationshipType } from '../../../core/shared/item-relationships/relationship-type.model'; import { Relationship } from '../../../core/shared/item-relationships/relationship.model'; -import { combineLatest as observableCombineLatest, of as observableOf } from 'rxjs'; -import { RemoteData } from '../../../core/data/remote-data'; import { Item } from '../../../core/shared/item.model'; -import { PaginatedList } from '../../../core/data/paginated-list'; import { PageInfo } from '../../../core/shared/page-info.model'; -import { FieldChangeType } from '../../../core/data/object-updates/object-updates.actions'; -import { RelationshipService } from '../../../core/data/relationship.service'; -import { ObjectCacheService } from '../../../core/cache/object-cache.service'; -import { getTestScheduler } from 'jasmine-marbles'; -import { RestResponse } from '../../../core/cache/response.models'; -import { RequestService } from '../../../core/data/request.service'; -import { EntityTypeService } from '../../../core/data/entity-type.service'; -import { ItemType } from '../../../core/shared/item-relationships/item-type.model'; +import { NotificationType } from '../../../shared/notifications/models/notification-type'; +import { + INotification, + Notification +} from '../../../shared/notifications/models/notification.model'; +import { ItemRelationshipsComponent } from './item-relationships.component'; let comp: any; let fixture: ComponentFixture; @@ -77,13 +77,17 @@ describe('ItemRelationshipsComponent', () => { relationships = [ Object.assign(new Relationship(), { - self: url + '/2', + _links: { + self: { href: url + '/2' } + }, id: '2', uuid: '2', relationshipType: observableOf(new RemoteData(false, false, true, undefined, relationshipType)) }), Object.assign(new Relationship(), { - self: url + '/3', + _links: { + self: { href: url + '/3' } + }, id: '3', uuid: '3', relationshipType: observableOf(new RemoteData(false, false, true, undefined, relationshipType)) @@ -91,7 +95,9 @@ describe('ItemRelationshipsComponent', () => { ]; item = Object.assign(new Item(), { - self: 'fake-item-url/publication', + _links: { + self: { href: 'fake-item-url/publication' } + }, id: 'publication', uuid: 'publication', relationships: observableOf(new RemoteData(false, false, true, undefined, new PaginatedList(new PageInfo(), relationships))), diff --git a/src/app/core/cache/object-cache.service.spec.ts b/src/app/core/cache/object-cache.service.spec.ts index e2bf27e791..461263d131 100644 --- a/src/app/core/cache/object-cache.service.spec.ts +++ b/src/app/core/cache/object-cache.service.spec.ts @@ -27,7 +27,6 @@ describe('ObjectCacheService', () => { const timestamp = new Date().getTime(); const msToLive = 900000; let objectToCache = { - self: selfLink, type: Item.type, _links: { self: { href: selfLink } @@ -39,7 +38,6 @@ describe('ObjectCacheService', () => { function init() { objectToCache = { - self: selfLink, type: Item.type, _links: { self: { href: selfLink } @@ -115,12 +113,13 @@ describe('ObjectCacheService', () => { describe('getList', () => { it('should return an observable of the array of cached objects with the specified self link and type', () => { - const item = new Item(); - item._links.self = { href: selfLink }; + const item = Object.assign(new Item(), { + _links: { self: { href: selfLink } } + }); spyOn(service, 'getObjectBySelfLink').and.returnValue(observableOf(item)); service.getList([selfLink, selfLink]).pipe(first()).subscribe((arr) => { - expect(arr[0].self).toBe(selfLink); + expect(arr[0]._links.self.href).toBe(selfLink); expect(arr[0] instanceof Item).toBeTruthy(); }); }); diff --git a/src/app/core/cache/server-sync-buffer.effects.spec.ts b/src/app/core/cache/server-sync-buffer.effects.spec.ts index 52407270c2..37ad0e6346 100644 --- a/src/app/core/cache/server-sync-buffer.effects.spec.ts +++ b/src/app/core/cache/server-sync-buffer.effects.spec.ts @@ -1,22 +1,22 @@ import { TestBed } from '@angular/core/testing'; - -import { Observable, of as observableOf } from 'rxjs'; import { provideMockActions } from '@ngrx/effects/testing'; +import { Store, StoreModule } from '@ngrx/store'; import { cold, hot } from 'jasmine-marbles'; -import { ServerSyncBufferEffects } from './server-sync-buffer.effects'; -import { GLOBAL_CONFIG } from '../../../config'; -import { CommitSSBAction, EmptySSBAction, ServerSyncBufferActionTypes } from './server-sync-buffer.actions'; -import { RestRequestMethod } from '../data/rest-request-method'; -import { Store, StoreModule } from '@ngrx/store'; -import { RequestService } from '../data/request.service'; -import { ObjectCacheService } from './object-cache.service'; -import { MockStore } from '../../shared/testing/mock-store'; +import { Observable, of as observableOf } from 'rxjs'; import * as operators from 'rxjs/operators'; -import { spyOnOperator } from '../../shared/testing/utils'; -import { DSpaceObject } from '../shared/dspace-object.model'; +import { GLOBAL_CONFIG } from '../../../config'; import { getMockRequestService } from '../../shared/mocks/mock-request.service'; +import { MockStore } from '../../shared/testing/mock-store'; +import { spyOnOperator } from '../../shared/testing/utils'; +import { RequestService } from '../data/request.service'; +import { RestRequestMethod } from '../data/rest-request-method'; +import { DSpaceObject } from '../shared/dspace-object.model'; import { ApplyPatchObjectCacheAction } from './object-cache.actions'; +import { ObjectCacheService } from './object-cache.service'; +import { CommitSSBAction, EmptySSBAction, ServerSyncBufferActionTypes } from './server-sync-buffer.actions'; + +import { ServerSyncBufferEffects } from './server-sync-buffer.effects'; describe('ServerSyncBufferEffects', () => { let ssbEffects: ServerSyncBufferEffects; @@ -47,8 +47,9 @@ describe('ServerSyncBufferEffects', () => { { provide: ObjectCacheService, useValue: { getObjectBySelfLink: (link) => { - const object = new DSpaceObject(); - object._links.self = { href: link }; + const object = Object.assign(new DSpaceObject(), { + _links: { self: { href: link } } + }); return observableOf(object); } } diff --git a/src/app/core/config/models/config-submission-section.model.ts b/src/app/core/config/models/config-submission-section.model.ts index f1881734d9..3c657c3d2a 100644 --- a/src/app/core/config/models/config-submission-section.model.ts +++ b/src/app/core/config/models/config-submission-section.model.ts @@ -1,9 +1,9 @@ import { autoserialize, deserialize } from 'cerialize'; +import { SectionsType } from '../../../submission/sections/sections-type'; import { resourceType } from '../../cache/builders/build-decorators'; import { HALLink } from '../../shared/hal-link.model'; -import { ConfigObject } from './config.model'; -import { SectionsType } from '../../../submission/sections/sections-type'; import { ResourceType } from '../../shared/resource-type'; +import { ConfigObject } from './config.model'; /** * An interface that define section visibility and its properties. @@ -47,6 +47,7 @@ export class SubmissionSectionModel extends ConfigObject { @deserialize _links: { self: HALLink; + config: HALLink; } } diff --git a/src/app/core/data/browse-response-parsing.service.spec.ts b/src/app/core/data/browse-response-parsing.service.spec.ts index a2ec2e8f62..fedfea1309 100644 --- a/src/app/core/data/browse-response-parsing.service.spec.ts +++ b/src/app/core/data/browse-response-parsing.service.spec.ts @@ -31,7 +31,6 @@ describe('BrowseResponseParsingService', () => { metadata: 'dc.date.issued' }, { name: 'dateaccessioned', metadata: 'dc.date.accessioned' }], order: 'ASC', - type: 'browse', metadata: ['dc.date.issued'], _links: { self: { href: 'https://rest.api/discover/browses/dateissued' }, @@ -44,7 +43,6 @@ describe('BrowseResponseParsingService', () => { metadata: 'dc.date.issued' }, { name: 'dateaccessioned', metadata: 'dc.date.accessioned' }], order: 'ASC', - type: 'browse', metadata: ['dc.contributor.*', 'dc.creator'], _links: { self: { href: 'https://rest.api/discover/browses/author' }, @@ -68,7 +66,6 @@ describe('BrowseResponseParsingService', () => { metadata: 'dc.date.issued' }, { name: 'dateaccessioned', metadata: 'dc.date.accessioned' }], order: 'ASC', - type: 'browse', metadata: ['dc.date.issued'], _links: { self: { href: 'https://rest.api/discover/browses/dateissued' }, diff --git a/src/app/core/data/data.service.spec.ts b/src/app/core/data/data.service.spec.ts index 2244b4c346..9e13850ad5 100644 --- a/src/app/core/data/data.service.spec.ts +++ b/src/app/core/data/data.service.spec.ts @@ -1,23 +1,23 @@ -import { DataService } from './data.service'; -import { NormalizedObject } from '../cache/models/normalized-object.model'; -import { RequestService } from './request.service'; -import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; -import { CoreState } from '../core.reducers'; +import { HttpClient } from '@angular/common/http'; import { Store } from '@ngrx/store'; -import { HALEndpointService } from '../shared/hal-endpoint.service'; +import { compare, Operation } from 'fast-json-patch'; import { Observable, of as observableOf } from 'rxjs'; -import { FindListOptions } from './request.models'; +import * as uuidv4 from 'uuid/v4'; +import { NotificationsService } from '../../shared/notifications/notifications.service'; +import { createSuccessfulRemoteDataObject$ } from '../../shared/testing/utils'; +import { NormalizedObjectBuildService } from '../cache/builders/normalized-object-build.service'; +import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; +import { NormalizedObject } from '../cache/models/normalized-object.model'; import { SortDirection, SortOptions } from '../cache/models/sort-options.model'; import { ObjectCacheService } from '../cache/object-cache.service'; -import { compare, Operation } from 'fast-json-patch'; +import { CoreState } from '../core.reducers'; import { DSpaceObject } from '../shared/dspace-object.model'; -import { ChangeAnalyzer } from './change-analyzer'; -import { HttpClient } from '@angular/common/http'; -import { NormalizedObjectBuildService } from '../cache/builders/normalized-object-build.service'; -import { NotificationsService } from '../../shared/notifications/notifications.service'; +import { HALEndpointService } from '../shared/hal-endpoint.service'; import { Item } from '../shared/item.model'; -import * as uuidv4 from 'uuid/v4'; -import { createSuccessfulRemoteDataObject$ } from '../../shared/testing/utils'; +import { ChangeAnalyzer } from './change-analyzer'; +import { DataService } from './data.service'; +import { FindListOptions } from './request.models'; +import { RequestService } from './request.service'; const endpoint = 'https://rest.api/core'; @@ -184,13 +184,15 @@ describe('DataService', () => { operations = [{ op: 'replace', path: '/0/value', value: name2 } as Operation]; selfLink = 'https://rest.api/endpoint/1698f1d3-be98-4c51-9fd8-6bfedcbd59b7'; - dso = new DSpaceObject(); - dso._links.self = { href: selfLink }; - dso.metadata = [{ key: 'dc.title', value: name1 }]; + dso = Object.assign(new DSpaceObject(), { + _links: { self: { href: selfLink } }, + metadata: [{ key: 'dc.title', value: name1 }] + }); - dso2 = new DSpaceObject(); - dso2._link.self = { href: selfLink }; - dso2.metadata = [{ key: 'dc.title', value: name2 }]; + dso2 = Object.assign(new DSpaceObject(), { + _links: { self: { href: selfLink } }, + metadata: [{ key: 'dc.title', value: name2 }] + }); spyOn(service, 'findByHref').and.returnValue(createSuccessfulRemoteDataObject$(dso)); spyOn(objectCache, 'addPatch'); diff --git a/src/app/core/data/item-data.service.spec.ts b/src/app/core/data/item-data.service.spec.ts index 8263601e28..6d96237db2 100644 --- a/src/app/core/data/item-data.service.spec.ts +++ b/src/app/core/data/item-data.service.spec.ts @@ -1,21 +1,21 @@ +import { HttpClient } from '@angular/common/http'; import { Store } from '@ngrx/store'; import { cold, getTestScheduler } from 'jasmine-marbles'; -import { TestScheduler } from 'rxjs/testing'; -import { BrowseService } from '../browse/browse.service'; -import { CoreState } from '../core.reducers'; -import { ItemDataService } from './item-data.service'; -import { RequestService } from './request.service'; -import { HALEndpointService } from '../shared/hal-endpoint.service'; -import { DeleteRequest, FindListOptions, PostRequest, RestRequest } from './request.models'; -import { ObjectCacheService } from '../cache/object-cache.service'; import { Observable, of as observableOf } from 'rxjs'; -import { RestResponse } from '../cache/response.models'; -import { NotificationsService } from '../../shared/notifications/notifications.service'; -import { NormalizedObjectBuildService } from '../cache/builders/normalized-object-build.service'; -import { HttpClient } from '@angular/common/http'; -import { RequestEntry } from './request.reducer'; +import { TestScheduler } from 'rxjs/testing'; import { getMockRequestService } from '../../shared/mocks/mock-request.service'; +import { NotificationsService } from '../../shared/notifications/notifications.service'; +import { BrowseService } from '../browse/browse.service'; +import { NormalizedObjectBuildService } from '../cache/builders/normalized-object-build.service'; +import { ObjectCacheService } from '../cache/object-cache.service'; +import { RestResponse } from '../cache/response.models'; +import { CoreState } from '../core.reducers'; import { ExternalSourceEntry } from '../shared/external-source-entry.model'; +import { HALEndpointService } from '../shared/hal-endpoint.service'; +import { ItemDataService } from './item-data.service'; +import { DeleteRequest, FindListOptions, PostRequest, RestRequest } from './request.models'; +import { RequestEntry } from './request.reducer'; +import { RequestService } from './request.service'; describe('ItemDataService', () => { let scheduler: TestScheduler; @@ -45,7 +45,7 @@ describe('ItemDataService', () => { const objectCache = {} as ObjectCacheService; const halEndpointService = { getEndpoint(linkPath: string): Observable { - return cold('a', {a: itemEndpoint}); + return cold('a', { a: itemEndpoint }); } } as HALEndpointService; @@ -132,7 +132,7 @@ describe('ItemDataService', () => { it('should return the endpoint to withdraw and reinstate items', () => { const result = service.getItemWithdrawEndpoint(scopeID); - const expected = cold('a', {a: ScopedItemEndpoint}); + const expected = cold('a', { a: ScopedItemEndpoint }); expect(result).toBeObservable(expected); }); @@ -154,7 +154,7 @@ describe('ItemDataService', () => { it('should return the endpoint to make an item private or public', () => { const result = service.getItemDiscoverableEndpoint(scopeID); - const expected = cold('a', {a: ScopedItemEndpoint}); + const expected = cold('a', { a: ScopedItemEndpoint }); expect(result).toBeObservable(expected); }); @@ -201,7 +201,7 @@ describe('ItemDataService', () => { const externalSourceEntry = Object.assign(new ExternalSourceEntry(), { display: 'John, Doe', value: 'John, Doe', - self: 'http://test-rest.com/server/api/integration/externalSources/orcidV2/entryValues/0000-0003-4851-8004' + _links: { self: { href: 'http://test-rest.com/server/api/integration/externalSources/orcidV2/entryValues/0000-0003-4851-8004' } } }); beforeEach(() => { diff --git a/src/app/core/data/item-data.service.ts b/src/app/core/data/item-data.service.ts index ce189b561d..b930ba2b19 100644 --- a/src/app/core/data/item-data.service.ts +++ b/src/app/core/data/item-data.service.ts @@ -2,7 +2,7 @@ import { HttpClient, HttpHeaders } from '@angular/common/http'; import { Injectable } from '@angular/core'; import { Store } from '@ngrx/store'; import { Observable } from 'rxjs'; -import { distinctUntilChanged, filter, find, map, switchMap } from 'rxjs/operators'; +import { distinctUntilChanged, filter, find, map, switchMap, tap } from 'rxjs/operators'; import { hasValue, isNotEmpty, isNotEmptyOperator } from '../../shared/empty.util'; import { NotificationsService } from '../../shared/notifications/notifications.service'; import { BrowseService } from '../browse/browse.service'; @@ -243,7 +243,7 @@ export class ItemDataService extends DataService { hrefObs.pipe( find((href: string) => hasValue(href)), map((href: string) => { - const request = new PutRequest(requestId, href, collection.self, options); + const request = new PutRequest(requestId, href, collection._links.self.href, options); this.requestService.configure(request); }) ).subscribe(); diff --git a/src/app/core/data/relationship.service.spec.ts b/src/app/core/data/relationship.service.spec.ts index be8bfe2b39..9dd9530fda 100644 --- a/src/app/core/data/relationship.service.spec.ts +++ b/src/app/core/data/relationship.service.spec.ts @@ -34,13 +34,17 @@ describe('RelationshipService', () => { }); const relationship1 = Object.assign(new Relationship(), { - self: relationshipsEndpointURL + '/2', + _links: { + self: { href: relationshipsEndpointURL + '/2' } + }, id: '2', uuid: '2', relationshipType: observableOf(new RemoteData(false, false, true, undefined, relationshipType)) }); const relationship2 = Object.assign(new Relationship(), { - self: relationshipsEndpointURL + '/3', + _links: { + self: { href: relationshipsEndpointURL + '/3' } + }, id: '3', uuid: '3', relationshipType: observableOf(new RemoteData(false, false, true, undefined, relationshipType)) @@ -49,24 +53,28 @@ describe('RelationshipService', () => { const relationships = [relationship1, relationship2]; const item = Object.assign(new Item(), { - self: restEndpointURL + '/publication', id: 'publication', uuid: 'publication', relationships: observableOf(new RemoteData(false, false, true, undefined, new PaginatedList(new PageInfo(), relationships))), _links: { - relationships: { href: restEndpointURL + '/publication/relationships' } + relationships: { href: restEndpointURL + '/publication/relationships' }, + self: { href: restEndpointURL + '/publication' } } }); const relatedItem1 = Object.assign(new Item(), { - self: 'fake-item-url/author1', id: 'author1', - uuid: 'author1' + uuid: 'author1', + _links: { + self: { href: restEndpointURL + '/author1' } + } }); const relatedItem2 = Object.assign(new Item(), { - self: 'fake-item-url/author2', id: 'author2', - uuid: 'author2' + uuid: 'author2', + _links: { + self: { href: restEndpointURL + '/author2' } + } }); relationship1.leftItem = getRemotedataObservable(relatedItem1); relationship1.rightItem = getRemotedataObservable(item); @@ -130,8 +138,8 @@ describe('RelationshipService', () => { }); it('should clear the cache of the related items', () => { - expect(objectCache.remove).toHaveBeenCalledWith(relatedItem1.self); - expect(objectCache.remove).toHaveBeenCalledWith(item.self); + expect(objectCache.remove).toHaveBeenCalledWith(relatedItem1._links.self.href); + expect(objectCache.remove).toHaveBeenCalledWith(item._links.self.href); expect(requestService.removeByHrefSubstring).toHaveBeenCalledWith(relatedItem1.self); expect(requestService.removeByHrefSubstring).toHaveBeenCalledWith(item.self); }); diff --git a/src/app/core/integration/integration-response-parsing.service.spec.ts b/src/app/core/integration/integration-response-parsing.service.spec.ts index 237045a0fa..8cc139744c 100644 --- a/src/app/core/integration/integration-response-parsing.service.spec.ts +++ b/src/app/core/integration/integration-response-parsing.service.spec.ts @@ -32,8 +32,16 @@ describe('IntegrationResponseParsingService', () => { let definitions; function initVars() { - pageInfo = Object.assign(new PageInfo(), { elementsPerPage: 5, totalElements: 5, totalPages: 1, currentPage: 1, self: 'https://rest.api/integration/authorities/type/entries'}); - definitions = new PaginatedList(pageInfo,[ + pageInfo = Object.assign(new PageInfo(), { + elementsPerPage: 5, + totalElements: 5, + totalPages: 1, + currentPage: 1, + _links: { + self: { href: 'https://rest.api/integration/authorities/type/entries' } + } + }); + definitions = new PaginatedList(pageInfo, [ Object.assign(new AuthorityValue(), { type: 'authority', display: 'One', diff --git a/src/app/core/registry/registry.service.spec.ts b/src/app/core/registry/registry.service.spec.ts index 03a7c132de..b466693649 100644 --- a/src/app/core/registry/registry.service.spec.ts +++ b/src/app/core/registry/registry.service.spec.ts @@ -1,30 +1,10 @@ -import { TestBed } from '@angular/core/testing'; -import { RegistryService } from './registry.service'; import { CommonModule } from '@angular/common'; -import { RequestService } from '../data/request.service'; -import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; -import { HALEndpointService } from '../shared/hal-endpoint.service'; -import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model'; -import { combineLatest as observableCombineLatest, Observable, of as observableOf } from 'rxjs'; -import { RequestEntry } from '../data/request.reducer'; -import { RemoteData } from '../data/remote-data'; -import { PageInfo } from '../shared/page-info.model'; -import { getMockRequestService } from '../../shared/mocks/mock-request.service'; - -import { - RegistryMetadatafieldsSuccessResponse, - RegistryMetadataschemasSuccessResponse, - RestResponse -} from '../cache/response.models'; import { Component } from '@angular/core'; -import { RegistryMetadataschemasResponse } from './registry-metadataschemas-response.model'; -import { RegistryMetadatafieldsResponse } from './registry-metadatafields-response.model'; -import { map } from 'rxjs/operators'; +import { TestBed } from '@angular/core/testing'; import { Store, StoreModule } from '@ngrx/store'; -import { MockStore } from '../../shared/testing/mock-store'; -import { NotificationsService } from '../../shared/notifications/notifications.service'; -import { NotificationsServiceStub } from '../../shared/testing/notifications-service-stub'; import { TranslateModule } from '@ngx-translate/core'; +import { combineLatest as observableCombineLatest, Observable, of as observableOf } from 'rxjs'; +import { map } from 'rxjs/operators'; import { MetadataRegistryCancelFieldAction, MetadataRegistryCancelSchemaAction, @@ -37,12 +17,31 @@ import { MetadataRegistrySelectFieldAction, MetadataRegistrySelectSchemaAction } from '../../+admin/admin-registries/metadata-registry/metadata-registry.actions'; -import { ResourceType } from '../shared/resource-type'; -import { MetadataSchema } from '../metadata/metadata-schema.model'; -import { MetadataField } from '../metadata/metadata-field.model'; +import { getMockRequestService } from '../../shared/mocks/mock-request.service'; +import { NotificationsService } from '../../shared/notifications/notifications.service'; +import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model'; +import { MockStore } from '../../shared/testing/mock-store'; +import { NotificationsServiceStub } from '../../shared/testing/notifications-service-stub'; import { createSuccessfulRemoteDataObject$ } from '../../shared/testing/utils'; +import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; -@Component({template: ''}) +import { + RegistryMetadatafieldsSuccessResponse, + RegistryMetadataschemasSuccessResponse, + RestResponse +} from '../cache/response.models'; +import { RemoteData } from '../data/remote-data'; +import { RequestEntry } from '../data/request.reducer'; +import { RequestService } from '../data/request.service'; +import { MetadataField } from '../metadata/metadata-field.model'; +import { MetadataSchema } from '../metadata/metadata-schema.model'; +import { HALEndpointService } from '../shared/hal-endpoint.service'; +import { PageInfo } from '../shared/page-info.model'; +import { RegistryMetadatafieldsResponse } from './registry-metadatafields-response.model'; +import { RegistryMetadataschemasResponse } from './registry-metadataschemas-response.model'; +import { RegistryService } from './registry.service'; + +@Component({ template: '' }) class DummyComponent { } @@ -57,15 +56,18 @@ describe('RegistryService', () => { const mockSchemasList = [ Object.assign(new MetadataSchema(), { id: 1, - self: 'https://dspace7.4science.it/dspace-spring-rest/api/core/metadataschemas/1', + _links: { + self: { href: 'https://dspace7.4science.it/dspace-spring-rest/api/core/metadataschemas/1' } + }, prefix: 'dc', namespace: 'http://dublincore.org/documents/dcmi-terms/', type: MetadataSchema.type -}), + }), Object.assign(new MetadataSchema(), { - id: 2, - self: 'https://dspace7.4science.it/dspace-spring-rest/api/core/metadataschemas/2', + _links: { + self: { href: 'https://dspace7.4science.it/dspace-spring-rest/api/core/metadataschemas/2' } + }, prefix: 'mock', namespace: 'http://dspace.org/mockschema', type: MetadataSchema.type @@ -73,45 +75,53 @@ describe('RegistryService', () => { ]; const mockFieldsList = [ Object.assign(new MetadataField(), - { - id: 1, - self: 'https://dspace7.4science.it/dspace-spring-rest/api/core/metadatafields/8', - element: 'contributor', - qualifier: 'advisor', - scopeNote: null, - schema: mockSchemasList[0], - type: MetadataField.type - }), + { + id: 1, + _links: { + self: { href: 'https://dspace7.4science.it/dspace-spring-rest/api/core/metadatafields/8' } + }, + element: 'contributor', + qualifier: 'advisor', + scopeNote: null, + schema: mockSchemasList[0], + type: MetadataField.type + }), Object.assign(new MetadataField(), { - id: 2, - self: 'https://dspace7.4science.it/dspace-spring-rest/api/core/metadatafields/9', - element: 'contributor', - qualifier: 'author', - scopeNote: null, - schema: mockSchemasList[0], - type: MetadataField.type - }), + id: 2, + _links: { + self: { href: 'https://dspace7.4science.it/dspace-spring-rest/api/core/metadatafields/9' } + }, + element: 'contributor', + qualifier: 'author', + scopeNote: null, + schema: mockSchemasList[0], + type: MetadataField.type + }), Object.assign(new MetadataField(), { - id: 3, - self: 'https://dspace7.4science.it/dspace-spring-rest/api/core/metadatafields/10', - element: 'contributor', - qualifier: 'editor', - scopeNote: 'test scope note', - schema: mockSchemasList[1], - type: MetadataField.type - }), + id: 3, + _links: { + self: { href: 'https://dspace7.4science.it/dspace-spring-rest/api/core/metadatafields/10' } + }, + element: 'contributor', + qualifier: 'editor', + scopeNote: 'test scope note', + schema: mockSchemasList[1], + type: MetadataField.type + }), Object.assign(new MetadataField(), { - id: 4, - self: 'https://dspace7.4science.it/dspace-spring-rest/api/core/metadatafields/11', - element: 'contributor', - qualifier: 'illustrator', - scopeNote: null, - schema: mockSchemasList[1], - type: MetadataField.type - }) + id: 4, + _links: { + self: { href: 'https://dspace7.4science.it/dspace-spring-rest/api/core/metadatafields/11' } + }, + element: 'contributor', + qualifier: 'illustrator', + scopeNote: null, + schema: mockSchemasList[1], + type: MetadataField.type + }) ]; const pageInfo = new PageInfo(); @@ -130,7 +140,7 @@ describe('RegistryService', () => { toRemoteDataObservable: (requestEntryObs: Observable, payloadObs: Observable) => { return observableCombineLatest(requestEntryObs, payloadObs).pipe(map(([req, pay]) => { - return {req, pay}; + return { req, pay }; }) ); }, @@ -146,11 +156,11 @@ describe('RegistryService', () => { DummyComponent ], providers: [ - {provide: RequestService, useValue: getMockRequestService()}, - {provide: RemoteDataBuildService, useValue: rdbStub}, - {provide: HALEndpointService, useValue: halServiceStub}, - {provide: Store, useClass: MockStore}, - {provide: NotificationsService, useValue: new NotificationsServiceStub()}, + { provide: RequestService, useValue: getMockRequestService() }, + { provide: RemoteDataBuildService, useValue: rdbStub }, + { provide: HALEndpointService, useValue: halServiceStub }, + { provide: Store, useClass: MockStore }, + { provide: NotificationsService, useValue: new NotificationsServiceStub() }, RegistryService ] }); @@ -165,7 +175,7 @@ describe('RegistryService', () => { page: pageInfo }); const response = new RegistryMetadataschemasSuccessResponse(queryResponse, 200, 'OK', pageInfo); - const responseEntry = Object.assign(new RequestEntry(), {response: response}); + const responseEntry = Object.assign(new RequestEntry(), { response: response }); beforeEach(() => { (registryService as any).requestService.getByHref.and.returnValue(observableOf(responseEntry)); @@ -194,7 +204,7 @@ describe('RegistryService', () => { page: pageInfo }); const response = new RegistryMetadataschemasSuccessResponse(queryResponse, 200, 'OK', pageInfo); - const responseEntry = Object.assign(new RequestEntry(), {response: response}); + const responseEntry = Object.assign(new RequestEntry(), { response: response }); beforeEach(() => { (registryService as any).requestService.getByHref.and.returnValue(observableOf(responseEntry)); @@ -223,7 +233,7 @@ describe('RegistryService', () => { page: pageInfo }); const response = new RegistryMetadatafieldsSuccessResponse(queryResponse, 200, 'OK', pageInfo); - const responseEntry = Object.assign(new RequestEntry(), {response: response}); + const responseEntry = Object.assign(new RequestEntry(), { response: response }); beforeEach(() => { (registryService as any).requestService.getByHref.and.returnValue(observableOf(responseEntry)); diff --git a/src/app/shared/comcol-forms/comcol-form/comcol-form.component.spec.ts b/src/app/shared/comcol-forms/comcol-form/comcol-form.component.spec.ts index 66534466f1..07fb64cbb0 100644 --- a/src/app/shared/comcol-forms/comcol-form/comcol-form.component.spec.ts +++ b/src/app/shared/comcol-forms/comcol-form/comcol-form.component.spec.ts @@ -1,27 +1,27 @@ -import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { TranslateModule } from '@ngx-translate/core'; import { Location } from '@angular/common'; -import { RouterTestingModule } from '@angular/router/testing'; import { NO_ERRORS_SCHEMA } from '@angular/core'; -import { DynamicFormControlModel, DynamicFormService, DynamicInputModel } from '@ng-dynamic-forms/core'; +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { FormControl, FormGroup } from '@angular/forms'; -import { Community } from '../../../core/shared/community.model'; -import { ComColFormComponent } from './comcol-form.component'; -import { DSpaceObject } from '../../../core/shared/dspace-object.model'; -import { hasValue } from '../../empty.util'; -import { VarDirective } from '../../utils/var.directive'; -import { NotificationsService } from '../../notifications/notifications.service'; -import { NotificationsServiceStub } from '../../testing/notifications-service-stub'; -import { AuthService } from '../../../core/auth/auth.service'; -import { AuthServiceMock } from '../../mocks/mock-auth.service'; +import { By } from '@angular/platform-browser'; +import { RouterTestingModule } from '@angular/router/testing'; +import { DynamicFormControlModel, DynamicFormService, DynamicInputModel } from '@ng-dynamic-forms/core'; +import { TranslateModule } from '@ngx-translate/core'; import { of as observableOf } from 'rxjs'; -import { RemoteData } from '../../../core/data/remote-data'; -import { RestRequestMethod } from '../../../core/data/rest-request-method'; +import { AuthService } from '../../../core/auth/auth.service'; +import { ObjectCacheService } from '../../../core/cache/object-cache.service'; import { ErrorResponse, RestResponse } from '../../../core/cache/response.models'; +import { RemoteData } from '../../../core/data/remote-data'; import { RequestError } from '../../../core/data/request.models'; import { RequestService } from '../../../core/data/request.service'; -import { ObjectCacheService } from '../../../core/cache/object-cache.service'; -import { By } from '@angular/platform-browser'; +import { RestRequestMethod } from '../../../core/data/rest-request-method'; +import { Community } from '../../../core/shared/community.model'; +import { DSpaceObject } from '../../../core/shared/dspace-object.model'; +import { hasValue } from '../../empty.util'; +import { AuthServiceMock } from '../../mocks/mock-auth.service'; +import { NotificationsService } from '../../notifications/notifications.service'; +import { NotificationsServiceStub } from '../../testing/notifications-service-stub'; +import { VarDirective } from '../../utils/var.directive'; +import { ComColFormComponent } from './comcol-form.component'; describe('ComColFormComponent', () => { let comp: ComColFormComponent; @@ -43,10 +43,10 @@ describe('ComColFormComponent', () => { const dcRandom = 'dc.random'; const dcAbstract = 'dc.description.abstract'; - const titleMD = { [dcTitle]: [ { value: 'Community Title', language: null } ] }; - const randomMD = { [dcRandom]: [ { value: 'Random metadata excluded from form', language: null } ] }; - const abstractMD = { [dcAbstract]: [ { value: 'Community description', language: null } ] }; - const newTitleMD = { [dcTitle]: [ { value: 'New Community Title', language: null } ] }; + const titleMD = { [dcTitle]: [{ value: 'Community Title', language: null }] }; + const randomMD = { [dcRandom]: [{ value: 'Random metadata excluded from form', language: null }] }; + const abstractMD = { [dcAbstract]: [{ value: 'Community description', language: null }] }; + const newTitleMD = { [dcTitle]: [{ value: 'New Community Title', language: null }] }; const formModel = [ new DynamicInputModel({ id: 'title', @@ -96,7 +96,9 @@ describe('ComColFormComponent', () => { describe('when the dso doesn\'t contain an ID (newly created)', () => { beforeEach(() => { - initComponent(new Community()); + initComponent(Object.assign(new Community(), { + _links: { self: { href: 'community-self' } } + })); }); it('should initialize the uploadFilesOptions with a placeholder url', () => { @@ -191,7 +193,8 @@ describe('ComColFormComponent', () => { beforeEach(() => { initComponent(Object.assign(new Community(), { id: 'community-id', - logo: observableOf(new RemoteData(false, false, true, null, undefined)) + logo: observableOf(new RemoteData(false, false, true, null, undefined)), + _links: { self: { href: 'community-self' } } })); }); @@ -208,7 +211,8 @@ describe('ComColFormComponent', () => { beforeEach(() => { initComponent(Object.assign(new Community(), { id: 'community-id', - logo: observableOf(new RemoteData(false, false, true, null, {})) + logo: observableOf(new RemoteData(false, false, true, null, {})), + _links: { self: { href: 'community-self' } } })); }); diff --git a/src/app/shared/comcol-forms/comcol-form/comcol-form.component.ts b/src/app/shared/comcol-forms/comcol-form/comcol-form.component.ts index 435ef61d72..4ed20b83e1 100644 --- a/src/app/shared/comcol-forms/comcol-form/comcol-form.component.ts +++ b/src/app/shared/comcol-forms/comcol-form/comcol-form.component.ts @@ -1,34 +1,30 @@ -import { Component, EventEmitter, Input, OnDestroy, OnInit, Output, ViewChild } from '@angular/core'; import { Location } from '@angular/common'; -import { - DynamicFormControlModel, - DynamicFormService, - DynamicInputModel -} from '@ng-dynamic-forms/core'; +import { Component, EventEmitter, Input, OnDestroy, OnInit, Output, ViewChild } from '@angular/core'; import { FormGroup } from '@angular/forms'; +import { DynamicFormControlModel, DynamicFormService, DynamicInputModel } from '@ng-dynamic-forms/core'; import { TranslateService } from '@ngx-translate/core'; +import { FileUploader } from 'ng2-file-upload'; +import { combineLatest as observableCombineLatest } from 'rxjs'; +import { BehaviorSubject } from 'rxjs/internal/BehaviorSubject'; +import { Subscription } from 'rxjs/internal/Subscription'; +import { AuthService } from '../../../core/auth/auth.service'; +import { ObjectCacheService } from '../../../core/cache/object-cache.service'; +import { ErrorResponse, RestResponse } from '../../../core/cache/response.models'; +import { ComColDataService } from '../../../core/data/comcol-data.service'; +import { RemoteData } from '../../../core/data/remote-data'; +import { RequestService } from '../../../core/data/request.service'; +import { RestRequestMethod } from '../../../core/data/rest-request-method'; +import { Bitstream } from '../../../core/shared/bitstream.model'; +import { Collection } from '../../../core/shared/collection.model'; +import { Community } from '../../../core/shared/community.model'; import { DSpaceObject } from '../../../core/shared/dspace-object.model'; import { MetadataMap, MetadataValue } from '../../../core/shared/metadata.models'; import { ResourceType } from '../../../core/shared/resource-type'; import { hasValue, isNotEmpty } from '../../empty.util'; -import { UploaderOptions } from '../../uploader/uploader-options.model'; import { NotificationsService } from '../../notifications/notifications.service'; -import { ComColDataService } from '../../../core/data/comcol-data.service'; -import { Subscription } from 'rxjs/internal/Subscription'; -import { AuthService } from '../../../core/auth/auth.service'; -import { Community } from '../../../core/shared/community.model'; -import { Collection } from '../../../core/shared/collection.model'; +import { UploaderOptions } from '../../uploader/uploader-options.model'; import { UploaderComponent } from '../../uploader/uploader.component'; -import { FileUploader } from 'ng2-file-upload'; -import { ErrorResponse, RestResponse } from '../../../core/cache/response.models'; -import { BehaviorSubject } from 'rxjs/internal/BehaviorSubject'; -import { RemoteData } from '../../../core/data/remote-data'; -import { Bitstream } from '../../../core/shared/bitstream.model'; -import { combineLatest as observableCombineLatest } from 'rxjs'; -import { RestRequestMethod } from '../../../core/data/rest-request-method'; -import { RequestService } from '../../../core/data/request.service'; -import { ObjectCacheService } from '../../../core/cache/object-cache.service'; /** * A form for creating and editing Communities or Collections @@ -253,8 +249,8 @@ export class ComColFormComponent implements OnInit, OnDe * Refresh the object's cache to ensure the latest version */ private refreshCache() { - this.requestService.removeByHrefSubstring(this.dso.self); - this.objectCache.remove(this.dso.self); + this.requestService.removeByHrefSubstring(this.dso._links.self.href); + this.objectCache.remove(this.dso._links.self.href); } /** diff --git a/src/app/shared/comcol-forms/create-comcol-page/create-comcol-page.component.ts b/src/app/shared/comcol-forms/create-comcol-page/create-comcol-page.component.ts index 7b23c59498..e9373aff47 100644 --- a/src/app/shared/comcol-forms/create-comcol-page/create-comcol-page.component.ts +++ b/src/app/shared/comcol-forms/create-comcol-page/create-comcol-page.component.ts @@ -1,19 +1,18 @@ import { Component, OnInit } from '@angular/core'; -import { Community } from '../../../core/shared/community.model'; -import { CommunityDataService } from '../../../core/data/community-data.service'; -import { Observable } from 'rxjs'; -import { RouteService } from '../../../core/services/route.service'; -import { ActivatedRoute, Router } from '@angular/router'; -import { RemoteData } from '../../../core/data/remote-data'; -import { hasValue, isNotEmpty, isNotUndefined } from '../../empty.util'; -import { take } from 'rxjs/operators'; -import { getSucceededRemoteData } from '../../../core/shared/operators'; -import { DSpaceObject } from '../../../core/shared/dspace-object.model'; -import { DataService } from '../../../core/data/data.service'; -import { ComColDataService } from '../../../core/data/comcol-data.service'; -import { NotificationsService } from '../../notifications/notifications.service'; +import { Router } from '@angular/router'; import { TranslateService } from '@ngx-translate/core'; +import { Observable } from 'rxjs'; +import { take } from 'rxjs/operators'; +import { ComColDataService } from '../../../core/data/comcol-data.service'; +import { CommunityDataService } from '../../../core/data/community-data.service'; +import { RemoteData } from '../../../core/data/remote-data'; +import { RouteService } from '../../../core/services/route.service'; +import { Community } from '../../../core/shared/community.model'; +import { DSpaceObject } from '../../../core/shared/dspace-object.model'; +import { getSucceededRemoteData } from '../../../core/shared/operators'; import { ResourceType } from '../../../core/shared/resource-type'; +import { hasValue, isNotEmpty, isNotUndefined } from '../../empty.util'; +import { NotificationsService } from '../../notifications/notifications.service'; /** * Component representing the create page for communities and collections diff --git a/src/app/shared/mocks/mock-link-service.ts b/src/app/shared/mocks/mock-link-service.ts new file mode 100644 index 0000000000..d50640a629 --- /dev/null +++ b/src/app/shared/mocks/mock-link-service.ts @@ -0,0 +1,9 @@ +import { LinkService } from '../../core/cache/builders/link.service'; + +export function getMockLinkService(): LinkService { + return jasmine.createSpyObj('linkService', { + resolveLinks: jasmine.createSpy('resolveLinks'), + resolveLink: jasmine.createSpy('resolveLink'), + removeResolvedLinks: jasmine.createSpy('removeResolvedLinks') + }); +} diff --git a/src/app/shared/object-list/my-dspace-result-list-element/workflow-item-search-result/workflow-item-search-result-list-element.component.spec.ts b/src/app/shared/object-list/my-dspace-result-list-element/workflow-item-search-result/workflow-item-search-result-list-element.component.spec.ts index f5521001ff..5aae862ed0 100644 --- a/src/app/shared/object-list/my-dspace-result-list-element/workflow-item-search-result/workflow-item-search-result-list-element.component.spec.ts +++ b/src/app/shared/object-list/my-dspace-result-list-element/workflow-item-search-result/workflow-item-search-result-list-element.component.spec.ts @@ -1,16 +1,19 @@ import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; +import { cold } from 'jasmine-marbles'; import { of as observableOf } from 'rxjs'; +import { LinkService } from '../../../../core/cache/builders/link.service'; +import { ItemDataService } from '../../../../core/data/item-data.service'; import { Item } from '../../../../core/shared/item.model'; import { WorkflowItem } from '../../../../core/submission/models/workflowitem.model'; import { MyDspaceItemStatusType } from '../../../object-collection/shared/mydspace-item-status/my-dspace-item-status-type'; -import { createSuccessfulRemoteDataObject } from '../../../testing/utils'; -import { WorkflowItemSearchResultListElementComponent } from './workflow-item-search-result-list-element.component'; import { WorkflowItemSearchResult } from '../../../object-collection/shared/workflow-item-search-result.model'; +import { createSuccessfulRemoteDataObject } from '../../../testing/utils'; import { TruncatableService } from '../../../truncatable/truncatable.service'; +import { WorkflowItemSearchResultListElementComponent } from './workflow-item-search-result-list-element.component'; let component: WorkflowItemSearchResultListElementComponent; let fixture: ComponentFixture; @@ -52,13 +55,22 @@ const item = Object.assign(new Item(), { const rd = createSuccessfulRemoteDataObject(item); mockResultObject.indexableObject = Object.assign(new WorkflowItem(), { item: observableOf(rd) }); +let linkService; + describe('WorkflowItemSearchResultListElementComponent', () => { beforeEach(async(() => { + linkService = { + resolveLink() { + // mock + }, + }; TestBed.configureTestingModule({ imports: [NoopAnimationsModule], declarations: [WorkflowItemSearchResultListElementComponent], providers: [ { provide: TruncatableService, useValue: {} }, + { provide: ItemDataService, useValue: {} }, + { provide: LinkService, useValue: linkService }, ], schemas: [NO_ERRORS_SCHEMA] }).overrideComponent(WorkflowItemSearchResultListElementComponent, { @@ -77,7 +89,7 @@ describe('WorkflowItemSearchResultListElementComponent', () => { }); it('should init item properly', () => { - expect(component.item).toEqual(item); + expect(component.item$).toBeObservable(cold('a',{a: item})); }); it('should have properly status', () => { diff --git a/src/app/shared/object-list/my-dspace-result-list-element/workspace-item-search-result/workspace-item-search-result-list-element.component.spec.ts b/src/app/shared/object-list/my-dspace-result-list-element/workspace-item-search-result/workspace-item-search-result-list-element.component.spec.ts index faf4a3b1be..95dc3745de 100644 --- a/src/app/shared/object-list/my-dspace-result-list-element/workspace-item-search-result/workspace-item-search-result-list-element.component.spec.ts +++ b/src/app/shared/object-list/my-dspace-result-list-element/workspace-item-search-result/workspace-item-search-result-list-element.component.spec.ts @@ -3,14 +3,17 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { of as observableOf } from 'rxjs'; +import { LinkService } from '../../../../core/cache/builders/link.service'; +import { ItemDataService } from '../../../../core/data/item-data.service'; import { Item } from '../../../../core/shared/item.model'; -import { WorkspaceItemSearchResultListElementComponent } from './workspace-item-search-result-list-element.component'; import { WorkspaceItem } from '../../../../core/submission/models/workspaceitem.model'; +import { getMockLinkService } from '../../../mocks/mock-link-service'; import { MyDspaceItemStatusType } from '../../../object-collection/shared/mydspace-item-status/my-dspace-item-status-type'; -import { createSuccessfulRemoteDataObject } from '../../../testing/utils'; import { WorkflowItemSearchResult } from '../../../object-collection/shared/workflow-item-search-result.model'; +import { createSuccessfulRemoteDataObject } from '../../../testing/utils'; import { TruncatableService } from '../../../truncatable/truncatable.service'; +import { WorkspaceItemSearchResultListElementComponent } from './workspace-item-search-result-list-element.component'; let component: WorkspaceItemSearchResultListElementComponent; let fixture: ComponentFixture; @@ -51,14 +54,18 @@ const item = Object.assign(new Item(), { }); const rd = createSuccessfulRemoteDataObject(item); mockResultObject.indexableObject = Object.assign(new WorkspaceItem(), { item: observableOf(rd) }); +let linkService; describe('WorkspaceItemSearchResultListElementComponent', () => { beforeEach(async(() => { + linkService = getMockLinkService; TestBed.configureTestingModule({ imports: [NoopAnimationsModule], declarations: [WorkspaceItemSearchResultListElementComponent], providers: [ { provide: TruncatableService, useValue: {} }, + { provide: ItemDataService, useValue: {} }, + { provide: LinkService, useValue: linkService }, ], schemas: [NO_ERRORS_SCHEMA] }).overrideComponent(WorkspaceItemSearchResultListElementComponent, { @@ -77,10 +84,12 @@ describe('WorkspaceItemSearchResultListElementComponent', () => { }); it('should init item properly', () => { - expect(component.item).toEqual(item); + expect(linkService.resolveLink).toHaveBeenCalled(); + expect(component.item$).toEqual(observableOf(item)); }); it('should have properly status', () => { + expect(linkService.resolveLink).toHaveBeenCalled(); expect(component.status).toEqual(MyDspaceItemStatusType.WORKSPACE); }); }); From bc7c92f44c5bab1c2ab2a8edf71a12e0a0cd5a28 Mon Sep 17 00:00:00 2001 From: Art Lowel Date: Fri, 14 Feb 2020 18:06:17 +0100 Subject: [PATCH 23/38] removed remaining normalized models and related services --- .../publication/publication.component.spec.ts | 2 - .../item-types/shared/item.component.spec.ts | 2 - .../auth/auth-response-parsing.service.ts | 3 +- .../core/cache/builders/build-decorators.ts | 73 +------ src/app/core/cache/builders/link.service.ts | 6 +- .../normalized-object-build.service.ts | 48 ----- .../builders/remote-data-build.service.ts | 85 +------- .../models/normalized-dspace-object.model.ts | 73 ------- .../cache/models/normalized-object.model.ts | 26 --- src/app/core/cache/object-cache.service.ts | 31 ++- .../config-response-parsing.service.spec.ts | 14 +- .../config-submission-definitions.model.ts | 2 + .../models/config-submission-forms.model.ts | 2 + .../config-submission-sections.model.ts | 2 + .../models/config-submission-uploads.model.ts | 5 + ...ized-config-submission-definition.model.ts | 25 --- ...zed-config-submission-definitions.model.ts | 11 - ...normalized-config-submission-form.model.ts | 16 -- ...ormalized-config-submission-forms.model.ts | 9 - ...malized-config-submission-section.model.ts | 38 ---- ...alized-config-submission-sections.model.ts | 10 - ...malized-config-submission-uploads.model.ts | 30 --- .../config/models/normalized-config.model.ts | 42 ---- src/app/core/core.module.ts | 2 - .../data/base-response-parsing.service.ts | 28 ++- src/app/core/data/bitstream-data.service.ts | 2 - .../bitstream-format-data.service.spec.ts | 3 - .../data/bitstream-format-data.service.ts | 2 - .../browse-items-response-parsing-service.ts | 4 +- src/app/core/data/bundle-data.service.ts | 3 - src/app/core/data/collection-data.service.ts | 2 - src/app/core/data/comcol-data.service.spec.ts | 11 - src/app/core/data/community-data.service.ts | 2 - src/app/core/data/data.service.spec.ts | 43 ++-- src/app/core/data/data.service.ts | 8 +- .../data/default-change-analyzer.service.ts | 11 +- .../core/data/dso-change-analyzer.service.ts | 1 - .../data/dso-redirect-data.service.spec.ts | 3 - .../core/data/dso-redirect-data.service.ts | 33 ++- .../core/data/dso-response-parsing.service.ts | 3 +- .../data/dspace-object-data.service.spec.ts | 4 - .../core/data/dspace-object-data.service.ts | 5 +- src/app/core/data/entity-type-data.service.ts | 5 +- src/app/core/data/external-source.service.ts | 2 - src/app/core/data/item-data.service.spec.ts | 3 - src/app/core/data/item-data.service.ts | 2 - src/app/core/data/license-data.service.ts | 5 +- .../core/data/metadata-schema-data.service.ts | 5 +- .../data/mydspace-response-parsing.service.ts | 4 +- .../core/data/relationship-type.service.ts | 2 - src/app/core/data/relationship.service.ts | 2 - src/app/core/data/request.effects.ts | 4 +- .../core/data/resource-policy.service.spec.ts | 4 - src/app/core/data/resource-policy.service.ts | 5 +- src/app/core/data/site-data.service.spec.ts | 3 - src/app/core/data/site-data.service.ts | 2 - .../dspace-rest-v2/dspace.serializer.spec.ts | 154 ++++++++++++++ .../normalized-object.serializer.spec.ts | 194 ------------------ .../normalized-object.serializer.ts | 95 --------- src/app/core/eperson/eperson-data.service.ts | 2 - src/app/core/eperson/group-data.service.ts | 3 - .../integration/models/authority.value.ts | 3 + .../core/metadata/metadata.service.spec.ts | 2 - ...egistry-bitstreamformats-response.model.ts | 22 +- .../registry-metadatafields-response.model.ts | 5 +- ...registry-metadataschemas-response.model.ts | 2 - src/app/core/registry/registry.service.ts | 4 +- src/app/core/shared/browse-entry.model.ts | 1 - .../shared/external-source-entry.model.ts | 3 + src/app/core/shared/external-source.model.ts | 3 + .../item-relationships/item-type.model.ts | 3 + src/app/core/shared/resource-policy.model.ts | 3 + .../normalized-submission-object.model.ts | 43 ---- .../models/normalized-workflowitem.model.ts | 45 ---- .../models/normalized-workspaceitem.model.ts | 46 ----- .../submission-response-parsing.service.ts | 33 ++- .../submission/workflowitem-data.service.ts | 2 - .../submission/workspaceitem-data.service.ts | 2 - .../tasks/claimed-task-data.service.spec.ts | 5 - .../core/tasks/claimed-task-data.service.ts | 5 +- .../tasks/models/claimed-task-object.model.ts | 3 + .../normalized-claimed-task-object.model.ts | 53 ----- .../normalized-pool-task-object.model.ts | 44 ---- .../models/normalized-task-object.model.ts | 54 ----- .../tasks/models/pool-task-object.model.ts | 2 + .../core/tasks/models/task-object.model.ts | 23 ++- .../core/tasks/pool-task-data.service.spec.ts | 5 - src/app/core/tasks/pool-task-data.service.ts | 5 +- src/app/core/tasks/tasks.service.spec.ts | 14 +- .../journal/journal.component.spec.ts | 2 - ...-list-submission-element.component.spec.ts | 2 - ...-list-submission-element.component.spec.ts | 2 - .../mocks/mock-remote-data-build.service.ts | 5 +- .../item-detail-preview.component.spec.ts | 2 - ...arch-result-grid-element.component.spec.ts | 2 - ...arch-result-grid-element.component.spec.ts | 2 - ...arch-result-grid-element.component.spec.ts | 2 - src/app/shared/search/facet-value.model.ts | 15 +- .../search-authority-filter.component.ts | 2 +- .../search-facet-option.component.ts | 2 +- .../search-facet-selected-option.component.ts | 2 +- .../search-facet-filter.component.ts | 2 +- .../search-range-filter.component.spec.ts | 27 ++- src/app/thumbnail/thumbnail.component.ts | 15 +- 104 files changed, 397 insertions(+), 1343 deletions(-) delete mode 100644 src/app/core/cache/builders/normalized-object-build.service.ts delete mode 100644 src/app/core/cache/models/normalized-dspace-object.model.ts delete mode 100644 src/app/core/cache/models/normalized-object.model.ts delete mode 100644 src/app/core/config/models/normalized-config-submission-definition.model.ts delete mode 100644 src/app/core/config/models/normalized-config-submission-definitions.model.ts delete mode 100644 src/app/core/config/models/normalized-config-submission-form.model.ts delete mode 100644 src/app/core/config/models/normalized-config-submission-forms.model.ts delete mode 100644 src/app/core/config/models/normalized-config-submission-section.model.ts delete mode 100644 src/app/core/config/models/normalized-config-submission-sections.model.ts delete mode 100644 src/app/core/config/models/normalized-config-submission-uploads.model.ts delete mode 100644 src/app/core/config/models/normalized-config.model.ts create mode 100644 src/app/core/dspace-rest-v2/dspace.serializer.spec.ts delete mode 100644 src/app/core/dspace-rest-v2/normalized-object.serializer.spec.ts delete mode 100644 src/app/core/dspace-rest-v2/normalized-object.serializer.ts delete mode 100644 src/app/core/submission/models/normalized-submission-object.model.ts delete mode 100644 src/app/core/submission/models/normalized-workflowitem.model.ts delete mode 100644 src/app/core/submission/models/normalized-workspaceitem.model.ts delete mode 100644 src/app/core/tasks/models/normalized-claimed-task-object.model.ts delete mode 100644 src/app/core/tasks/models/normalized-pool-task-object.model.ts delete mode 100644 src/app/core/tasks/models/normalized-task-object.model.ts diff --git a/src/app/+item-page/simple/item-types/publication/publication.component.spec.ts b/src/app/+item-page/simple/item-types/publication/publication.component.spec.ts index 16025bc2ea..c1aef2739f 100644 --- a/src/app/+item-page/simple/item-types/publication/publication.component.spec.ts +++ b/src/app/+item-page/simple/item-types/publication/publication.component.spec.ts @@ -5,7 +5,6 @@ import { By } from '@angular/platform-browser'; import { Store } from '@ngrx/store'; import { TranslateLoader, TranslateModule } from '@ngx-translate/core'; import { Observable } from 'rxjs/internal/Observable'; -import { NormalizedObjectBuildService } from '../../../../core/cache/builders/normalized-object-build.service'; import { RemoteDataBuildService } from '../../../../core/cache/builders/remote-data-build.service'; import { ObjectCacheService } from '../../../../core/cache/object-cache.service'; import { BitstreamDataService } from '../../../../core/data/bitstream-data.service'; @@ -63,7 +62,6 @@ describe('PublicationComponent', () => { { provide: UUIDService, useValue: {} }, { provide: Store, useValue: {} }, { provide: RemoteDataBuildService, useValue: {} }, - { provide: NormalizedObjectBuildService, useValue: {} }, { provide: CommunityDataService, useValue: {} }, { provide: HALEndpointService, useValue: {} }, { provide: NotificationsService, useValue: {} }, diff --git a/src/app/+item-page/simple/item-types/shared/item.component.spec.ts b/src/app/+item-page/simple/item-types/shared/item.component.spec.ts index ef22348b9c..24a2f028a5 100644 --- a/src/app/+item-page/simple/item-types/shared/item.component.spec.ts +++ b/src/app/+item-page/simple/item-types/shared/item.component.spec.ts @@ -5,7 +5,6 @@ import { By } from '@angular/platform-browser'; import { Store } from '@ngrx/store'; import { TranslateLoader, TranslateModule } from '@ngx-translate/core'; import { Observable } from 'rxjs/internal/Observable'; -import { NormalizedObjectBuildService } from '../../../../core/cache/builders/normalized-object-build.service'; import { RemoteDataBuildService } from '../../../../core/cache/builders/remote-data-build.service'; import { ObjectCacheService } from '../../../../core/cache/object-cache.service'; import { BitstreamDataService } from '../../../../core/data/bitstream-data.service'; @@ -67,7 +66,6 @@ export function getItemPageFieldsTest(mockItem: Item, component) { { provide: UUIDService, useValue: {} }, { provide: Store, useValue: {} }, { provide: RemoteDataBuildService, useValue: {} }, - { provide: NormalizedObjectBuildService, useValue: {} }, { provide: CommunityDataService, useValue: {} }, { provide: HALEndpointService, useValue: {} }, { provide: HttpClient, useValue: {} }, diff --git a/src/app/core/auth/auth-response-parsing.service.ts b/src/app/core/auth/auth-response-parsing.service.ts index 79572fb0d8..9ef523ca14 100644 --- a/src/app/core/auth/auth-response-parsing.service.ts +++ b/src/app/core/auth/auth-response-parsing.service.ts @@ -10,7 +10,6 @@ import { ObjectCacheService } from '../cache/object-cache.service'; import { ResponseParsingService } from '../data/parsing.service'; import { RestRequest } from '../data/request.models'; import { AuthStatus } from './models/auth-status.model'; -import { NormalizedObject } from '../cache/models/normalized-object.model'; @Injectable() export class AuthResponseParsingService extends BaseResponseParsingService implements ResponseParsingService { @@ -24,7 +23,7 @@ export class AuthResponseParsingService extends BaseResponseParsingService imple parse(request: RestRequest, data: DSpaceRESTV2Response): RestResponse { if (isNotEmpty(data.payload) && isNotEmpty(data.payload._links) && (data.statusCode === 200)) { - const response = this.process>(data.payload, request); + const response = this.process(data.payload, request); return new AuthStatusResponse(response, data.statusCode, data.statusText); } else { return new AuthStatusResponse(data.payload as AuthStatus, data.statusCode, data.statusText); diff --git a/src/app/core/cache/builders/build-decorators.ts b/src/app/core/cache/builders/build-decorators.ts index f02beed8a7..17bbc4a8b4 100644 --- a/src/app/core/cache/builders/build-decorators.ts +++ b/src/app/core/cache/builders/build-decorators.ts @@ -8,101 +8,34 @@ import { HALResource } from '../../shared/hal-resource.model'; import { CacheableObject, TypedObject } from '../object-cache.reducer'; import { ResourceType } from '../../shared/resource-type'; -const mapsToMetadataKey = Symbol('mapsTo'); -const relationshipKey = Symbol('relationship'); const resolvedLinkKey = Symbol('resolvedLink'); -const relationshipMap = new Map(); const resolvedLinkMap = new Map(); const typeMap = new Map(); const dataServiceMap = new Map(); const linkMap = new Map(); /** - * Decorator function to map a normalized class to it's not-normalized counter part class - * It will also maps a type to the matching class - * @param value The not-normalized class to map to + * Decorator function to map a ResourceType to its class + * @param value The ResourceType to map */ -export function mapsTo(value: GenericConstructor) { - return function decorator(objectConstructor: GenericConstructor) { - Reflect.defineMetadata(mapsToMetadataKey, value, objectConstructor); - mapsToType((value as any).type, objectConstructor); - } -} - -/** - * Decorator function to map a normalized class to it's not-normalized counter part class - * It will also maps a type to the matching class - * @param value The not-normalized class to map to - */ -// export function resourceType(target: any, key: string) { -// typeMap.set(target.key.value, target.constructor); -// } - export function resourceType(value: ResourceType) { return function decorator(objectConstructor: GenericConstructor) { typeMap.set(value.value, objectConstructor); } } -/** - * Maps a type to the matching class - * @param value The resourse type - * @param objectConstructor The class to map to - */ -function mapsToType(value: ResourceType, objectConstructor: GenericConstructor) { - if (!objectConstructor || !value) { - return; - } - typeMap.set(value.value, objectConstructor); -} - -/** - * Returns the mapped class for the given normalized class - * @param target The normalized class - */ -export function getMapsTo(target: any) { - return Reflect.getOwnMetadata(mapsToMetadataKey, target); -} - /** * Returns the mapped class for the given type * @param type The resource type */ -export function getMapsToType(type: string | ResourceType) { +export function getClassForType(type: string | ResourceType) { if (typeof(type) === 'object') { type = (type as ResourceType).value; } return typeMap.get(type); } -export function relationship(value: GenericConstructor, isList: boolean = false, shouldAutoResolve: boolean = true): any { - return function r(target: any, propertyKey: string, descriptor: PropertyDescriptor) { - if (!target || !propertyKey) { - return; - } - - const metaDataList: string[] = relationshipMap.get(target.constructor) || []; - if (metaDataList.indexOf(propertyKey) === -1) { - metaDataList.push(propertyKey); - } - relationshipMap.set(target.constructor, metaDataList); - return Reflect.metadata(relationshipKey, { - resourceType: (value as any).type.value, - isList, - shouldAutoResolve - }).apply(this, arguments); - }; -} - -export function getRelationMetadata(target: any, propertyKey: string) { - return Reflect.getMetadata(relationshipKey, target, propertyKey); -} - -export function getRelationships(target: any) { - return relationshipMap.get(target); -} - export function dataService(resourceType: ResourceType): any { return (target: any) => { if (hasNoValue(resourceType)) { diff --git a/src/app/core/cache/builders/link.service.ts b/src/app/core/cache/builders/link.service.ts index 90440c0c83..1b044ebee9 100644 --- a/src/app/core/cache/builders/link.service.ts +++ b/src/app/core/cache/builders/link.service.ts @@ -55,13 +55,15 @@ export class LinkService { /** * Remove any resolved links that the model may have. */ - public removeResolvedLinks(model: T) { + public removeResolvedLinks(model: T): T { + const result = Object.assign(new (model.constructor as GenericConstructor)(), model); const linkDefs = getLinkDefinitions(model.constructor as GenericConstructor); if (isNotEmpty(linkDefs)) { linkDefs.forEach((linkDef: LinkDefinition) => { - model[linkDef.propertyName] = undefined; + result[linkDef.propertyName] = undefined; }); } + return result; } } diff --git a/src/app/core/cache/builders/normalized-object-build.service.ts b/src/app/core/cache/builders/normalized-object-build.service.ts deleted file mode 100644 index 69d7454d2d..0000000000 --- a/src/app/core/cache/builders/normalized-object-build.service.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { Injectable } from '@angular/core'; -import { NormalizedObject } from '../models/normalized-object.model'; -import { getMapsToType, getRelationships } from './build-decorators'; -import { hasValue, isNotEmpty } from '../../../shared/empty.util'; -import { CacheableObject, TypedObject } from '../object-cache.reducer'; - -/** - * Return true if halObj has a value for `_links.self` - * - * @param {any} halObj The object to test - */ -export function isRestDataObject(halObj: any): boolean { - return isNotEmpty(halObj._links) && hasValue(halObj._links.self); -} - -/** - * Return true if halObj has a value for `page` and `_embedded` - * - * @param {any} halObj The object to test - */ -export function isRestPaginatedList(halObj: any): boolean { - return hasValue(halObj.page) && hasValue(halObj._embedded); -} - -/** - * A service to turn domain models in to their normalized - * counterparts. - */ -@Injectable() -export class NormalizedObjectBuildService { - - /** - * Returns the normalized model that corresponds to the given domain model - * - * @param {TDomain} domainModel a domain model - */ - normalize(domainModel: T): NormalizedObject { - const normalizedConstructor = getMapsToType((domainModel as any).type); - const relationships = getRelationships(normalizedConstructor) || []; - const normalizedModel = Object.assign({}, domainModel) as any; - relationships.forEach((key: string) => { - if (hasValue(normalizedModel[key])) { - normalizedModel[key] = normalizedModel._links[key]; - } - }); - return normalizedModel; - } -} diff --git a/src/app/core/cache/builders/remote-data-build.service.ts b/src/app/core/cache/builders/remote-data-build.service.ts index 582fac532f..a35998375c 100644 --- a/src/app/core/cache/builders/remote-data-build.service.ts +++ b/src/app/core/cache/builders/remote-data-build.service.ts @@ -24,11 +24,9 @@ import { getResourceLinksFromResponse } from '../../shared/operators'; import { PageInfo } from '../../shared/page-info.model'; -import { NormalizedObject } from '../models/normalized-object.model'; import { CacheableObject } from '../object-cache.reducer'; import { ObjectCacheService } from '../object-cache.service'; import { DSOSuccessResponse, ErrorResponse } from '../response.models'; -import { getMapsTo, getRelationMetadata, getRelationships } from './build-decorators'; import { LinkService } from './link.service'; @Injectable() @@ -84,8 +82,8 @@ export class RemoteDataBuildService { } }), hasValueOperator(), - map((normalized: NormalizedObject) => { - return this.build(normalized, ...linksToFollow); + map((obj: T) => { + return this.build(obj, ...linksToFollow); }), startWith(undefined), distinctUntilChanged() @@ -138,9 +136,9 @@ export class RemoteDataBuildService { getResourceLinksFromResponse(), switchMap((resourceUUIDs: string[]) => { return this.objectCache.getList(resourceUUIDs).pipe( - map((normList: Array>) => { - return normList.map((normalized: NormalizedObject) => { - return this.build(normalized, ...linksToFollow); + map((objs: Array) => { + return objs.map((obj: T) => { + return this.build(obj, ...linksToFollow); }); })); }), @@ -170,76 +168,9 @@ export class RemoteDataBuildService { return this.toRemoteDataObservable(requestEntry$, payload$); } - build(normalized: NormalizedObject, ...linksToFollow: Array>): T { - const halLinks: any = {}; - const relationships = getRelationships(normalized.constructor) || []; - - relationships.forEach((relationship: string) => { - let result; - if (hasValue(normalized[relationship])) { - const { resourceType, isList, shouldAutoResolve } = getRelationMetadata(normalized, relationship); - const objectList = normalized[relationship].page || normalized[relationship]; - if (shouldAutoResolve) { - if (typeof objectList !== 'string') { - objectList.forEach((href: string) => { - const request = new GetRequest(this.requestService.generateRequestId(), href); - if (!this.requestService.isCachedOrPending(request)) { - this.requestService.configure(request) - } - }); - - const rdArr = []; - objectList.forEach((href: string) => { - rdArr.push(this.buildSingle(href)); - }); - - if (isList) { - result = this.aggregate(rdArr); - } else if (rdArr.length === 1) { - result = rdArr[0]; - } - } else { - const request = new GetRequest(this.requestService.generateRequestId(), objectList); - if (!this.requestService.isCachedOrPending(request)) { - this.requestService.configure(request) - } - - // The rest API can return a single URL to represent a list of resources (e.g. /items/:id/bitstreams) - // in that case only 1 href will be stored in the normalized obj (so the isArray above fails), - // but it should still be built as a list - if (isList) { - result = this.buildList(objectList); - } else { - result = this.buildSingle(objectList); - } - } - - if (hasValue(normalized[relationship].page)) { - halLinks[relationship] = this.toPaginatedList(result, normalized[relationship].pageInfo); - } else { - halLinks[relationship] = result; - } - } else { - if (hasNoValue(halLinks._links)) { - halLinks._links = {}; - } - halLinks._links[relationship] = { - href: objectList - }; - } - } - }); - let domainModel; - const domainModelConstructor = getMapsTo(normalized.constructor); - if(hasValue(domainModelConstructor) && domainModelConstructor !== normalized.constructor) { - domainModel = Object.assign(new domainModelConstructor(), normalized, halLinks); - } else { - domainModel = normalized; - } - - this.linkService.resolveLinks(domainModel, ...linksToFollow); - - return domainModel; + build(model: T, ...linksToFollow: Array>): T { + this.linkService.resolveLinks(model, ...linksToFollow); + return model; } aggregate(input: Array>>): Observable> { diff --git a/src/app/core/cache/models/normalized-dspace-object.model.ts b/src/app/core/cache/models/normalized-dspace-object.model.ts deleted file mode 100644 index 2282947bfc..0000000000 --- a/src/app/core/cache/models/normalized-dspace-object.model.ts +++ /dev/null @@ -1,73 +0,0 @@ -import { autoserializeAs, deserializeAs, autoserialize } from 'cerialize'; -import { DSpaceObject } from '../../shared/dspace-object.model'; -import { HALLink } from '../../shared/hal-link.model'; -import { MetadataMap, MetadataMapSerializer } from '../../shared/metadata.models'; -import { ResourceType } from '../../shared/resource-type'; -import { NormalizedObject } from './normalized-object.model'; -import { TypedObject } from '../object-cache.reducer'; - -/** - * An model class for a DSpaceObject. - */ -export class NormalizedDSpaceObject extends NormalizedObject implements TypedObject { - - /** - * The link to the rest endpoint where this object can be found - * - * Repeated here to make the serialization work, - * inheritSerialization doesn't seem to work for more than one level - */ - @deserializeAs(String) - self: string; - - /** - * The human-readable identifier of this DSpaceObject - * - * Currently mapped to uuid but left in to leave room - * for a shorter, more user friendly type of id - */ - @autoserializeAs(String, 'uuid') - id: string; - - /** - * The universally unique identifier of this DSpaceObject - */ - @autoserializeAs(String) - uuid: string; - - /** - * The type of the object - */ - @autoserialize - type: ResourceType; - - /** - * All metadata of this DSpaceObject - */ - @autoserializeAs(MetadataMapSerializer) - metadata: MetadataMap; - - /** - * An array of DSpaceObjects that are direct parents of this DSpaceObject - */ - @deserializeAs(String) - parents: string[]; - - /** - * The DSpaceObject that owns this DSpaceObject - */ - @deserializeAs(String) - owner: string; - - /** - * The links to all related resources returned by the rest api. - * - * Repeated here to make the serialization work, - * inheritSerialization doesn't seem to work for more than one level - */ - @deserializeAs(Object) - _links: { - self: HALLink, - [name: string]: HALLink - } -} diff --git a/src/app/core/cache/models/normalized-object.model.ts b/src/app/core/cache/models/normalized-object.model.ts deleted file mode 100644 index 21de0de1f0..0000000000 --- a/src/app/core/cache/models/normalized-object.model.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { HALLink } from '../../shared/hal-link.model'; -import { CacheableObject, TypedObject } from '../object-cache.reducer'; -import { autoserialize, deserialize } from 'cerialize'; -import { ResourceType } from '../../shared/resource-type'; -/** - * An abstract model class for a NormalizedObject. - */ -export abstract class NormalizedObject implements CacheableObject { - /** - * The link to the rest endpoint where this object can be found - */ - @deserialize - self: string; - - @deserialize - _links: { - self: HALLink, - [name: string]: HALLink - }; - - /** - * A string representing the kind of object - */ - @deserialize - type: ResourceType; -} diff --git a/src/app/core/cache/object-cache.service.ts b/src/app/core/cache/object-cache.service.ts index b9a164d7af..269f61e847 100644 --- a/src/app/core/cache/object-cache.service.ts +++ b/src/app/core/cache/object-cache.service.ts @@ -11,7 +11,6 @@ import { RestRequestMethod } from '../data/rest-request-method'; import { selfLinkFromUuidSelector } from '../index/index.selectors'; import { GenericConstructor } from '../shared/generic-constructor'; import { LinkService } from './builders/link.service'; -import { NormalizedObject } from './models/normalized-object.model'; import { AddPatchObjectCacheAction, AddToObjectCacheAction, @@ -21,7 +20,7 @@ import { import { CacheableObject, ObjectCacheEntry, ObjectCacheState } from './object-cache.reducer'; import { AddToSSBAction } from './server-sync-buffer.actions'; -import { getMapsToType } from './builders/build-decorators'; +import { getClassForType } from './builders/build-decorators'; /** * The base selector function to select the object cache in the store @@ -55,16 +54,16 @@ export class ObjectCacheService { /** * Add an object to the cache * - * @param objectToCache + * @param object * The object to add * @param msToLive * The number of milliseconds it should be cached for * @param requestUUID * The UUID of the request that resulted in this object */ - add(objectToCache: CacheableObject, msToLive: number, requestUUID: string): void { - this.linkService.removeResolvedLinks(objectToCache); // Ensure the object we're storing has no resolved links - this.store.dispatch(new AddToObjectCacheAction(objectToCache, new Date().getTime(), msToLive, requestUUID)); + add(object: CacheableObject, msToLive: number, requestUUID: string): void { + object = this.linkService.removeResolvedLinks(object); // Ensure the object we're storing has no resolved links + this.store.dispatch(new AddToObjectCacheAction(object, new Date().getTime(), msToLive, requestUUID)); } /** @@ -82,14 +81,14 @@ export class ObjectCacheService { * * @param uuid * The UUID of the object to get - * @return Observable> - * An observable of the requested object in normalized form + * @return Observable + * An observable of the requested object */ getObjectByUUID(uuid: string): - Observable> { + Observable { return this.store.pipe( select(selfLinkFromUuidSelector(uuid)), - mergeMap((selfLink: string) => this.getObjectBySelfLink(selfLink) + mergeMap((selfLink: string) => this.getObjectBySelfLink(selfLink) ) ) } @@ -99,10 +98,10 @@ export class ObjectCacheService { * * @param selfLink * The selfLink of the object to get - * @return Observable> - * An observable of the requested object in normalized form + * @return Observable + * An observable of the requested object */ - getObjectBySelfLink(selfLink: string): Observable> { + getObjectBySelfLink(selfLink: string): Observable { return this.getBySelfLink(selfLink).pipe( map((entry: ObjectCacheEntry) => { if (isNotEmpty(entry.patches)) { @@ -115,11 +114,11 @@ export class ObjectCacheService { } ), map((entry: ObjectCacheEntry) => { - const type: GenericConstructor> = getMapsToType((entry.data as any).type); + const type: GenericConstructor = getClassForType((entry.data as any).type); if (typeof type !== 'function') { throw new Error(`${type} is not a valid constructor for ${JSON.stringify(entry.data)}`); } - return Object.assign(new type(), entry.data) as NormalizedObject + return Object.assign(new type(), entry.data) as T }) ); } @@ -188,7 +187,7 @@ export class ObjectCacheService { * The type of the objects to get * @return Observable> */ - getList(selfLinks: string[]): Observable>> { + getList(selfLinks: string[]): Observable> { return observableCombineLatest( selfLinks.map((selfLink: string) => this.getObjectBySelfLink(selfLink)) ); diff --git a/src/app/core/config/config-response-parsing.service.spec.ts b/src/app/core/config/config-response-parsing.service.spec.ts index 96e0f92cb4..ecc4750c9c 100644 --- a/src/app/core/config/config-response-parsing.service.spec.ts +++ b/src/app/core/config/config-response-parsing.service.spec.ts @@ -7,8 +7,8 @@ import { PaginatedList } from '../data/paginated-list'; import { ConfigRequest } from '../data/request.models'; import { PageInfo } from '../shared/page-info.model'; import { ConfigResponseParsingService } from './config-response-parsing.service'; -import { NormalizedSubmissionDefinitionModel } from './models/normalized-config-submission-definition.model'; -import { NormalizedSubmissionSectionModel } from './models/normalized-config-submission-section.model'; +import { SubmissionDefinitionModel } from './models/config-submission-definition.model'; +import { SubmissionSectionModel } from './models/config-submission-section.model'; describe('ConfigResponseParsingService', () => { let service: ConfigResponseParsingService; @@ -172,7 +172,7 @@ describe('ConfigResponseParsingService', () => { self: 'https://rest.api/config/submissiondefinitions/traditional/sections' }); const definitions = - Object.assign(new NormalizedSubmissionDefinitionModel(), { + Object.assign(new SubmissionDefinitionModel(), { isDefault: true, name: 'traditional', type: 'submissiondefinition', @@ -182,7 +182,7 @@ describe('ConfigResponseParsingService', () => { }, self: 'https://rest.api/config/submissiondefinitions/traditional', sections: new PaginatedList(pageinfo, [ - Object.assign(new NormalizedSubmissionSectionModel(), { + Object.assign(new SubmissionSectionModel(), { header: 'submit.progressbar.describe.stepone', mandatory: true, sectionType: 'submission-form', @@ -197,7 +197,7 @@ describe('ConfigResponseParsingService', () => { }, self: 'https://rest.api/config/submissionsections/traditionalpageone', }), - Object.assign(new NormalizedSubmissionSectionModel(), { + Object.assign(new SubmissionSectionModel(), { header: 'submit.progressbar.describe.steptwo', mandatory: true, sectionType: 'submission-form', @@ -212,7 +212,7 @@ describe('ConfigResponseParsingService', () => { }, self: 'https://rest.api/config/submissionsections/traditionalpagetwo', }), - Object.assign(new NormalizedSubmissionSectionModel(), { + Object.assign(new SubmissionSectionModel(), { header: 'submit.progressbar.upload', mandatory: false, sectionType: 'upload', @@ -227,7 +227,7 @@ describe('ConfigResponseParsingService', () => { }, self: 'https://rest.api/config/submissionsections/upload', }), - Object.assign(new NormalizedSubmissionSectionModel(), { + Object.assign(new SubmissionSectionModel(), { header: 'submit.progressbar.license', mandatory: true, sectionType: 'license', diff --git a/src/app/core/config/models/config-submission-definitions.model.ts b/src/app/core/config/models/config-submission-definitions.model.ts index 4554fa172d..534f044b08 100644 --- a/src/app/core/config/models/config-submission-definitions.model.ts +++ b/src/app/core/config/models/config-submission-definitions.model.ts @@ -1,8 +1,10 @@ +import { inheritSerialization } from 'cerialize'; import { resourceType } from '../../cache/builders/build-decorators'; import { SubmissionDefinitionModel } from './config-submission-definition.model'; import { ResourceType } from '../../shared/resource-type'; @resourceType(SubmissionDefinitionsModel.type) +@inheritSerialization(SubmissionDefinitionModel) export class SubmissionDefinitionsModel extends SubmissionDefinitionModel { static type = new ResourceType('submissiondefinitions'); diff --git a/src/app/core/config/models/config-submission-forms.model.ts b/src/app/core/config/models/config-submission-forms.model.ts index 6f688061f4..aabce33ea5 100644 --- a/src/app/core/config/models/config-submission-forms.model.ts +++ b/src/app/core/config/models/config-submission-forms.model.ts @@ -1,3 +1,4 @@ +import { inheritSerialization } from 'cerialize'; import { resourceType } from '../../cache/builders/build-decorators'; import { SubmissionFormModel } from './config-submission-form.model'; import { ResourceType } from '../../shared/resource-type'; @@ -6,6 +7,7 @@ import { ResourceType } from '../../shared/resource-type'; * A model class for a NormalizedObject. */ @resourceType(SubmissionFormsModel.type) +@inheritSerialization(SubmissionFormModel) export class SubmissionFormsModel extends SubmissionFormModel { static type = new ResourceType('submissionforms'); } diff --git a/src/app/core/config/models/config-submission-sections.model.ts b/src/app/core/config/models/config-submission-sections.model.ts index 870468213c..a87e0cb3d6 100644 --- a/src/app/core/config/models/config-submission-sections.model.ts +++ b/src/app/core/config/models/config-submission-sections.model.ts @@ -1,8 +1,10 @@ +import { inheritSerialization } from 'cerialize'; import { resourceType } from '../../cache/builders/build-decorators'; import { SubmissionSectionModel } from './config-submission-section.model'; import { ResourceType } from '../../shared/resource-type'; @resourceType(SubmissionSectionsModel.type) +@inheritSerialization(SubmissionSectionModel) export class SubmissionSectionsModel extends SubmissionSectionModel { static type = new ResourceType('submissionsections'); } diff --git a/src/app/core/config/models/config-submission-uploads.model.ts b/src/app/core/config/models/config-submission-uploads.model.ts index 9b59ab6cc7..6a9aace270 100644 --- a/src/app/core/config/models/config-submission-uploads.model.ts +++ b/src/app/core/config/models/config-submission-uploads.model.ts @@ -1,3 +1,4 @@ +import { autoserialize } from 'cerialize'; import { resourceType } from '../../cache/builders/build-decorators'; import { ConfigObject } from './config.model'; import { AccessConditionOption } from './config-access-condition-option.model'; @@ -10,15 +11,19 @@ export class SubmissionUploadsModel extends ConfigObject { /** * A list of available bitstream access conditions */ + @autoserialize accessConditionOptions: AccessConditionOption[]; /** * An object representing the configuration describing the bistream metadata form */ + @autoserialize metadata: SubmissionFormsModel; + @autoserialize required: boolean; + @autoserialize maxSize: number; } diff --git a/src/app/core/config/models/normalized-config-submission-definition.model.ts b/src/app/core/config/models/normalized-config-submission-definition.model.ts deleted file mode 100644 index 6cbda0d9be..0000000000 --- a/src/app/core/config/models/normalized-config-submission-definition.model.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { autoserialize, autoserializeAs, inheritSerialization } from 'cerialize'; -import { PaginatedList } from '../../data/paginated-list'; -import { SubmissionDefinitionModel } from './config-submission-definition.model'; -import { SubmissionSectionModel } from './config-submission-section.model'; -import { NormalizedConfigObject } from './normalized-config.model'; - -/** - * Normalized class for the configuration describing the submission - */ -@inheritSerialization(NormalizedConfigObject) -export class NormalizedSubmissionDefinitionModel extends NormalizedConfigObject { - - /** - * A boolean representing if this submission definition is the default or not - */ - @autoserialize - isDefault: boolean; - - /** - * A list of SubmissionSectionModel that are present in this submission definition - */ - @autoserializeAs(SubmissionSectionModel) - sections: PaginatedList; - -} diff --git a/src/app/core/config/models/normalized-config-submission-definitions.model.ts b/src/app/core/config/models/normalized-config-submission-definitions.model.ts deleted file mode 100644 index c1dc6d607b..0000000000 --- a/src/app/core/config/models/normalized-config-submission-definitions.model.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { inheritSerialization } from 'cerialize'; -import { NormalizedConfigObject } from './normalized-config.model'; -import { SubmissionDefinitionsModel } from './config-submission-definitions.model'; -import { NormalizedSubmissionDefinitionModel } from './normalized-config-submission-definition.model'; - -/** - * Normalized class for the configuration describing the submission - */ -@inheritSerialization(NormalizedConfigObject) -export class NormalizedSubmissionDefinitionsModel extends NormalizedSubmissionDefinitionModel { -} diff --git a/src/app/core/config/models/normalized-config-submission-form.model.ts b/src/app/core/config/models/normalized-config-submission-form.model.ts deleted file mode 100644 index d6352c5822..0000000000 --- a/src/app/core/config/models/normalized-config-submission-form.model.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { autoserialize, inheritSerialization } from 'cerialize'; -import { NormalizedConfigObject } from './normalized-config.model'; -import { FormRowModel, SubmissionFormModel } from './config-submission-form.model'; - -/** - * Normalized class for the configuration describing the submission form - */ -@inheritSerialization(NormalizedConfigObject) -export class NormalizedSubmissionFormModel extends NormalizedConfigObject { - - /** - * An array of [FormRowModel] that are present in this form - */ - @autoserialize - rows: FormRowModel[]; -} diff --git a/src/app/core/config/models/normalized-config-submission-forms.model.ts b/src/app/core/config/models/normalized-config-submission-forms.model.ts deleted file mode 100644 index d79571ec16..0000000000 --- a/src/app/core/config/models/normalized-config-submission-forms.model.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { inheritSerialization } from 'cerialize'; -import { NormalizedSubmissionFormModel } from './normalized-config-submission-form.model'; - -/** - * Normalized class for the configuration describing the submission form - */ -@inheritSerialization(NormalizedSubmissionFormModel) -export class NormalizedSubmissionFormsModel extends NormalizedSubmissionFormModel { -} diff --git a/src/app/core/config/models/normalized-config-submission-section.model.ts b/src/app/core/config/models/normalized-config-submission-section.model.ts deleted file mode 100644 index 05ccf454b7..0000000000 --- a/src/app/core/config/models/normalized-config-submission-section.model.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { autoserialize, inheritSerialization } from 'cerialize'; -import { SectionsType } from '../../../submission/sections/sections-type'; -import { NormalizedConfigObject } from './normalized-config.model'; -import { - SubmissionSectionModel, - SubmissionSectionVisibility -} from './config-submission-section.model'; -/** - * Normalized class for the configuration describing the submission section - */ -@inheritSerialization(NormalizedConfigObject) -export class NormalizedSubmissionSectionModel extends NormalizedConfigObject { - - /** - * The header for this section - */ - @autoserialize - header: string; - - /** - * A boolean representing if this submission section is the mandatory or not - */ - @autoserialize - mandatory: boolean; - - /** - * A string representing the kind of section object - */ - @autoserialize - sectionType: SectionsType; - - /** - * The [SubmissionSectionVisibility] object for this section - */ - @autoserialize - visibility: SubmissionSectionVisibility - -} diff --git a/src/app/core/config/models/normalized-config-submission-sections.model.ts b/src/app/core/config/models/normalized-config-submission-sections.model.ts deleted file mode 100644 index 9d1a92aed2..0000000000 --- a/src/app/core/config/models/normalized-config-submission-sections.model.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { inheritSerialization } from 'cerialize'; -import { SubmissionSectionsModel } from './config-submission-sections.model'; -import { NormalizedSubmissionSectionModel } from './normalized-config-submission-section.model'; - -/** - * Normalized class for the configuration describing the submission section - */ -@inheritSerialization(NormalizedSubmissionSectionModel) -export class NormalizedSubmissionSectionsModel extends NormalizedSubmissionSectionModel { -} diff --git a/src/app/core/config/models/normalized-config-submission-uploads.model.ts b/src/app/core/config/models/normalized-config-submission-uploads.model.ts deleted file mode 100644 index 5393c1e89a..0000000000 --- a/src/app/core/config/models/normalized-config-submission-uploads.model.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { autoserialize, autoserializeAs, inheritSerialization } from 'cerialize'; -import { AccessConditionOption } from './config-access-condition-option.model'; -import { SubmissionFormsModel } from './config-submission-forms.model'; -import { NormalizedConfigObject } from './normalized-config.model'; -import { SubmissionUploadsModel } from './config-submission-uploads.model'; -/** - * Normalized class for the configuration describing the submission upload section - */ -@inheritSerialization(NormalizedConfigObject) -export class NormalizedSubmissionUploadsModel extends NormalizedConfigObject { - - /** - * A list of available bitstream access conditions - */ - @autoserialize - accessConditionOptions: AccessConditionOption[]; - - /** - * An object representing the configuration describing the bistream metadata form - */ - @autoserializeAs(SubmissionFormsModel) - metadata: SubmissionFormsModel; - - @autoserialize - required: boolean; - - @autoserialize - maxSize: number; - -} diff --git a/src/app/core/config/models/normalized-config.model.ts b/src/app/core/config/models/normalized-config.model.ts deleted file mode 100644 index f697fdf857..0000000000 --- a/src/app/core/config/models/normalized-config.model.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { autoserialize, inheritSerialization } from 'cerialize'; -import { NormalizedObject } from '../../cache/models/normalized-object.model'; -import { CacheableObject } from '../../cache/object-cache.reducer'; -import { HALLink } from '../../shared/hal-link.model'; -import { ResourceType } from '../../shared/resource-type'; -import { excludeFromEquals } from '../../utilities/equals.decorators'; - -/** - * Normalized abstract class for a configuration object - */ -@inheritSerialization(NormalizedObject) -export abstract class NormalizedConfigObject implements CacheableObject { - - /** - * The name for this configuration - */ - @autoserialize - public name: string; - - /** - * The object type - */ - @excludeFromEquals - @autoserialize - type: ResourceType; - - /** - * The links to all related resources returned by the rest api. - */ - @autoserialize - public _links: { - self: HALLink, - [name: string]: HALLink - }; - - /** - * The link to the rest endpoint where this config object can be found - */ - @autoserialize - self: string; - -} diff --git a/src/app/core/core.module.ts b/src/app/core/core.module.ts index 9afd2276b6..82edaed96b 100644 --- a/src/app/core/core.module.ts +++ b/src/app/core/core.module.ts @@ -38,7 +38,6 @@ import { AuthInterceptor } from './auth/auth.interceptor'; import { AuthenticatedGuard } from './auth/authenticated.guard'; import { AuthStatus } from './auth/models/auth-status.model'; import { BrowseService } from './browse/browse.service'; -import { NormalizedObjectBuildService } from './cache/builders/normalized-object-build.service'; import { RemoteDataBuildService } from './cache/builders/remote-data-build.service'; import { ObjectCacheService } from './cache/object-cache.service'; import { ConfigResponseParsingService } from './config/config-response-parsing.service'; @@ -194,7 +193,6 @@ const PROVIDERS = [ ResourcePolicyService, RegistryService, BitstreamFormatDataService, - NormalizedObjectBuildService, RemoteDataBuildService, EndpointMapResponseParsingService, FacetValueResponseParsingService, diff --git a/src/app/core/data/base-response-parsing.service.ts b/src/app/core/data/base-response-parsing.service.ts index c9bc58b5d7..a1aea3ee38 100644 --- a/src/app/core/data/base-response-parsing.service.ts +++ b/src/app/core/data/base-response-parsing.service.ts @@ -7,11 +7,33 @@ import { ObjectCacheService } from '../cache/object-cache.service'; import { GlobalConfig } from '../../../config/global-config.interface'; import { GenericConstructor } from '../shared/generic-constructor'; import { PaginatedList } from './paginated-list'; -import { isRestDataObject, isRestPaginatedList } from '../cache/builders/normalized-object-build.service'; -import { getMapsToType } from '../cache/builders/build-decorators'; +import { getClassForType } from '../cache/builders/build-decorators'; import { RestRequest } from './request.models'; /* tslint:disable:max-classes-per-file */ +/** + * Return true if halObj has a value for `_links.self` + * + * @param {any} halObj The object to test + */ +export function isRestDataObject(halObj: any): boolean { + return isNotEmpty(halObj._links) && hasValue(halObj._links.self); +} + +/** + * Return true if halObj has a value for `page` with properties + * `size`, `totalElements`, `totalPages`, `number` + * + * @param {any} halObj The object to test + */ +export function isRestPaginatedList(halObj: any): boolean { + return hasValue(halObj.page) && + hasValue(halObj.page.size) && + hasValue(halObj.page.totalElements) && + hasValue(halObj.page.totalPages) && + hasValue(halObj.page.number); +} + export abstract class BaseResponseParsingService { protected abstract EnvConfig: GlobalConfig; protected abstract objectCache: ObjectCacheService; @@ -89,7 +111,7 @@ export abstract class BaseResponseParsingService { protected deserialize(obj): any { const type: string = obj.type; if (hasValue(type)) { - const normObjConstructor = getMapsToType(type) as GenericConstructor; + const normObjConstructor = getClassForType(type) as GenericConstructor; if (hasValue(normObjConstructor)) { const serializer = new this.serializerConstructor(normObjConstructor); diff --git a/src/app/core/data/bitstream-data.service.ts b/src/app/core/data/bitstream-data.service.ts index 27aa60ae42..e1d55598e4 100644 --- a/src/app/core/data/bitstream-data.service.ts +++ b/src/app/core/data/bitstream-data.service.ts @@ -7,7 +7,6 @@ import { hasValue } from '../../shared/empty.util'; import { NotificationsService } from '../../shared/notifications/notifications.service'; import { FollowLinkConfig } from '../../shared/utils/follow-link-config.model'; import { dataService } from '../cache/builders/build-decorators'; -import { NormalizedObjectBuildService } from '../cache/builders/normalized-object-build.service'; import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; import { ObjectCacheService } from '../cache/object-cache.service'; import { CoreState } from '../core.reducers'; @@ -37,7 +36,6 @@ export class BitstreamDataService extends DataService { constructor( protected requestService: RequestService, protected rdbService: RemoteDataBuildService, - protected dataBuildService: NormalizedObjectBuildService, protected store: Store, protected cds: CommunityDataService, protected objectCache: ObjectCacheService, diff --git a/src/app/core/data/bitstream-format-data.service.spec.ts b/src/app/core/data/bitstream-format-data.service.spec.ts index c626fcd6e2..daf3dea87c 100644 --- a/src/app/core/data/bitstream-format-data.service.spec.ts +++ b/src/app/core/data/bitstream-format-data.service.spec.ts @@ -8,7 +8,6 @@ import { cold, getTestScheduler, hot } from 'jasmine-marbles'; import { HALEndpointService } from '../shared/hal-endpoint.service'; import { NotificationsService } from '../../shared/notifications/notifications.service'; import { HttpClient } from '@angular/common/http'; -import { NormalizedObjectBuildService } from '../cache/builders/normalized-object-build.service'; import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; import { BitstreamFormat } from '../shared/bitstream-format.model'; import { async } from '@angular/core/testing'; @@ -48,14 +47,12 @@ describe('BitstreamFormatDataService', () => { const notificationsService = {} as NotificationsService; const http = {} as HttpClient; const comparator = {} as any; - const dataBuildService = {} as NormalizedObjectBuildService; const rdbService = {} as RemoteDataBuildService; function initTestService(halService) { return new BitstreamFormatDataService( requestService, rdbService, - dataBuildService, store, objectCache, halService, diff --git a/src/app/core/data/bitstream-format-data.service.ts b/src/app/core/data/bitstream-format-data.service.ts index 7fff9d012a..5c7029a09f 100644 --- a/src/app/core/data/bitstream-format-data.service.ts +++ b/src/app/core/data/bitstream-format-data.service.ts @@ -13,7 +13,6 @@ import { BitstreamFormatRegistryState } from '../../+admin/admin-registries/bits import { hasValue } from '../../shared/empty.util'; import { NotificationsService } from '../../shared/notifications/notifications.service'; import { dataService } from '../cache/builders/build-decorators'; -import { NormalizedObjectBuildService } from '../cache/builders/normalized-object-build.service'; import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; import { ObjectCacheService } from '../cache/object-cache.service'; import { RestResponse } from '../cache/response.models'; @@ -50,7 +49,6 @@ export class BitstreamFormatDataService extends DataService { constructor( protected requestService: RequestService, protected rdbService: RemoteDataBuildService, - protected dataBuildService: NormalizedObjectBuildService, protected store: Store, protected objectCache: ObjectCacheService, protected halService: HALEndpointService, diff --git a/src/app/core/data/browse-items-response-parsing-service.ts b/src/app/core/data/browse-items-response-parsing-service.ts index c8a432b3e5..08ade5772d 100644 --- a/src/app/core/data/browse-items-response-parsing-service.ts +++ b/src/app/core/data/browse-items-response-parsing-service.ts @@ -3,11 +3,11 @@ import { Inject, Injectable } from '@angular/core'; import { GLOBAL_CONFIG } from '../../../config'; import { GlobalConfig } from '../../../config/global-config.interface'; import { hasValue, isNotEmpty } from '../../shared/empty.util'; -import { NormalizedDSpaceObject } from '../cache/models/normalized-dspace-object.model'; import { ObjectCacheService } from '../cache/object-cache.service'; import { ErrorResponse, GenericSuccessResponse, RestResponse } from '../cache/response.models'; import { DSpaceRESTV2Response } from '../dspace-rest-v2/dspace-rest-v2-response.model'; import { DSpaceSerializer } from '../dspace-rest-v2/dspace.serializer'; +import { DSpaceObject } from '../shared/dspace-object.model'; import { BaseResponseParsingService } from './base-response-parsing.service'; import { ResponseParsingService } from './parsing.service'; import { RestRequest } from './request.models'; @@ -34,7 +34,7 @@ export class BrowseItemsResponseParsingService extends BaseResponseParsingServic parse(request: RestRequest, data: DSpaceRESTV2Response): RestResponse { if (isNotEmpty(data.payload) && isNotEmpty(data.payload._embedded) && Array.isArray(data.payload._embedded[Object.keys(data.payload._embedded)[0]])) { - const serializer = new DSpaceSerializer(NormalizedDSpaceObject); + const serializer = new DSpaceSerializer(DSpaceObject); const items = serializer.deserializeArray(data.payload._embedded[Object.keys(data.payload._embedded)[0]]); return new GenericSuccessResponse(items, data.statusCode, data.statusText, this.processPageInfo(data.payload)); } else if (hasValue(data.payload) && hasValue(data.payload.page)) { diff --git a/src/app/core/data/bundle-data.service.ts b/src/app/core/data/bundle-data.service.ts index 2d668e5416..5a5d52b637 100644 --- a/src/app/core/data/bundle-data.service.ts +++ b/src/app/core/data/bundle-data.service.ts @@ -7,7 +7,6 @@ import { hasValue } from '../../shared/empty.util'; import { NotificationsService } from '../../shared/notifications/notifications.service'; import { FollowLinkConfig } from '../../shared/utils/follow-link-config.model'; import { dataService } from '../cache/builders/build-decorators'; -import { NormalizedObjectBuildService } from '../cache/builders/normalized-object-build.service'; import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; import { ObjectCacheService } from '../cache/object-cache.service'; import { CoreState } from '../core.reducers'; @@ -31,12 +30,10 @@ import { RequestService } from './request.service'; @dataService(BUNDLE) export class BundleDataService extends DataService { protected linkPath = 'bundles'; - protected forceBypassCache = false; constructor( protected requestService: RequestService, protected rdbService: RemoteDataBuildService, - protected dataBuildService: NormalizedObjectBuildService, protected store: Store, protected objectCache: ObjectCacheService, protected halService: HALEndpointService, diff --git a/src/app/core/data/collection-data.service.ts b/src/app/core/data/collection-data.service.ts index 5238b51f5a..4c64b0a60b 100644 --- a/src/app/core/data/collection-data.service.ts +++ b/src/app/core/data/collection-data.service.ts @@ -11,7 +11,6 @@ import { NotificationsService } from '../../shared/notifications/notifications.s import { PaginatedSearchOptions } from '../../shared/search/paginated-search-options.model'; import { FollowLinkConfig } from '../../shared/utils/follow-link-config.model'; import { dataService } from '../cache/builders/build-decorators'; -import { NormalizedObjectBuildService } from '../cache/builders/normalized-object-build.service'; import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; import { SearchParam } from '../cache/models/search-param.model'; import { ObjectCacheService } from '../cache/object-cache.service'; @@ -58,7 +57,6 @@ export class CollectionDataService extends ComColDataService { constructor( protected requestService: RequestService, protected rdbService: RemoteDataBuildService, - protected dataBuildService: NormalizedObjectBuildService, protected store: Store, protected cds: CommunityDataService, protected objectCache: ObjectCacheService, diff --git a/src/app/core/data/comcol-data.service.spec.ts b/src/app/core/data/comcol-data.service.spec.ts index f364afa873..fc487527b9 100644 --- a/src/app/core/data/comcol-data.service.spec.ts +++ b/src/app/core/data/comcol-data.service.spec.ts @@ -6,9 +6,7 @@ import { TestScheduler } from 'rxjs/testing'; import { GlobalConfig } from '../../../config'; import { getMockRequestService } from '../../shared/mocks/mock-request.service'; import { NotificationsService } from '../../shared/notifications/notifications.service'; -import { NormalizedObjectBuildService } from '../cache/builders/normalized-object-build.service'; import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; -import { NormalizedObject } from '../cache/models/normalized-object.model'; import { ObjectCacheService } from '../cache/object-cache.service'; import { CoreState } from '../core.reducers'; import { Community } from '../shared/community.model'; @@ -23,16 +21,11 @@ import { RequestService } from './request.service'; const LINK_NAME = 'test'; -/* tslint:disable:max-classes-per-file */ -class NormalizedTestObject extends NormalizedObject { -} - class TestService extends ComColDataService { constructor( protected requestService: RequestService, protected rdbService: RemoteDataBuildService, - protected dataBuildService: NormalizedObjectBuildService, protected store: Store, protected EnvConfig: GlobalConfig, protected cds: CommunityDataService, @@ -52,8 +45,6 @@ class TestService extends ComColDataService { } } -/* tslint:enable:max-classes-per-file */ - describe('ComColDataService', () => { let scheduler: TestScheduler; let service: TestService; @@ -68,7 +59,6 @@ describe('ComColDataService', () => { const notificationsService = {} as NotificationsService; const http = {} as HttpClient; const comparator = {} as any; - const dataBuildService = {} as NormalizedObjectBuildService; const scopeID = 'd9d30c0c-69b7-4369-8397-ca67c888974d'; const options = Object.assign(new FindListOptions(), { @@ -115,7 +105,6 @@ describe('ComColDataService', () => { return new TestService( requestService, rdbService, - dataBuildService, store, EnvConfig, cds, diff --git a/src/app/core/data/community-data.service.ts b/src/app/core/data/community-data.service.ts index 1d64bc6a63..123c3eccd1 100644 --- a/src/app/core/data/community-data.service.ts +++ b/src/app/core/data/community-data.service.ts @@ -7,7 +7,6 @@ import { filter, switchMap, take } from 'rxjs/operators'; import { hasValue } from '../../shared/empty.util'; import { NotificationsService } from '../../shared/notifications/notifications.service'; import { dataService } from '../cache/builders/build-decorators'; -import { NormalizedObjectBuildService } from '../cache/builders/normalized-object-build.service'; import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; import { ObjectCacheService } from '../cache/object-cache.service'; import { CoreState } from '../core.reducers'; @@ -31,7 +30,6 @@ export class CommunityDataService extends ComColDataService { constructor( protected requestService: RequestService, protected rdbService: RemoteDataBuildService, - protected dataBuildService: NormalizedObjectBuildService, protected store: Store, protected objectCache: ObjectCacheService, protected halService: HALEndpointService, diff --git a/src/app/core/data/data.service.spec.ts b/src/app/core/data/data.service.spec.ts index 9e13850ad5..ddb77496e3 100644 --- a/src/app/core/data/data.service.spec.ts +++ b/src/app/core/data/data.service.spec.ts @@ -1,43 +1,36 @@ -import { HttpClient } from '@angular/common/http'; -import { Store } from '@ngrx/store'; -import { compare, Operation } from 'fast-json-patch'; -import { Observable, of as observableOf } from 'rxjs'; -import * as uuidv4 from 'uuid/v4'; -import { NotificationsService } from '../../shared/notifications/notifications.service'; -import { createSuccessfulRemoteDataObject$ } from '../../shared/testing/utils'; -import { NormalizedObjectBuildService } from '../cache/builders/normalized-object-build.service'; +import { DataService } from './data.service'; +import { RequestService } from './request.service'; import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; -import { NormalizedObject } from '../cache/models/normalized-object.model'; +import { CoreState } from '../core.reducers'; +import { Store } from '@ngrx/store'; +import { HALEndpointService } from '../shared/hal-endpoint.service'; +import { Observable, of as observableOf } from 'rxjs'; +import { FindListOptions } from './request.models'; import { SortDirection, SortOptions } from '../cache/models/sort-options.model'; import { ObjectCacheService } from '../cache/object-cache.service'; -import { CoreState } from '../core.reducers'; +import { compare, Operation } from 'fast-json-patch'; import { DSpaceObject } from '../shared/dspace-object.model'; -import { HALEndpointService } from '../shared/hal-endpoint.service'; -import { Item } from '../shared/item.model'; import { ChangeAnalyzer } from './change-analyzer'; -import { DataService } from './data.service'; -import { FindListOptions } from './request.models'; -import { RequestService } from './request.service'; +import { HttpClient } from '@angular/common/http'; +import { NotificationsService } from '../../shared/notifications/notifications.service'; +import { Item } from '../shared/item.model'; +import * as uuidv4 from 'uuid/v4'; +import { createSuccessfulRemoteDataObject$ } from '../../shared/testing/utils'; const endpoint = 'https://rest.api/core'; -// tslint:disable:max-classes-per-file -class NormalizedTestObject extends NormalizedObject { -} - class TestService extends DataService { constructor( protected requestService: RequestService, protected rdbService: RemoteDataBuildService, - protected dataBuildService: NormalizedObjectBuildService, protected store: Store, protected linkPath: string, protected halService: HALEndpointService, protected objectCache: ObjectCacheService, protected notificationsService: NotificationsService, protected http: HttpClient, - protected comparator: ChangeAnalyzer + protected comparator: ChangeAnalyzer ) { super(); } @@ -47,8 +40,8 @@ class TestService extends DataService { } } -class DummyChangeAnalyzer implements ChangeAnalyzer { - diff(object1: NormalizedTestObject, object2: NormalizedTestObject): Operation[] { +class DummyChangeAnalyzer implements ChangeAnalyzer { + diff(object1: Item, object2: Item): Operation[] { return compare((object1 as any).metadata, (object2 as any).metadata); } @@ -63,9 +56,6 @@ describe('DataService', () => { const notificationsService = {} as NotificationsService; const http = {} as HttpClient; const comparator = new DummyChangeAnalyzer() as any; - const dataBuildService = { - normalize: (object) => object - } as NormalizedObjectBuildService; const objectCache = { addPatch: () => { /* empty */ @@ -80,7 +70,6 @@ describe('DataService', () => { return new TestService( requestService, rdbService, - dataBuildService, store, endpoint, halService, diff --git a/src/app/core/data/data.service.ts b/src/app/core/data/data.service.ts index 489fbad371..5d0b8774e1 100644 --- a/src/app/core/data/data.service.ts +++ b/src/app/core/data/data.service.ts @@ -18,10 +18,8 @@ import { hasValue, isNotEmpty, isNotEmptyOperator } from '../../shared/empty.uti import { NotificationOptions } from '../../shared/notifications/models/notification-options.model'; import { NotificationsService } from '../../shared/notifications/notifications.service'; import { FollowLinkConfig } from '../../shared/utils/follow-link-config.model'; -import { getMapsToType } from '../cache/builders/build-decorators'; -import { NormalizedObjectBuildService } from '../cache/builders/normalized-object-build.service'; +import { getClassForType } from '../cache/builders/build-decorators'; import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; -import { NormalizedObject } from '../cache/models/normalized-object.model'; import { SearchParam } from '../cache/models/search-param.model'; import { CacheableObject } from '../cache/object-cache.reducer'; import { ObjectCacheService } from '../cache/object-cache.service'; @@ -55,7 +53,6 @@ import { RestRequestMethod } from './rest-request-method'; export abstract class DataService { protected abstract requestService: RequestService; protected abstract rdbService: RemoteDataBuildService; - protected abstract dataBuildService: NormalizedObjectBuildService; protected abstract store: Store; protected abstract linkPath: string; protected abstract halService: HALEndpointService; @@ -333,8 +330,7 @@ export abstract class DataService { map((endpoint: string) => parentUUID ? `${endpoint}?parent=${parentUUID}` : endpoint) ); - const normalizedObject: NormalizedObject = this.dataBuildService.normalize(dso); - const serializedDso = new DSpaceSerializer(getMapsToType((dso as any).type)).serialize(normalizedObject); + const serializedDso = new DSpaceSerializer(getClassForType((dso as any).type)).serialize(dso); const request$ = endpoint$.pipe( take(1), diff --git a/src/app/core/data/default-change-analyzer.service.ts b/src/app/core/data/default-change-analyzer.service.ts index 8e8674749b..d8cfb999dc 100644 --- a/src/app/core/data/default-change-analyzer.service.ts +++ b/src/app/core/data/default-change-analyzer.service.ts @@ -1,8 +1,7 @@ import { Injectable } from '@angular/core'; import { compare } from 'fast-json-patch'; import { Operation } from 'fast-json-patch/lib/core'; -import { getMapsToType } from '../cache/builders/build-decorators'; -import { NormalizedObject } from '../cache/models/normalized-object.model'; +import { getClassForType } from '../cache/builders/build-decorators'; import { CacheableObject } from '../cache/object-cache.reducer'; import { DSpaceSerializer } from '../dspace-rest-v2/dspace.serializer'; import { ChangeAnalyzer } from './change-analyzer'; @@ -20,14 +19,14 @@ export class DefaultChangeAnalyzer implements ChangeA * Compare the metadata of two CacheableObject and return the differences as * a JsonPatch Operation Array * - * @param {NormalizedObject} object1 + * @param {CacheableObject} object1 * The first object to compare - * @param {NormalizedObject} object2 + * @param {CacheableObject} object2 * The second object to compare */ diff(object1: T, object2: T): Operation[] { - const serializer1 = new DSpaceSerializer(getMapsToType(object1.type)); - const serializer2 = new DSpaceSerializer(getMapsToType(object2.type)); + const serializer1 = new DSpaceSerializer(getClassForType(object1.type)); + const serializer2 = new DSpaceSerializer(getClassForType(object2.type)); return compare(serializer1.serialize(object1), serializer2.serialize(object2)); } } diff --git a/src/app/core/data/dso-change-analyzer.service.ts b/src/app/core/data/dso-change-analyzer.service.ts index 7dc5f8fd2d..dba8395bc5 100644 --- a/src/app/core/data/dso-change-analyzer.service.ts +++ b/src/app/core/data/dso-change-analyzer.service.ts @@ -1,7 +1,6 @@ import { Operation } from 'fast-json-patch/lib/core'; import { compare } from 'fast-json-patch'; import { ChangeAnalyzer } from './change-analyzer'; -import { NormalizedDSpaceObject } from '../cache/models/normalized-dspace-object.model'; import { Injectable } from '@angular/core'; import { DSpaceObject } from '../shared/dspace-object.model'; diff --git a/src/app/core/data/dso-redirect-data.service.spec.ts b/src/app/core/data/dso-redirect-data.service.spec.ts index b7bae768c2..25a148d92b 100644 --- a/src/app/core/data/dso-redirect-data.service.spec.ts +++ b/src/app/core/data/dso-redirect-data.service.spec.ts @@ -7,7 +7,6 @@ import { RequestService } from './request.service'; import { ObjectCacheService } from '../cache/object-cache.service'; import { NotificationsService } from '../../shared/notifications/notifications.service'; import { HttpClient } from '@angular/common/http'; -import { NormalizedObjectBuildService } from '../cache/builders/normalized-object-build.service'; import { DsoRedirectDataService } from './dso-redirect-data.service'; import { Store } from '@ngrx/store'; import { CoreState } from '../core.reducers'; @@ -31,7 +30,6 @@ describe('DsoRedirectDataService', () => { const notificationsService = {} as NotificationsService; const http = {} as HttpClient; const comparator = {} as any; - const dataBuildService = {} as NormalizedObjectBuildService; const objectCache = {} as ObjectCacheService; let setup; beforeEach(() => { @@ -68,7 +66,6 @@ describe('DsoRedirectDataService', () => { service = new DsoRedirectDataService( requestService, rdbService, - dataBuildService, store, objectCache, halService, diff --git a/src/app/core/data/dso-redirect-data.service.ts b/src/app/core/data/dso-redirect-data.service.ts index 8855791943..232fde65d0 100644 --- a/src/app/core/data/dso-redirect-data.service.ts +++ b/src/app/core/data/dso-redirect-data.service.ts @@ -1,35 +1,32 @@ -import { DataService } from './data.service'; -import { NormalizedObjectBuildService } from '../cache/builders/normalized-object-build.service'; -import { HALEndpointService } from '../shared/hal-endpoint.service'; import { HttpClient } from '@angular/common/http'; -import { NotificationsService } from '../../shared/notifications/notifications.service'; -import { ObjectCacheService } from '../cache/object-cache.service'; -import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; -import { RequestService } from './request.service'; -import { Store } from '@ngrx/store'; -import { CoreState } from '../core.reducers'; -import { FindListOptions, FindByIDRequest, IdentifierType } from './request.models'; -import { Observable } from 'rxjs'; -import { RemoteData } from './remote-data'; -import { DSOChangeAnalyzer } from './dso-change-analyzer.service'; import { Injectable } from '@angular/core'; -import { filter, take, tap } from 'rxjs/operators'; -import { hasValue } from '../../shared/empty.util'; -import { getFinishedRemoteData } from '../shared/operators'; import { Router } from '@angular/router'; +import { Store } from '@ngrx/store'; +import { Observable } from 'rxjs'; +import { take, tap } from 'rxjs/operators'; +import { hasValue } from '../../shared/empty.util'; +import { NotificationsService } from '../../shared/notifications/notifications.service'; +import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; +import { ObjectCacheService } from '../cache/object-cache.service'; +import { CoreState } from '../core.reducers'; +import { HALEndpointService } from '../shared/hal-endpoint.service'; +import { getFinishedRemoteData } from '../shared/operators'; +import { DataService } from './data.service'; +import { DSOChangeAnalyzer } from './dso-change-analyzer.service'; +import { RemoteData } from './remote-data'; +import { FindByIDRequest, IdentifierType } from './request.models'; +import { RequestService } from './request.service'; @Injectable() export class DsoRedirectDataService extends DataService { // Set the default link path to the identifier lookup endpoint. protected linkPath = 'pid'; - protected forceBypassCache = false; private uuidEndpoint = 'dso'; constructor( protected requestService: RequestService, protected rdbService: RemoteDataBuildService, - protected dataBuildService: NormalizedObjectBuildService, protected store: Store, protected objectCache: ObjectCacheService, protected halService: HALEndpointService, diff --git a/src/app/core/data/dso-response-parsing.service.ts b/src/app/core/data/dso-response-parsing.service.ts index 1c9c7d0e55..83676ce105 100644 --- a/src/app/core/data/dso-response-parsing.service.ts +++ b/src/app/core/data/dso-response-parsing.service.ts @@ -3,7 +3,6 @@ import { Inject, Injectable } from '@angular/core'; import { ObjectCacheService } from '../cache/object-cache.service'; import { GlobalConfig } from '../../../config/global-config.interface'; import { GLOBAL_CONFIG } from '../../../config'; -import { NormalizedObject } from '../cache/models/normalized-object.model'; import { DSpaceRESTV2Response } from '../dspace-rest-v2/dspace-rest-v2-response.model'; import { RestResponse, DSOSuccessResponse } from '../cache/response.models'; import { RestRequest } from './request.models'; @@ -30,7 +29,7 @@ export class DSOResponseParsingService extends BaseResponseParsingService implem if (hasValue(data.payload) && hasValue(data.payload.page) && data.payload.page.totalElements === 0) { processRequestDTO = { page: [] }; } else { - processRequestDTO = this.process>(data.payload, request); + processRequestDTO = this.process(data.payload, request); } let objectList = processRequestDTO; diff --git a/src/app/core/data/dspace-object-data.service.spec.ts b/src/app/core/data/dspace-object-data.service.spec.ts index 7047db6065..b7c8c3fe9d 100644 --- a/src/app/core/data/dspace-object-data.service.spec.ts +++ b/src/app/core/data/dspace-object-data.service.spec.ts @@ -9,8 +9,6 @@ import { DSpaceObjectDataService } from './dspace-object-data.service'; import { ObjectCacheService } from '../cache/object-cache.service'; import { NotificationsService } from '../../shared/notifications/notifications.service'; import { HttpClient } from '@angular/common/http'; -import { NormalizedObjectBuildService } from '../cache/builders/normalized-object-build.service'; - describe('DSpaceObjectDataService', () => { let scheduler: TestScheduler; let service: DSpaceObjectDataService; @@ -46,12 +44,10 @@ describe('DSpaceObjectDataService', () => { const notificationsService = {} as NotificationsService; const http = {} as HttpClient; const comparator = {} as any; - const dataBuildService = {} as NormalizedObjectBuildService; service = new DSpaceObjectDataService( requestService, rdbService, - dataBuildService, objectCache, halService, notificationsService, diff --git a/src/app/core/data/dspace-object-data.service.ts b/src/app/core/data/dspace-object-data.service.ts index 2c72f1540f..38e9f8d888 100644 --- a/src/app/core/data/dspace-object-data.service.ts +++ b/src/app/core/data/dspace-object-data.service.ts @@ -4,7 +4,6 @@ import { Store } from '@ngrx/store'; import { Observable } from 'rxjs'; import { NotificationsService } from '../../shared/notifications/notifications.service'; import { dataService } from '../cache/builders/build-decorators'; -import { NormalizedObjectBuildService } from '../cache/builders/normalized-object-build.service'; import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; import { ObjectCacheService } from '../cache/object-cache.service'; import { CoreState } from '../core.reducers'; @@ -23,7 +22,6 @@ class DataServiceImpl extends DataService { constructor( protected requestService: RequestService, protected rdbService: RemoteDataBuildService, - protected dataBuildService: NormalizedObjectBuildService, protected store: Store, protected objectCache: ObjectCacheService, protected halService: HALEndpointService, @@ -47,13 +45,12 @@ export class DSpaceObjectDataService { constructor( protected requestService: RequestService, protected rdbService: RemoteDataBuildService, - protected dataBuildService: NormalizedObjectBuildService, protected objectCache: ObjectCacheService, protected halService: HALEndpointService, protected notificationsService: NotificationsService, protected http: HttpClient, protected comparator: DSOChangeAnalyzer) { - this.dataService = new DataServiceImpl(requestService, rdbService, dataBuildService, null, objectCache, halService, notificationsService, http, comparator); + this.dataService = new DataServiceImpl(requestService, rdbService, null, objectCache, halService, notificationsService, http, comparator); } findById(uuid: string): Observable> { diff --git a/src/app/core/data/entity-type-data.service.ts b/src/app/core/data/entity-type-data.service.ts index caad775139..db958fe680 100644 --- a/src/app/core/data/entity-type-data.service.ts +++ b/src/app/core/data/entity-type-data.service.ts @@ -5,7 +5,6 @@ import { Observable } from 'rxjs'; import { NotificationsService } from '../../shared/notifications/notifications.service'; import { FollowLinkConfig } from '../../shared/utils/follow-link-config.model'; import { dataService } from '../cache/builders/build-decorators'; -import { NormalizedObjectBuildService } from '../cache/builders/normalized-object-build.service'; import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; import { ObjectCacheService } from '../cache/object-cache.service'; import { CoreState } from '../core.reducers'; @@ -25,7 +24,6 @@ class DataServiceImpl extends DataService { constructor( protected requestService: RequestService, protected rdbService: RemoteDataBuildService, - protected dataBuildService: NormalizedObjectBuildService, protected store: Store, protected objectCache: ObjectCacheService, protected halService: HALEndpointService, @@ -44,14 +42,13 @@ export class ItemTypeDataService { constructor( protected requestService: RequestService, protected rdbService: RemoteDataBuildService, - protected dataBuildService: NormalizedObjectBuildService, protected store: Store, protected objectCache: ObjectCacheService, protected halService: HALEndpointService, protected notificationsService: NotificationsService, protected http: HttpClient, protected comparator: DefaultChangeAnalyzer) { - this.dataService = new DataServiceImpl(requestService, rdbService, dataBuildService, null, objectCache, halService, notificationsService, http, comparator); + this.dataService = new DataServiceImpl(requestService, rdbService, null, objectCache, halService, notificationsService, http, comparator); } /** diff --git a/src/app/core/data/external-source.service.ts b/src/app/core/data/external-source.service.ts index c32c13a20f..0c1a8d255c 100644 --- a/src/app/core/data/external-source.service.ts +++ b/src/app/core/data/external-source.service.ts @@ -3,7 +3,6 @@ import { DataService } from './data.service'; import { ExternalSource } from '../shared/external-source.model'; import { RequestService } from './request.service'; import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; -import { NormalizedObjectBuildService } from '../cache/builders/normalized-object-build.service'; import { Store } from '@ngrx/store'; import { CoreState } from '../core.reducers'; import { ObjectCacheService } from '../cache/object-cache.service'; @@ -31,7 +30,6 @@ export class ExternalSourceService extends DataService { constructor( protected requestService: RequestService, protected rdbService: RemoteDataBuildService, - protected dataBuildService: NormalizedObjectBuildService, protected store: Store, protected objectCache: ObjectCacheService, protected halService: HALEndpointService, diff --git a/src/app/core/data/item-data.service.spec.ts b/src/app/core/data/item-data.service.spec.ts index 6d96237db2..06adfd5143 100644 --- a/src/app/core/data/item-data.service.spec.ts +++ b/src/app/core/data/item-data.service.spec.ts @@ -6,7 +6,6 @@ import { TestScheduler } from 'rxjs/testing'; import { getMockRequestService } from '../../shared/mocks/mock-request.service'; import { NotificationsService } from '../../shared/notifications/notifications.service'; import { BrowseService } from '../browse/browse.service'; -import { NormalizedObjectBuildService } from '../cache/builders/normalized-object-build.service'; import { ObjectCacheService } from '../cache/object-cache.service'; import { RestResponse } from '../cache/response.models'; import { CoreState } from '../core.reducers'; @@ -66,7 +65,6 @@ describe('ItemDataService', () => { const notificationsService = {} as NotificationsService; const http = {} as HttpClient; const comparator = {} as any; - const dataBuildService = {} as NormalizedObjectBuildService; const itemEndpoint = 'https://rest.api/core/items'; const ScopedItemEndpoint = `https://rest.api/core/items/${scopeID}`; @@ -83,7 +81,6 @@ describe('ItemDataService', () => { return new ItemDataService( requestService, rdbService, - dataBuildService, store, bs, objectCache, diff --git a/src/app/core/data/item-data.service.ts b/src/app/core/data/item-data.service.ts index b930ba2b19..b9fb36e6d8 100644 --- a/src/app/core/data/item-data.service.ts +++ b/src/app/core/data/item-data.service.ts @@ -7,7 +7,6 @@ import { hasValue, isNotEmpty, isNotEmptyOperator } from '../../shared/empty.uti import { NotificationsService } from '../../shared/notifications/notifications.service'; import { BrowseService } from '../browse/browse.service'; import { dataService } from '../cache/builders/build-decorators'; -import { NormalizedObjectBuildService } from '../cache/builders/normalized-object-build.service'; import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; import { ObjectCacheService } from '../cache/object-cache.service'; import { GenericSuccessResponse, RestResponse } from '../cache/response.models'; @@ -50,7 +49,6 @@ export class ItemDataService extends DataService { constructor( protected requestService: RequestService, protected rdbService: RemoteDataBuildService, - protected dataBuildService: NormalizedObjectBuildService, protected store: Store, private bs: BrowseService, protected objectCache: ObjectCacheService, diff --git a/src/app/core/data/license-data.service.ts b/src/app/core/data/license-data.service.ts index 799de864ff..fbdc44f233 100644 --- a/src/app/core/data/license-data.service.ts +++ b/src/app/core/data/license-data.service.ts @@ -5,7 +5,6 @@ import { Observable } from 'rxjs'; import { NotificationsService } from '../../shared/notifications/notifications.service'; import { FollowLinkConfig } from '../../shared/utils/follow-link-config.model'; import { dataService } from '../cache/builders/build-decorators'; -import { NormalizedObjectBuildService } from '../cache/builders/normalized-object-build.service'; import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; import { ObjectCacheService } from '../cache/object-cache.service'; import { CoreState } from '../core.reducers'; @@ -25,7 +24,6 @@ class DataServiceImpl extends DataService { constructor( protected requestService: RequestService, protected rdbService: RemoteDataBuildService, - protected dataBuildService: NormalizedObjectBuildService, protected store: Store, protected objectCache: ObjectCacheService, protected halService: HALEndpointService, @@ -44,14 +42,13 @@ export class LicenseDataService { constructor( protected requestService: RequestService, protected rdbService: RemoteDataBuildService, - protected dataBuildService: NormalizedObjectBuildService, protected store: Store, protected objectCache: ObjectCacheService, protected halService: HALEndpointService, protected notificationsService: NotificationsService, protected http: HttpClient, protected comparator: DefaultChangeAnalyzer) { - this.dataService = new DataServiceImpl(requestService, rdbService, dataBuildService, null, objectCache, halService, notificationsService, http, comparator); + this.dataService = new DataServiceImpl(requestService, rdbService, null, objectCache, halService, notificationsService, http, comparator); } findByHref(href: string, ...linksToFollow: Array>): Observable> { diff --git a/src/app/core/data/metadata-schema-data.service.ts b/src/app/core/data/metadata-schema-data.service.ts index a11d378065..915f588379 100644 --- a/src/app/core/data/metadata-schema-data.service.ts +++ b/src/app/core/data/metadata-schema-data.service.ts @@ -3,7 +3,6 @@ import { Injectable } from '@angular/core'; import { Store } from '@ngrx/store'; import { NotificationsService } from '../../shared/notifications/notifications.service'; import { dataService } from '../cache/builders/build-decorators'; -import { NormalizedObjectBuildService } from '../cache/builders/normalized-object-build.service'; import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; import { ObjectCacheService } from '../cache/object-cache.service'; import { CoreState } from '../core.reducers'; @@ -23,7 +22,6 @@ class DataServiceImpl extends DataService { constructor( protected requestService: RequestService, protected rdbService: RemoteDataBuildService, - protected dataBuildService: NormalizedObjectBuildService, protected store: Store, protected objectCache: ObjectCacheService, protected halService: HALEndpointService, @@ -50,9 +48,8 @@ export class MetadataSchemaDataService { protected halService: HALEndpointService, protected objectCache: ObjectCacheService, protected comparator: DefaultChangeAnalyzer, - protected dataBuildService: NormalizedObjectBuildService, protected http: HttpClient, protected notificationsService: NotificationsService) { - this.dataService = new DataServiceImpl(requestService, rdbService, dataBuildService, null, objectCache, halService, notificationsService, http, comparator); + this.dataService = new DataServiceImpl(requestService, rdbService, null, objectCache, halService, notificationsService, http, comparator); } } diff --git a/src/app/core/data/mydspace-response-parsing.service.ts b/src/app/core/data/mydspace-response-parsing.service.ts index cbaf28d34b..062bafab46 100644 --- a/src/app/core/data/mydspace-response-parsing.service.ts +++ b/src/app/core/data/mydspace-response-parsing.service.ts @@ -1,10 +1,10 @@ import { Injectable } from '@angular/core'; import { RestResponse, SearchSuccessResponse } from '../cache/response.models'; +import { DSpaceSerializer } from '../dspace-rest-v2/dspace.serializer'; import { DSOResponseParsingService } from './dso-response-parsing.service'; import { ResponseParsingService } from './parsing.service'; import { RestRequest } from './request.models'; import { DSpaceRESTV2Response } from '../dspace-rest-v2/dspace-rest-v2-response.model'; -import { NormalizedObjectSerializer } from '../dspace-rest-v2/normalized-object.serializer'; import { hasValue } from '../../shared/empty.util'; import { SearchQueryResponse } from '../../shared/search/search-query-response.model'; import { MetadataMap, MetadataValue } from '../shared/metadata.models'; @@ -57,7 +57,7 @@ export class MyDSpaceResponseParsingService implements ResponseParsingService { _embedded: this.filterEmbeddedObjects(object) })); payload.objects = objects; - const deserialized = new NormalizedObjectSerializer(SearchQueryResponse).deserialize(payload); + const deserialized = new DSpaceSerializer(SearchQueryResponse).deserialize(payload); return new SearchSuccessResponse(deserialized, data.statusCode, data.statusText, this.dsoParser.processPageInfo(payload)); } diff --git a/src/app/core/data/relationship-type.service.ts b/src/app/core/data/relationship-type.service.ts index 017bf7bf91..eefe663209 100644 --- a/src/app/core/data/relationship-type.service.ts +++ b/src/app/core/data/relationship-type.service.ts @@ -9,7 +9,6 @@ import { isNotUndefined } from '../../shared/empty.util'; import { NotificationsService } from '../../shared/notifications/notifications.service'; import { followLink } from '../../shared/utils/follow-link-config.model'; import { dataService } from '../cache/builders/build-decorators'; -import { NormalizedObjectBuildService } from '../cache/builders/normalized-object-build.service'; import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; import { ObjectCacheService } from '../cache/object-cache.service'; import { CoreState } from '../core.reducers'; @@ -37,7 +36,6 @@ export class RelationshipTypeService extends DataService { constructor(protected itemService: ItemDataService, protected requestService: RequestService, protected rdbService: RemoteDataBuildService, - protected dataBuildService: NormalizedObjectBuildService, protected store: Store, protected halService: HALEndpointService, protected objectCache: ObjectCacheService, diff --git a/src/app/core/data/relationship.service.ts b/src/app/core/data/relationship.service.ts index 7fe7b23c9c..7df56252de 100644 --- a/src/app/core/data/relationship.service.ts +++ b/src/app/core/data/relationship.service.ts @@ -20,7 +20,6 @@ import { NameVariantListState } from '../../shared/form/builder/ds-dynamic-form- import { NotificationsService } from '../../shared/notifications/notifications.service'; import { followLink, FollowLinkConfig } from '../../shared/utils/follow-link-config.model'; import { dataService } from '../cache/builders/build-decorators'; -import { NormalizedObjectBuildService } from '../cache/builders/normalized-object-build.service'; import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; import { SearchParam } from '../cache/models/search-param.model'; import { ObjectCacheService } from '../cache/object-cache.service'; @@ -67,7 +66,6 @@ export class RelationshipService extends DataService { constructor(protected itemService: ItemDataService, protected requestService: RequestService, protected rdbService: RemoteDataBuildService, - protected dataBuildService: NormalizedObjectBuildService, protected store: Store, protected halService: HALEndpointService, protected objectCache: ObjectCacheService, diff --git a/src/app/core/data/request.effects.ts b/src/app/core/data/request.effects.ts index 76e6a188e2..a9052aa8dc 100644 --- a/src/app/core/data/request.effects.ts +++ b/src/app/core/data/request.effects.ts @@ -6,7 +6,7 @@ import { catchError, filter, flatMap, map, take } from 'rxjs/operators'; import { GLOBAL_CONFIG, GlobalConfig } from '../../../config'; import { hasValue, isNotEmpty } from '../../shared/empty.util'; import { StoreActionTypes } from '../../store.actions'; -import { getMapsToType } from '../cache/builders/build-decorators'; +import { getClassForType } from '../cache/builders/build-decorators'; import { ErrorResponse, RestResponse } from '../cache/response.models'; import { DSpaceRESTV2Response } from '../dspace-rest-v2/dspace-rest-v2-response.model'; @@ -45,7 +45,7 @@ export class RequestEffects { flatMap((request: RestRequest) => { let body; if (isNotEmpty(request.body)) { - const serializer = new DSpaceSerializer(getMapsToType(request.body.type)); + const serializer = new DSpaceSerializer(getClassForType(request.body.type)); body = serializer.serialize(request.body); } return this.restApi.request(request.method, request.href, body, request.options).pipe( diff --git a/src/app/core/data/resource-policy.service.spec.ts b/src/app/core/data/resource-policy.service.spec.ts index 971d62b2dd..abed805ca3 100644 --- a/src/app/core/data/resource-policy.service.spec.ts +++ b/src/app/core/data/resource-policy.service.spec.ts @@ -2,12 +2,10 @@ import { HttpClient } from '@angular/common/http'; import { cold, getTestScheduler } from 'jasmine-marbles'; import { TestScheduler } from 'rxjs/testing'; import { NotificationsService } from '../../shared/notifications/notifications.service'; -import { NormalizedObjectBuildService } from '../cache/builders/normalized-object-build.service'; import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; import { ObjectCacheService } from '../cache/object-cache.service'; import { HALEndpointService } from '../shared/hal-endpoint.service'; import { ResourcePolicy } from '../shared/resource-policy.model'; -import { GetRequest } from './request.models'; import { RequestService } from './request.service'; import { ResourcePolicyService } from './resource-policy.service'; @@ -42,12 +40,10 @@ describe('ResourcePolicyService', () => { const notificationsService = {} as NotificationsService; const http = {} as HttpClient; const comparator = {} as any; - const dataBuildService = {} as NormalizedObjectBuildService; service = new ResourcePolicyService( requestService, rdbService, - dataBuildService, objectCache, halService, notificationsService, diff --git a/src/app/core/data/resource-policy.service.ts b/src/app/core/data/resource-policy.service.ts index acfc013f0d..9401168984 100644 --- a/src/app/core/data/resource-policy.service.ts +++ b/src/app/core/data/resource-policy.service.ts @@ -17,7 +17,6 @@ import { RemoteDataBuildService } from '../cache/builders/remote-data-build.serv import { CoreState } from '../core.reducers'; import { ObjectCacheService } from '../cache/object-cache.service'; import { NotificationsService } from '../../shared/notifications/notifications.service'; -import { NormalizedObjectBuildService } from '../cache/builders/normalized-object-build.service'; import { RESOURCE_POLICY } from '../shared/resource-policy.resource-type'; import { ChangeAnalyzer } from './change-analyzer'; import { DefaultChangeAnalyzer } from '../data/default-change-analyzer.service'; @@ -30,7 +29,6 @@ class DataServiceImpl extends DataService { constructor( protected requestService: RequestService, protected rdbService: RemoteDataBuildService, - protected dataBuildService: NormalizedObjectBuildService, protected store: Store, protected objectCache: ObjectCacheService, protected halService: HALEndpointService, @@ -53,13 +51,12 @@ export class ResourcePolicyService { constructor( protected requestService: RequestService, protected rdbService: RemoteDataBuildService, - protected dataBuildService: NormalizedObjectBuildService, protected objectCache: ObjectCacheService, protected halService: HALEndpointService, protected notificationsService: NotificationsService, protected http: HttpClient, protected comparator: DefaultChangeAnalyzer) { - this.dataService = new DataServiceImpl(requestService, rdbService, dataBuildService, null, objectCache, halService, notificationsService, http, comparator); + this.dataService = new DataServiceImpl(requestService, rdbService, null, objectCache, halService, notificationsService, http, comparator); } findByHref(href: string, ...linksToFollow: Array>): Observable> { diff --git a/src/app/core/data/site-data.service.spec.ts b/src/app/core/data/site-data.service.spec.ts index 6148135f50..6938cd65a9 100644 --- a/src/app/core/data/site-data.service.spec.ts +++ b/src/app/core/data/site-data.service.spec.ts @@ -8,7 +8,6 @@ import { Store } from '@ngrx/store'; import { CoreState } from '../core.reducers'; import { NotificationsService } from '../../shared/notifications/notifications.service'; import { HttpClient } from '@angular/common/http'; -import { NormalizedObjectBuildService } from '../cache/builders/normalized-object-build.service'; import { HALEndpointService } from '../shared/hal-endpoint.service'; import { of as observableOf } from 'rxjs'; import { RestResponse } from '../cache/response.models'; @@ -63,12 +62,10 @@ describe('SiteDataService', () => { const notificationsService = {} as NotificationsService; const http = {} as HttpClient; const comparator = {} as any; - const dataBuildService = {} as NormalizedObjectBuildService; service = new SiteDataService( requestService, rdbService, - dataBuildService, store, objectCache, halService, diff --git a/src/app/core/data/site-data.service.ts b/src/app/core/data/site-data.service.ts index 20b9e5e6e0..7b2bfdb543 100644 --- a/src/app/core/data/site-data.service.ts +++ b/src/app/core/data/site-data.service.ts @@ -5,7 +5,6 @@ import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; import { NotificationsService } from '../../shared/notifications/notifications.service'; import { dataService } from '../cache/builders/build-decorators'; -import { NormalizedObjectBuildService } from '../cache/builders/normalized-object-build.service'; import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; import { ObjectCacheService } from '../cache/object-cache.service'; import { CoreState } from '../core.reducers'; @@ -30,7 +29,6 @@ export class SiteDataService extends DataService {​ constructor( protected requestService: RequestService, protected rdbService: RemoteDataBuildService, - protected dataBuildService: NormalizedObjectBuildService, protected store: Store, protected objectCache: ObjectCacheService, protected halService: HALEndpointService, diff --git a/src/app/core/dspace-rest-v2/dspace.serializer.spec.ts b/src/app/core/dspace-rest-v2/dspace.serializer.spec.ts new file mode 100644 index 0000000000..36af99e073 --- /dev/null +++ b/src/app/core/dspace-rest-v2/dspace.serializer.spec.ts @@ -0,0 +1,154 @@ +import { autoserialize, autoserializeAs, deserialize } from 'cerialize'; +import { HALLink } from '../shared/hal-link.model'; +import { HALResource } from '../shared/hal-resource.model'; +import { DSpaceSerializer } from './dspace.serializer'; + +class TestModel implements HALResource { + @autoserialize + id: string; + + @autoserialize + name: string; + + @deserialize + _links: { + self: HALLink; + parents: HALLink; + } +} + +const testModels = [ + { + id: 'd4466d54-d73b-4d8f-b73f-c702020baa14', + name: 'Model 1', + _links: { + self: { + href: '/testmodels/9e32a2e2-6b91-4236-a361-995ccdc14c60' + }, + parents: { + href: '/testmodels/9e32a2e2-6b91-4236-a361-995ccdc14c60/parents' + } + } + }, + { + id: '752a1250-949a-46ad-9bea-fbc45f0b656d', + name: 'Model 2', + _links: { + self: { + href: '/testmodels/598ce822-c357-46f3-ab70-63724d02d6ad' + }, + parents: { + href: '/testmodels/598ce822-c357-46f3-ab70-63724d02d6ad/parents' + } + } + } +]; + +const testResponses = [ + { + _links: { + self: { + href: '/testmodels/9e32a2e2-6b91-4236-a361-995ccdc14c60' + }, + parents: { + href: '/testmodels/9e32a2e2-6b91-4236-a361-995ccdc14c60/parents' + } + }, + id: '9e32a2e2-6b91-4236-a361-995ccdc14c60', + type: 'testModels', + name: 'A Test Model' + }, + { + _links: { + self: { + href: '/testmodels/598ce822-c357-46f3-ab70-63724d02d6ad' + }, + parents: { + href: '/testmodels/598ce822-c357-46f3-ab70-63724d02d6ad/parents' + } + }, + id: '598ce822-c357-46f3-ab70-63724d02d6ad', + type: 'testModels', + name: 'Another Test Model' + } +]; + +describe('DSpaceSerializer', () => { + + describe('serialize', () => { + + it('should turn a model in to a valid document', () => { + const serializer = new DSpaceSerializer(TestModel); + const doc = serializer.serialize(testModels[0]); + expect(testModels[0].id).toBe(doc.id); + expect(testModels[0].name).toBe(doc.name); + expect(testModels[0]._links).toBeUndefined(); + }); + + }); + + describe('serializeArray', () => { + + it('should turn an array of models in to a valid document', () => { + const serializer = new DSpaceSerializer(TestModel); + const doc = serializer.serializeArray(testModels); + + expect(testModels[0].id).toBe(doc[0].id); + expect(testModels[0].name).toBe(doc[0].name); + expect(testModels[0]._links).toBeUndefined(); + expect(testModels[1].id).toBe(doc[1].id); + expect(testModels[1].name).toBe(doc[1].name); + expect(testModels[1]._links).toBeUndefined(); + }); + + }); + + describe('deserialize', () => { + + it('should turn a valid document describing a single entity in to a valid model', () => { + const serializer = new DSpaceSerializer(TestModel); + const model = serializer.deserialize(testResponses[0]); + + expect(model.id).toBe(testResponses[0].id); + expect(model.name).toBe(testResponses[0].name); + }); + + it('should throw an error when dealing with a document describing an array', () => { + const serializer = new DSpaceSerializer(TestModel); + expect(() => { + serializer.deserialize(testResponses); + }).toThrow(); + }); + + }); + + describe('deserializeArray', () => { + + it('should throw an error when dealing with a document describing a single model', () => { + const serializer = new DSpaceSerializer(TestModel); + const doc = { + _embedded: testResponses[0] + }; + + expect(() => { + serializer.deserializeArray(doc); + }).toThrow(); + }); + + it('should turn an array of responses in to valid models', () => { + const serializer = new DSpaceSerializer(TestModel); + const output = serializer.deserializeArray(testResponses); + + expect(testResponses[0].id).toBe(output[0].id); + expect(testResponses[0].name).toBe(output[0].name); + expect(testResponses[0]._links.self.href).toBe(output[0]._links.self.href); + expect(testResponses[0]._links.parents.href).toBe(output[0]._links.parents.href); + expect(testResponses[1].id).toBe(output[1].id); + expect(testResponses[1].name).toBe(output[1].name); + expect(testResponses[1]._links.self.href).toBe(output[1]._links.self.href); + expect(testResponses[1]._links.parents.href).toBe(output[1]._links.parents.href); + }); + + }); + +}); diff --git a/src/app/core/dspace-rest-v2/normalized-object.serializer.spec.ts b/src/app/core/dspace-rest-v2/normalized-object.serializer.spec.ts deleted file mode 100644 index ab9ac0795f..0000000000 --- a/src/app/core/dspace-rest-v2/normalized-object.serializer.spec.ts +++ /dev/null @@ -1,194 +0,0 @@ -import { autoserialize, autoserializeAs } from 'cerialize'; - -import { NormalizedObjectSerializer } from './normalized-object.serializer'; - -class TestModel { - @autoserialize - id: string; - - @autoserialize - name: string; - - @autoserializeAs(TestModel) - parents?: TestModel[]; -} - -const testModels = [ - { - id: 'd4466d54-d73b-4d8f-b73f-c702020baa14', - name: 'Model 1', - }, - { - id: '752a1250-949a-46ad-9bea-fbc45f0b656d', - name: 'Model 2', - } -]; - -const testResponses = [ - { - _links: { - self: '/testmodels/9e32a2e2-6b91-4236-a361-995ccdc14c60', - parents: [ - { href: '/testmodels/21539b1d-9ef1-4eda-9c77-49565b5bfb78' }, - { href: '/testmodels/be8325f7-243b-49f4-8a4b-df2b793ff3b5' } - ] - }, - id: '9e32a2e2-6b91-4236-a361-995ccdc14c60', - type: 'testModels', - name: 'A Test Model' - }, - { - _links: { - self: '/testmodels/598ce822-c357-46f3-ab70-63724d02d6ad', - parents: [ - { href: '/testmodels/be8325f7-243b-49f4-8a4b-df2b793ff3b5' }, - { href: '/testmodels/21539b1d-9ef1-4eda-9c77-49565b5bfb78' } - ] - }, - id: '598ce822-c357-46f3-ab70-63724d02d6ad', - type: 'testModels', - name: 'Another Test Model' - } -]; - -const parentHrefRegex = /^\/testmodels\/(.+)$/g; - -describe('NormalizedObjectSerializer', () => { - - describe('serialize', () => { - - it('should turn a model in to a valid document', () => { - const serializer = new NormalizedObjectSerializer(TestModel); - const doc = serializer.serialize(testModels[0]); - expect(testModels[0].id).toBe(doc.id); - expect(testModels[0].name).toBe(doc.name); - }); - - }); - - describe('serializeArray', () => { - - it('should turn an array of models in to a valid document', () => { - const serializer = new NormalizedObjectSerializer(TestModel); - const doc = serializer.serializeArray(testModels); - - expect(testModels[0].id).toBe(doc[0].id); - expect(testModels[0].name).toBe(doc[0].name); - expect(testModels[1].id).toBe(doc[1].id); - expect(testModels[1].name).toBe(doc[1].name); - }); - - }); - - describe('deserialize', () => { - - it('should turn a valid document describing a single entity in to a valid model', () => { - const serializer = new NormalizedObjectSerializer(TestModel); - const model = serializer.deserialize(testResponses[0]); - - expect(model.id).toBe(testResponses[0].id); - expect(model.name).toBe(testResponses[0].name); - }); - - // TODO: cant implement/test this yet - depends on how relationships - // will be handled in the rest api - // it('should retain relationship information', () => { - // const serializer = new NormalizedObjectSerializer(TestModel); - // const doc = { - // '_embedded': testResponses[0], - // }; - // - // const model = serializer.deserialize(doc); - // - // console.log(model); - // - // const modelParentIds = model.parents.map(parent => parent.id).sort(); - // const responseParentIds = doc._embedded._links.parents - // .map(parent => parent.href) - // .map(href => href.replace(parentHrefRegex, '$1')) - // .sort(); - // - // expect(modelParentIds).toEqual(responseParentIds); - // }); - - // TODO enable once validation is enabled in the serializer - // it('should throw an error when dealing with an invalid document', () => { - // const serializer = new NormalizedObjectSerializer(TestModel); - // const doc = testResponses[0]; - // - // expect(() => { - // serializer.deserialize(doc); - // }).toThrow(); - // }); - - it('should throw an error when dealing with a document describing an array', () => { - const serializer = new NormalizedObjectSerializer(TestModel); - expect(() => { - serializer.deserialize(testResponses); - }).toThrow(); - }); - - }); - - describe('deserializeArray', () => { - - // TODO: rewrite to incorporate normalisation. - // it('should turn a valid document describing a collection of objects in to an array of valid models', () => { - // const serializer = new NormalizedObjectSerializer(TestModel); - // const doc = { - // '_embedded': testResponses - // }; - // - // const models = serializer.deserializeArray(doc); - // - // expect(models[0].id).toBe(doc._embedded[0].id); - // expect(models[0].name).toBe(doc._embedded[0].name); - // expect(models[1].id).toBe(doc._embedded[1].id); - // expect(models[1].name).toBe(doc._embedded[1].name); - // }); - - // TODO: cant implement/test this yet - depends on how relationships - // will be handled in the rest api - // it('should retain relationship information', () => { - // const serializer = new NormalizedObjectSerializer(TestModel); - // const doc = { - // '_embedded': testResponses, - // }; - // - // const models = serializer.deserializeArray(doc); - // - // models.forEach((model, i) => { - // const modelParentIds = model.parents.map(parent => parent.id).sort(); - // const responseParentIds = doc._embedded[i]._links.parents - // .map(parent => parent.href) - // .map(href => href.replace(parentHrefRegex, '$1')) - // .sort(); - // - // expect(modelParentIds).toEqual(responseParentIds); - // }); - // }); - - // TODO enable once validation is enabled in the serializer - // it('should throw an error when dealing with an invalid document', () => { - // const serializer = new NormalizedObjectSerializer(TestModel); - // const doc = testResponses[0]; - // - // expect(() => { - // serializer.deserializeArray(doc); - // }).toThrow(); - // }); - - it('should throw an error when dealing with a document describing a single model', () => { - const serializer = new NormalizedObjectSerializer(TestModel); - const doc = { - _embedded: testResponses[0] - }; - - expect(() => { - serializer.deserializeArray(doc); - }).toThrow(); - }); - - }); - -}); diff --git a/src/app/core/dspace-rest-v2/normalized-object.serializer.ts b/src/app/core/dspace-rest-v2/normalized-object.serializer.ts deleted file mode 100644 index d7c3332fa9..0000000000 --- a/src/app/core/dspace-rest-v2/normalized-object.serializer.ts +++ /dev/null @@ -1,95 +0,0 @@ -import { Deserialize, Serialize } from 'cerialize'; -import { deprecate } from 'util'; - -import { Serializer } from '../serializer'; -import { GenericConstructor } from '../shared/generic-constructor'; - -/** - * This Serializer turns responses from v2 of DSpace's REST API - * to normalized models and vice versa - * - * @deprecated use DSpaceSerializer instead - */ -export class NormalizedObjectSerializer implements Serializer { - - /** - * Create a new NormalizedObjectSerializer instance - * - * @param modelType a class or interface to indicate - * the kind of model this serializer should work with - */ - constructor(private modelType: GenericConstructor) { - } - - /** - * Convert a model in to the format expected by the backend - * - * @param model The model to serialize - * @returns An object to send to the backend - */ - serialize(model: T): any { - return Serialize(model, this.modelType); - } - - /** - * Convert an array of models in to the format expected by the backend - * - * @param models The array of models to serialize - * @returns An object to send to the backend - */ - serializeArray(models: T[]): any { - return Serialize(models, this.modelType); - } - - /** - * Convert a response from the backend in to a model. - * - * @param response An object returned by the backend - * @returns a model of type T - */ - deserialize(response: any): T { - // TODO enable validation, once rest data stabilizes - // new DSpaceRESTv2Validator(response).validate(); - if (Array.isArray(response)) { - throw new Error('Expected a single model, use deserializeArray() instead'); - } - const normalized = Object.assign({}, response, this.normalizeLinks(response._links)); - return Deserialize(normalized, this.modelType) as T; - } - - /** - * Convert a response from the backend in to an array of models - * - * @param response An object returned by the backend - * @returns an array of models of type T - */ - deserializeArray(response: any): T[] { - // TODO: enable validation, once rest data stabilizes - // new DSpaceRESTv2Validator(response).validate(); - if (!Array.isArray(response)) { - throw new Error('Expected an Array, use deserialize() instead'); - } - const normalized = response.map((resource) => { - return Object.assign({}, resource, this.normalizeLinks(resource._links)); - }); - - return Deserialize(normalized, this.modelType) as T[]; - } - - private normalizeLinks(links: any): any { - const normalizedLinks = {}; - for (const link in links) { - if (links.hasOwnProperty(link)) { - if (Array.isArray(links[link])) { - normalizedLinks[link] = links[link].map((linkedResource) => { - return linkedResource.href; - }); - } else { - normalizedLinks[link] = links[link].href; - } - } - } - return normalizedLinks; - } - -} diff --git a/src/app/core/eperson/eperson-data.service.ts b/src/app/core/eperson/eperson-data.service.ts index 61e47d1a77..2c1a27f4e5 100644 --- a/src/app/core/eperson/eperson-data.service.ts +++ b/src/app/core/eperson/eperson-data.service.ts @@ -3,7 +3,6 @@ import { Injectable } from '@angular/core'; import { Store } from '@ngrx/store'; import { NotificationsService } from '../../shared/notifications/notifications.service'; import { dataService } from '../cache/builders/build-decorators'; -import { NormalizedObjectBuildService } from '../cache/builders/normalized-object-build.service'; import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; import { ObjectCacheService } from '../cache/object-cache.service'; import { CoreState } from '../core.reducers'; @@ -23,7 +22,6 @@ export class EPersonDataService extends DataService { constructor( protected requestService: RequestService, protected rdbService: RemoteDataBuildService, - protected dataBuildService: NormalizedObjectBuildService, protected store: Store, protected objectCache: ObjectCacheService, protected halService: HALEndpointService, diff --git a/src/app/core/eperson/group-data.service.ts b/src/app/core/eperson/group-data.service.ts index 5bee9c8171..1372efb9d6 100644 --- a/src/app/core/eperson/group-data.service.ts +++ b/src/app/core/eperson/group-data.service.ts @@ -6,7 +6,6 @@ import { Observable } from 'rxjs'; import { filter, map, take } from 'rxjs/operators'; import { DataService } from '../data/data.service'; -import { EPersonDataService } from './eperson-data.service'; import { RequestService } from '../data/request.service'; import { FindListOptions } from '../data/request.models'; import { HALEndpointService } from '../shared/hal-endpoint.service'; @@ -18,7 +17,6 @@ import { SearchParam } from '../cache/models/search-param.model'; import { RemoteData } from '../data/remote-data'; import { PaginatedList } from '../data/paginated-list'; import { NotificationsService } from '../../shared/notifications/notifications.service'; -import { NormalizedObjectBuildService } from '../cache/builders/normalized-object-build.service'; import { DSOChangeAnalyzer } from '../data/dso-change-analyzer.service'; /** @@ -33,7 +31,6 @@ export class GroupDataService extends DataService { constructor( protected comparator: DSOChangeAnalyzer, - protected dataBuildService: NormalizedObjectBuildService, protected http: HttpClient, protected notificationsService: NotificationsService, protected requestService: RequestService, diff --git a/src/app/core/integration/models/authority.value.ts b/src/app/core/integration/models/authority.value.ts index 59301cadca..55e0fba99d 100644 --- a/src/app/core/integration/models/authority.value.ts +++ b/src/app/core/integration/models/authority.value.ts @@ -46,6 +46,9 @@ export class AuthorityValue extends IntegrationModel implements MetadataValueInt @autoserialize language: string; + /** + * The HALLinks for this AuthorityValue + */ @deserialize _links: { self: HALLink, diff --git a/src/app/core/metadata/metadata.service.spec.ts b/src/app/core/metadata/metadata.service.spec.ts index fea45b96c0..e3f6c3401c 100644 --- a/src/app/core/metadata/metadata.service.spec.ts +++ b/src/app/core/metadata/metadata.service.spec.ts @@ -31,7 +31,6 @@ import { createSuccessfulRemoteDataObject$ } from '../../shared/testing/utils'; import { FollowLinkConfig } from '../../shared/utils/follow-link-config.model'; import { AuthService } from '../auth/auth.service'; import { BrowseService } from '../browse/browse.service'; -import { NormalizedObjectBuildService } from '../cache/builders/normalized-object-build.service'; import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; import { ObjectCacheService } from '../cache/object-cache.service'; @@ -166,7 +165,6 @@ describe('MetadataService', () => { { provide: AuthService, useValue: {} }, { provide: NotificationsService, useValue: {} }, { provide: HttpClient, useValue: {} }, - { provide: NormalizedObjectBuildService, useValue: {} }, { provide: DSOChangeAnalyzer, useValue: {} }, { provide: CommunityDataService, useValue: {} }, { provide: DefaultChangeAnalyzer, useValue: {} }, diff --git a/src/app/core/registry/registry-bitstreamformats-response.model.ts b/src/app/core/registry/registry-bitstreamformats-response.model.ts index ddf926f3be..0e346db03d 100644 --- a/src/app/core/registry/registry-bitstreamformats-response.model.ts +++ b/src/app/core/registry/registry-bitstreamformats-response.model.ts @@ -1,16 +1,24 @@ import { autoserialize, deserialize } from 'cerialize'; +import { BITSTREAM_FORMAT } from '../shared/bitstream-format.resource-type'; +import { HALLink } from '../shared/hal-link.model'; import { PageInfo } from '../shared/page-info.model'; import { BitstreamFormat } from '../shared/bitstream-format.model'; -import { relationship } from '../cache/builders/build-decorators'; +import { link } from '../cache/builders/build-decorators'; export class RegistryBitstreamformatsResponse { - @deserialize - @relationship(BitstreamFormat, true) - bitstreamformats: BitstreamFormat[]; - @autoserialize page: PageInfo; - @autoserialize - self: string; + /** + * The HALLinks for this RegistryBitstreamformatsResponse + */ + @deserialize + _links: { + self: HALLink; + bitstreamformats: HALLink; + }; + + @link(BITSTREAM_FORMAT) + bitstreamformats?: BitstreamFormat[]; + } diff --git a/src/app/core/registry/registry-metadatafields-response.model.ts b/src/app/core/registry/registry-metadatafields-response.model.ts index e9c41b7841..2bdaade0b7 100644 --- a/src/app/core/registry/registry-metadatafields-response.model.ts +++ b/src/app/core/registry/registry-metadatafields-response.model.ts @@ -1,5 +1,5 @@ import { autoserialize, deserialize } from 'cerialize'; -import { relationship, resourceType } from '../cache/builders/build-decorators'; +import { resourceType } from '../cache/builders/build-decorators'; import { MetadataField } from '../metadata/metadata-field.model'; import { METADATA_FIELD } from '../metadata/metadata-field.resource-type'; import { HALLink } from '../shared/hal-link.model'; @@ -25,7 +25,6 @@ export class RegistryMetadatafieldsResponse { * List of metadata fields in the response */ @deserialize - @relationship(MetadataField, true) metadatafields: MetadataField[]; /** @@ -40,8 +39,8 @@ export class RegistryMetadatafieldsResponse { @autoserialize self: string; + @deserialize _links: { self: HALLink, - schema: HALLink } } diff --git a/src/app/core/registry/registry-metadataschemas-response.model.ts b/src/app/core/registry/registry-metadataschemas-response.model.ts index fc53b354a5..7a485d8849 100644 --- a/src/app/core/registry/registry-metadataschemas-response.model.ts +++ b/src/app/core/registry/registry-metadataschemas-response.model.ts @@ -1,11 +1,9 @@ import { PageInfo } from '../shared/page-info.model'; import { autoserialize, deserialize } from 'cerialize'; import { MetadataSchema } from '../metadata/metadata-schema.model'; -import { relationship } from '../cache/builders/build-decorators'; export class RegistryMetadataschemasResponse { @deserialize - @relationship(MetadataSchema, true) metadataschemas: MetadataSchema[]; @autoserialize diff --git a/src/app/core/registry/registry.service.ts b/src/app/core/registry/registry.service.ts index 7d38365c2e..fbc42b26f4 100644 --- a/src/app/core/registry/registry.service.ts +++ b/src/app/core/registry/registry.service.ts @@ -56,7 +56,7 @@ import { HttpHeaders } from '@angular/common/http'; import { TranslateService } from '@ngx-translate/core'; import { MetadataSchema } from '../metadata/metadata-schema.model'; import { MetadataField } from '../metadata/metadata-field.model'; -import { getMapsToType } from '../cache/builders/build-decorators'; +import { getClassForType } from '../cache/builders/build-decorators'; const metadataRegistryStateSelector = (state: AppState) => state.metadataRegistry; const editMetadataSchemaSelector = createSelector(metadataRegistryStateSelector, (metadataState: MetadataRegistryState) => metadataState.editSchema); @@ -399,7 +399,7 @@ export class RegistryService { distinctUntilChanged() ); - const serializedSchema = new DSpaceSerializer(getMapsToType(MetadataSchema.type)).serialize(schema); + const serializedSchema = new DSpaceSerializer(getClassForType(MetadataSchema.type)).serialize(schema); const request$ = endpoint$.pipe( take(1), diff --git a/src/app/core/shared/browse-entry.model.ts b/src/app/core/shared/browse-entry.model.ts index 0ce9e8b9bd..a5e444ae5a 100644 --- a/src/app/core/shared/browse-entry.model.ts +++ b/src/app/core/shared/browse-entry.model.ts @@ -10,7 +10,6 @@ import { ResourceType } from './resource-type'; /** * Class object representing a browse entry - * This class is not normalized because browse entries do not have self links */ @resourceType(BrowseEntry.type) export class BrowseEntry extends ListableObject implements TypedObject { diff --git a/src/app/core/shared/external-source-entry.model.ts b/src/app/core/shared/external-source-entry.model.ts index 1e37904573..cfab5f93d6 100644 --- a/src/app/core/shared/external-source-entry.model.ts +++ b/src/app/core/shared/external-source-entry.model.ts @@ -52,6 +52,9 @@ export class ExternalSourceEntry extends ListableObject { @autoserializeAs(MetadataMapSerializer) metadata: MetadataMap; + /** + * The HALLinks for this ExternalSourceEntry + */ @deserialize _links: { self: HALLink; diff --git a/src/app/core/shared/external-source.model.ts b/src/app/core/shared/external-source.model.ts index afb6e48818..f83d7a82db 100644 --- a/src/app/core/shared/external-source.model.ts +++ b/src/app/core/shared/external-source.model.ts @@ -38,6 +38,9 @@ export class ExternalSource extends CacheableObject { @autoserialize hierarchical: boolean; + /** + * The HALLinks for this ExternalSource + */ @deserialize _links: { self: HALLink; diff --git a/src/app/core/shared/item-relationships/item-type.model.ts b/src/app/core/shared/item-relationships/item-type.model.ts index e379544c49..e63c01ea8e 100644 --- a/src/app/core/shared/item-relationships/item-type.model.ts +++ b/src/app/core/shared/item-relationships/item-type.model.ts @@ -38,6 +38,9 @@ export class ItemType implements CacheableObject { @deserializeAs(new IDToUUIDSerializer(ItemType.type.value), 'id') uuid: string; + /** + * The HALLinks for this ItemType + */ @deserialize _links: { self: HALLink, diff --git a/src/app/core/shared/resource-policy.model.ts b/src/app/core/shared/resource-policy.model.ts index 4ee8ad0e43..29dc90d6a5 100644 --- a/src/app/core/shared/resource-policy.model.ts +++ b/src/app/core/shared/resource-policy.model.ts @@ -48,6 +48,9 @@ export class ResourcePolicy implements CacheableObject { @deserializeAs(new IDToUUIDSerializer('resource-policy'), 'id') uuid: string; + /** + * The HALLinks for this ResourcePolicy + */ @deserialize _links: { self: HALLink, diff --git a/src/app/core/submission/models/normalized-submission-object.model.ts b/src/app/core/submission/models/normalized-submission-object.model.ts deleted file mode 100644 index f674ebdf72..0000000000 --- a/src/app/core/submission/models/normalized-submission-object.model.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { autoserialize, autoserializeAs, inheritSerialization } from 'cerialize'; - -import { NormalizedDSpaceObject } from '../../cache/models/normalized-dspace-object.model'; -import { WorkspaceitemSectionsObject } from './workspaceitem-sections.model'; -import { SubmissionObjectError } from './submission-object.model'; -import { DSpaceObject } from '../../shared/dspace-object.model'; - -/** - * An abstract model class for a NormalizedSubmissionObject. - */ -@inheritSerialization(NormalizedDSpaceObject) -export class NormalizedSubmissionObject extends NormalizedDSpaceObject { - - /** - * The workspaceitem/workflowitem identifier - */ - @autoserialize - id: string; - - /** - * The workspaceitem/workflowitem identifier - */ - @autoserializeAs(String, 'id') - uuid: string; - - /** - * The workspaceitem/workflowitem last modified date - */ - @autoserialize - lastModified: Date; - - /** - * The workspaceitem/workflowitem last sections data - */ - @autoserialize - sections: WorkspaceitemSectionsObject; - - /** - * The workspaceitem/workflowitem last sections errors - */ - @autoserialize - errors: SubmissionObjectError[]; -} diff --git a/src/app/core/submission/models/normalized-workflowitem.model.ts b/src/app/core/submission/models/normalized-workflowitem.model.ts deleted file mode 100644 index 54ee199f34..0000000000 --- a/src/app/core/submission/models/normalized-workflowitem.model.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { autoserialize, inheritSerialization } from 'cerialize'; - -import { relationship } from '../../cache/builders/build-decorators'; -import { WorkflowItem } from './workflowitem.model'; -import { NormalizedSubmissionObject } from './normalized-submission-object.model'; -import { Collection } from '../../shared/collection.model'; -import { Item } from '../../shared/item.model'; -import { SubmissionDefinitionsModel } from '../../config/models/config-submission-definitions.model'; -import { EPerson } from '../../eperson/models/eperson.model'; - -/** - * An model class for a NormalizedWorkflowItem. - */ -@inheritSerialization(NormalizedSubmissionObject) -export class NormalizedWorkflowItem extends NormalizedSubmissionObject { - - /** - * The collection this workflowitem belonging to - */ - @autoserialize - @relationship(Collection, false) - collection: string; - - /** - * The item created with this workflowitem - */ - @autoserialize - @relationship(Item, false) - item: string; - - /** - * The configuration object that define this workflowitem - */ - @autoserialize - @relationship(SubmissionDefinitionsModel, false) - submissionDefinition: string; - - /** - * The EPerson who submit this workflowitem - */ - @autoserialize - @relationship(EPerson, false) - submitter: string; - -} diff --git a/src/app/core/submission/models/normalized-workspaceitem.model.ts b/src/app/core/submission/models/normalized-workspaceitem.model.ts deleted file mode 100644 index 47b7d59f41..0000000000 --- a/src/app/core/submission/models/normalized-workspaceitem.model.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { autoserialize, inheritSerialization } from 'cerialize'; - -import { WorkspaceItem } from './workspaceitem.model'; -import { NormalizedSubmissionObject } from './normalized-submission-object.model'; -import { relationship } from '../../cache/builders/build-decorators'; -import { NormalizedDSpaceObject } from '../../cache/models/normalized-dspace-object.model'; -import { Item } from '../../shared/item.model'; -import { Collection } from '../../shared/collection.model'; -import { SubmissionDefinitionModel } from '../../config/models/config-submission-definition.model'; -import { EPerson } from '../../eperson/models/eperson.model'; - -/** - * An model class for a NormalizedWorkspaceItem. - */ -@inheritSerialization(NormalizedDSpaceObject) -@inheritSerialization(NormalizedSubmissionObject) -export class NormalizedWorkspaceItem extends NormalizedSubmissionObject { - - /** - * The collection this workspaceitem belonging to - */ - @autoserialize - @relationship(Collection, false) - collection: string; - - /** - * The item created with this workspaceitem - */ - @autoserialize - @relationship(Item, false) - item: string; - - /** - * The configuration object that define this workspaceitem - */ - @autoserialize - @relationship(SubmissionDefinitionModel, false) - submissionDefinition: string; - - /** - * The EPerson who submit this workspaceitem - */ - @autoserialize - @relationship(EPerson, false) - submitter: string; -} diff --git a/src/app/core/submission/submission-response-parsing.service.ts b/src/app/core/submission/submission-response-parsing.service.ts index 5afc3b0138..a37d7c4f49 100644 --- a/src/app/core/submission/submission-response-parsing.service.ts +++ b/src/app/core/submission/submission-response-parsing.service.ts @@ -12,13 +12,12 @@ import { BaseResponseParsingService } from '../data/base-response-parsing.servic import { GLOBAL_CONFIG } from '../../../config'; import { GlobalConfig } from '../../../config/global-config.interface'; import { ObjectCacheService } from '../cache/object-cache.service'; -import { NormalizedObjectSerializer } from '../dspace-rest-v2/normalized-object.serializer'; import { Serializer } from '../serializer'; import { GenericConstructor } from '../shared/generic-constructor'; -import { NormalizedWorkspaceItem } from './models/normalized-workspaceitem.model'; -import { NormalizedWorkflowItem } from './models/normalized-workflowitem.model'; import { FormFieldMetadataValueObject } from '../../shared/form/builder/models/form-field-metadata-value.model'; import { SubmissionObject } from './models/submission-object.model'; +import { WorkflowItem } from './models/workflowitem.model'; +import { WorkspaceItem } from './models/workspaceitem.model'; /** * Export a function to check if object has same properties of FormFieldMetadataValueObject @@ -81,8 +80,6 @@ export class SubmissionResponseParsingService extends BaseResponseParsingService protected toCache = false; protected shouldDirectlyAttachEmbeds = true; - protected serializerConstructor: GenericConstructor> = NormalizedObjectSerializer; - constructor(@Inject(GLOBAL_CONFIG) protected EnvConfig: GlobalConfig, protected objectCache: ObjectCacheService, protected dsoParser: DSOResponseParsingService @@ -125,15 +122,15 @@ export class SubmissionResponseParsingService extends BaseResponseParsingService */ protected processResponse(data: any, request: RestRequest): any[] { const dataDefinition = this.process(data, request); - const normalizedDefinition = Array.of(); + const definition = Array.of(); const processedList = Array.isArray(dataDefinition) ? dataDefinition : Array.of(dataDefinition); processedList.forEach((item) => { - let normalizedItem = Object.assign({}, item); - // In case data is an Instance of NormalizedWorkspaceItem normalize field value of all the section of type form - if (item instanceof NormalizedWorkspaceItem - || item instanceof NormalizedWorkflowItem) { + item = Object.assign({}, item); + // In case data is an Instance of WorkspaceItem normalize field value of all the section of type form + if (item instanceof WorkspaceItem + || item instanceof WorkflowItem) { if (item.sections) { const precessedSection = Object.create({}); // Iterate over all workspaceitem's sections @@ -143,35 +140,35 @@ export class SubmissionResponseParsingService extends BaseResponseParsingService // When Upload section is disabled, add to submission only if there are files (!item.sections[sectionId].hasOwnProperty('files') || isNotEmpty((item.sections[sectionId] as any).files)))) { - const normalizedSectionData = Object.create({}); + const sectiondata = Object.create({}); // Iterate over all sections property Object.keys(item.sections[sectionId]) .forEach((metdadataId) => { const entry = item.sections[sectionId][metdadataId]; // If entry is not an array, for sure is not a section of type form if (Array.isArray(entry)) { - normalizedSectionData[metdadataId] = []; + sectiondata[metdadataId] = []; entry.forEach((valueItem, index) => { // Parse value and normalize it const normValue = normalizeSectionData(valueItem, index); if (isNotEmpty(normValue)) { - normalizedSectionData[metdadataId].push(normValue); + sectiondata[metdadataId].push(normValue); } }); } else { - normalizedSectionData[metdadataId] = entry; + sectiondata[metdadataId] = entry; } }); - precessedSection[sectionId] = normalizedSectionData; + precessedSection[sectionId] = sectiondata; } }); - normalizedItem = Object.assign({}, item, { sections: precessedSection }); + item = Object.assign({}, item, { sections: precessedSection }); } } - normalizedDefinition.push(normalizedItem); + definition.push(item); }); - return normalizedDefinition; + return definition; } } diff --git a/src/app/core/submission/workflowitem-data.service.ts b/src/app/core/submission/workflowitem-data.service.ts index 41897aba98..a2dfca5eb3 100644 --- a/src/app/core/submission/workflowitem-data.service.ts +++ b/src/app/core/submission/workflowitem-data.service.ts @@ -10,7 +10,6 @@ import { RequestService } from '../data/request.service'; import { WorkflowItem } from './models/workflowitem.model'; import { HALEndpointService } from '../shared/hal-endpoint.service'; import { FindListOptions } from '../data/request.models'; -import { NormalizedObjectBuildService } from '../cache/builders/normalized-object-build.service'; import { NotificationsService } from '../../shared/notifications/notifications.service'; import { ObjectCacheService } from '../cache/object-cache.service'; import { DSOChangeAnalyzer } from '../data/dso-change-analyzer.service'; @@ -26,7 +25,6 @@ export class WorkflowItemDataService extends DataService { constructor( protected comparator: DSOChangeAnalyzer, - protected dataBuildService: NormalizedObjectBuildService, protected halService: HALEndpointService, protected http: HttpClient, protected notificationsService: NotificationsService, diff --git a/src/app/core/submission/workspaceitem-data.service.ts b/src/app/core/submission/workspaceitem-data.service.ts index 9114882d73..fcb85cc8b4 100644 --- a/src/app/core/submission/workspaceitem-data.service.ts +++ b/src/app/core/submission/workspaceitem-data.service.ts @@ -9,7 +9,6 @@ import { DataService } from '../data/data.service'; import { RequestService } from '../data/request.service'; import { HALEndpointService } from '../shared/hal-endpoint.service'; import { FindListOptions } from '../data/request.models'; -import { NormalizedObjectBuildService } from '../cache/builders/normalized-object-build.service'; import { NotificationsService } from '../../shared/notifications/notifications.service'; import { ObjectCacheService } from '../cache/object-cache.service'; import { DSOChangeAnalyzer } from '../data/dso-change-analyzer.service'; @@ -26,7 +25,6 @@ export class WorkspaceitemDataService extends DataService { constructor( protected comparator: DSOChangeAnalyzer, - protected dataBuildService: NormalizedObjectBuildService, protected halService: HALEndpointService, protected http: HttpClient, protected notificationsService: NotificationsService, diff --git a/src/app/core/tasks/claimed-task-data.service.spec.ts b/src/app/core/tasks/claimed-task-data.service.spec.ts index a7be0830ec..90d449b22b 100644 --- a/src/app/core/tasks/claimed-task-data.service.spec.ts +++ b/src/app/core/tasks/claimed-task-data.service.spec.ts @@ -6,7 +6,6 @@ import { getMockRequestService } from '../../shared/mocks/mock-request.service'; import { HALEndpointServiceStub } from '../../shared/testing/hal-endpoint-service-stub'; import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; import { NotificationsService } from '../../shared/notifications/notifications.service'; -import { NormalizedObjectBuildService } from '../cache/builders/normalized-object-build.service'; import { CoreState } from '../core.reducers'; import { ClaimedTaskDataService } from './claimed-task-data.service'; import { HttpOptions } from '../dspace-rest-v2/dspace-rest-v2.service'; @@ -22,9 +21,6 @@ describe('ClaimedTaskDataService', () => { const notificationsService = {} as NotificationsService; const http = {} as HttpClient; const comparator = {} as any; - const dataBuildService = { - normalize: (object) => object - } as NormalizedObjectBuildService; const objectCache = { addPatch: () => { /* empty */ @@ -39,7 +35,6 @@ describe('ClaimedTaskDataService', () => { return new ClaimedTaskDataService( requestService, rdbService, - dataBuildService, store, objectCache, halService, diff --git a/src/app/core/tasks/claimed-task-data.service.ts b/src/app/core/tasks/claimed-task-data.service.ts index 7be6ed62ef..0a9de20530 100644 --- a/src/app/core/tasks/claimed-task-data.service.ts +++ b/src/app/core/tasks/claimed-task-data.service.ts @@ -5,8 +5,6 @@ import { Store } from '@ngrx/store'; import { Observable } from 'rxjs'; import { NotificationsService } from '../../shared/notifications/notifications.service'; import { dataService } from '../cache/builders/build-decorators'; -import { NormalizedObjectBuildService } from '../cache/builders/normalized-object-build.service'; - import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; import { ObjectCacheService } from '../cache/object-cache.service'; import { CoreState } from '../core.reducers'; @@ -37,7 +35,7 @@ export class ClaimedTaskDataService extends TasksService { * * @param {RequestService} requestService * @param {RemoteDataBuildService} rdbService - * @param {NormalizedObjectBuildService} dataBuildService + * @param {NormalizedObjectBuildService} linkService * @param {Store} store * @param {ObjectCacheService} objectCache * @param {HALEndpointService} halService @@ -48,7 +46,6 @@ export class ClaimedTaskDataService extends TasksService { constructor( protected requestService: RequestService, protected rdbService: RemoteDataBuildService, - protected dataBuildService: NormalizedObjectBuildService, protected store: Store, protected objectCache: ObjectCacheService, protected halService: HALEndpointService, diff --git a/src/app/core/tasks/models/claimed-task-object.model.ts b/src/app/core/tasks/models/claimed-task-object.model.ts index ce87674c86..314bc3a1fa 100644 --- a/src/app/core/tasks/models/claimed-task-object.model.ts +++ b/src/app/core/tasks/models/claimed-task-object.model.ts @@ -1,4 +1,6 @@ +import { inheritSerialization } from 'cerialize'; import { resourceType } from '../../cache/builders/build-decorators'; +import { DSpaceObject } from '../../shared/dspace-object.model'; import { CLAIMED_TASK } from './claimed-task-object.resource-type'; import { TaskObject } from './task-object.model'; @@ -6,6 +8,7 @@ import { TaskObject } from './task-object.model'; * A model class for a ClaimedTask. */ @resourceType(ClaimedTask.type) +@inheritSerialization(DSpaceObject) export class ClaimedTask extends TaskObject { static type = CLAIMED_TASK; } diff --git a/src/app/core/tasks/models/normalized-claimed-task-object.model.ts b/src/app/core/tasks/models/normalized-claimed-task-object.model.ts deleted file mode 100644 index fa7f817e1d..0000000000 --- a/src/app/core/tasks/models/normalized-claimed-task-object.model.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { NormalizedTaskObject } from './normalized-task-object.model'; -import { relationship } from '../../cache/builders/build-decorators'; -import { autoserialize, inheritSerialization } from 'cerialize'; -import { ClaimedTask } from './claimed-task-object.model'; -import { EPerson } from '../../eperson/models/eperson.model'; -import { Group } from '../../eperson/models/group.model'; -import { WorkflowItem } from '../../submission/models/workflowitem.model'; - -/** - * A normalized model class for a ClaimedTask. - */ -@inheritSerialization(NormalizedTaskObject) -export class NormalizedClaimedTask extends NormalizedTaskObject { - /** - * The task identifier - */ - @autoserialize - id: string; - - /** - * The workflow step - */ - @autoserialize - step: string; - - /** - * The task action type - */ - @autoserialize - action: string; - - /** - * The eperson object for this task - */ - @autoserialize - @relationship(EPerson, false) - eperson: string; - - /** - * The group object for this task - */ - @autoserialize - @relationship(Group, false) - group: string; - - /** - * The workflowitem object whom this task is related - */ - @autoserialize - @relationship(WorkflowItem, false) - workflowitem: string; - -} diff --git a/src/app/core/tasks/models/normalized-pool-task-object.model.ts b/src/app/core/tasks/models/normalized-pool-task-object.model.ts deleted file mode 100644 index 39c7877807..0000000000 --- a/src/app/core/tasks/models/normalized-pool-task-object.model.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { NormalizedTaskObject } from './normalized-task-object.model'; -import { PoolTask } from './pool-task-object.model'; -import { autoserialize, inheritSerialization } from 'cerialize'; -import { relationship } from '../../cache/builders/build-decorators'; -import { Group } from '../../eperson/models/group.model'; -import { WorkflowItem } from '../../submission/models/workflowitem.model'; - -/** - * A normalized model class for a PoolTask. - */ -@inheritSerialization(NormalizedTaskObject) -export class NormalizedPoolTask extends NormalizedTaskObject { - /** - * The task identifier - */ - @autoserialize - id: string; - - /** - * The workflow step - */ - @autoserialize - step: string; - - /** - * The task action type - */ - @autoserialize - action: string; - - /** - * The group object for this task - */ - @autoserialize - @relationship(Group, false) - group: string; - - /** - * The workflowitem object whom this task is related - */ - @autoserialize - @relationship(WorkflowItem, false) - workflowitem: string; -} diff --git a/src/app/core/tasks/models/normalized-task-object.model.ts b/src/app/core/tasks/models/normalized-task-object.model.ts deleted file mode 100644 index 3fe999d91c..0000000000 --- a/src/app/core/tasks/models/normalized-task-object.model.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { autoserialize, inheritSerialization } from 'cerialize'; -import { relationship } from '../../cache/builders/build-decorators'; -import { NormalizedDSpaceObject } from '../../cache/models/normalized-dspace-object.model'; -import { TaskObject } from './task-object.model'; -import { DSpaceObject } from '../../shared/dspace-object.model'; -import { Group } from '../../eperson/models/group.model'; -import { EPerson } from '../../eperson/models/eperson.model'; -import { WorkflowItem } from '../../submission/models/workflowitem.model'; - -/** - * An abstract normalized model class for a TaskObject. - */ -@inheritSerialization(NormalizedDSpaceObject) -export class NormalizedTaskObject extends NormalizedDSpaceObject { - - /** - * The task identifier - */ - @autoserialize - id: string; - - /** - * The workflow step - */ - @autoserialize - step: string; - - /** - * The task action type - */ - @autoserialize - action: string; - - /** - * The eperson object for this task - */ - @autoserialize - @relationship(EPerson, false) - eperson: string; - - /** - * The group object for this task - */ - @autoserialize - @relationship(Group, false) - group: string; - - /** - * The workflowitem object whom this task is related - */ - @autoserialize - @relationship(WorkflowItem, false) - workflowitem: string; -} diff --git a/src/app/core/tasks/models/pool-task-object.model.ts b/src/app/core/tasks/models/pool-task-object.model.ts index 2546ba0c6f..9938435f12 100644 --- a/src/app/core/tasks/models/pool-task-object.model.ts +++ b/src/app/core/tasks/models/pool-task-object.model.ts @@ -1,3 +1,4 @@ +import { inheritSerialization } from 'cerialize'; import { resourceType } from '../../cache/builders/build-decorators'; import { POOL_TASK } from './pool-task-object.resource-type'; import { TaskObject } from './task-object.model'; @@ -6,6 +7,7 @@ import { TaskObject } from './task-object.model'; * A model class for a PoolTask. */ @resourceType(PoolTask.type) +@inheritSerialization(TaskObject) export class PoolTask extends TaskObject { static type = POOL_TASK; } diff --git a/src/app/core/tasks/models/task-object.model.ts b/src/app/core/tasks/models/task-object.model.ts index c851bc092f..bab1b3b62b 100644 --- a/src/app/core/tasks/models/task-object.model.ts +++ b/src/app/core/tasks/models/task-object.model.ts @@ -1,3 +1,4 @@ +import { autoserialize, deserialize, inheritSerialization } from 'cerialize'; import { Observable } from 'rxjs'; import { link, resourceType } from '../../cache/builders/build-decorators'; @@ -16,24 +17,39 @@ import { TASK_OBJECT } from './task-object.resource-type'; * An abstract model class for a TaskObject. */ @resourceType(TaskObject.type) +@inheritSerialization(DSpaceObject) export class TaskObject extends DSpaceObject implements CacheableObject { static type = TASK_OBJECT; /** * The task identifier */ + @autoserialize id: string; /** * The workflow step */ + @autoserialize step: string; /** * The task action type */ + @autoserialize action: string; + /** + * The HALLinks for this TaskObject + */ + @deserialize + _links: { + self: HALLink; + eperson: HALLink; + group: HALLink; + workflowitem: HALLink; + }; + /** * The EPerson for this task * Will be undefined unless the eperson HALLink has been resolved. @@ -55,11 +71,4 @@ export class TaskObject extends DSpaceObject implements CacheableObject { @link(WorkflowItem.type) workflowitem?: Observable> | WorkflowItem; - _links: { - self: HALLink, - eperson: HALLink, - group: HALLink, - workflowitem: HALLink, - } - } diff --git a/src/app/core/tasks/pool-task-data.service.spec.ts b/src/app/core/tasks/pool-task-data.service.spec.ts index 7f40c6e89c..70ae4c7a91 100644 --- a/src/app/core/tasks/pool-task-data.service.spec.ts +++ b/src/app/core/tasks/pool-task-data.service.spec.ts @@ -6,7 +6,6 @@ import { getMockRequestService } from '../../shared/mocks/mock-request.service'; import { HALEndpointServiceStub } from '../../shared/testing/hal-endpoint-service-stub'; import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; import { NotificationsService } from '../../shared/notifications/notifications.service'; -import { NormalizedObjectBuildService } from '../cache/builders/normalized-object-build.service'; import { CoreState } from '../core.reducers'; import { PoolTaskDataService } from './pool-task-data.service'; import { HttpOptions } from '../dspace-rest-v2/dspace-rest-v2.service'; @@ -22,9 +21,6 @@ describe('PoolTaskDataService', () => { const notificationsService = {} as NotificationsService; const http = {} as HttpClient; const comparator = {} as any; - const dataBuildService = { - normalize: (object) => object - } as NormalizedObjectBuildService; const objectCache = { addPatch: () => { /* empty */ @@ -39,7 +35,6 @@ describe('PoolTaskDataService', () => { return new PoolTaskDataService( requestService, rdbService, - dataBuildService, store, objectCache, halService, diff --git a/src/app/core/tasks/pool-task-data.service.ts b/src/app/core/tasks/pool-task-data.service.ts index 1259c1496f..f08274b5f1 100644 --- a/src/app/core/tasks/pool-task-data.service.ts +++ b/src/app/core/tasks/pool-task-data.service.ts @@ -5,8 +5,6 @@ import { Store } from '@ngrx/store'; import { Observable } from 'rxjs'; import { NotificationsService } from '../../shared/notifications/notifications.service'; import { dataService } from '../cache/builders/build-decorators'; -import { NormalizedObjectBuildService } from '../cache/builders/normalized-object-build.service'; - import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; import { ObjectCacheService } from '../cache/object-cache.service'; import { CoreState } from '../core.reducers'; @@ -37,7 +35,7 @@ export class PoolTaskDataService extends TasksService { * * @param {RequestService} requestService * @param {RemoteDataBuildService} rdbService - * @param {NormalizedObjectBuildService} dataBuildService + * @param {NormalizedObjectBuildService} linkService * @param {Store} store * @param {ObjectCacheService} objectCache * @param {HALEndpointService} halService @@ -48,7 +46,6 @@ export class PoolTaskDataService extends TasksService { constructor( protected requestService: RequestService, protected rdbService: RemoteDataBuildService, - protected dataBuildService: NormalizedObjectBuildService, protected store: Store, protected objectCache: ObjectCacheService, protected halService: HALEndpointService, diff --git a/src/app/core/tasks/tasks.service.spec.ts b/src/app/core/tasks/tasks.service.spec.ts index 3ca9b8ea8f..782a950b2d 100644 --- a/src/app/core/tasks/tasks.service.spec.ts +++ b/src/app/core/tasks/tasks.service.spec.ts @@ -9,7 +9,6 @@ import { HALEndpointService } from '../shared/hal-endpoint.service'; import { HALEndpointServiceStub } from '../../shared/testing/hal-endpoint-service-stub'; import { TaskObject } from './models/task-object.model'; import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; -import { NormalizedObjectBuildService } from '../cache/builders/normalized-object-build.service'; import { Store } from '@ngrx/store'; import { CoreState } from '../core.reducers'; import { ObjectCacheService } from '../cache/object-cache.service'; @@ -18,7 +17,6 @@ import { HttpClient, HttpHeaders } from '@angular/common/http'; import { DSOChangeAnalyzer } from '../data/dso-change-analyzer.service'; import { ChangeAnalyzer } from '../data/change-analyzer'; import { compare, Operation } from 'fast-json-patch'; -import { NormalizedTaskObject } from './models/normalized-task-object.model'; import { HttpOptions } from '../dspace-rest-v2/dspace-rest-v2.service'; const LINK_NAME = 'test'; @@ -33,7 +31,6 @@ class TestService extends TasksService { constructor( protected requestService: RequestService, protected rdbService: RemoteDataBuildService, - protected dataBuildService: NormalizedObjectBuildService, protected store: Store, protected objectCache: ObjectCacheService, protected halService: HALEndpointService, @@ -44,11 +41,8 @@ class TestService extends TasksService { } } -class NormalizedTestTaskObject extends NormalizedTaskObject { -} - -class DummyChangeAnalyzer implements ChangeAnalyzer { - diff(object1: NormalizedTestTaskObject, object2: NormalizedTestTaskObject): Operation[] { +class DummyChangeAnalyzer implements ChangeAnalyzer { + diff(object1: TestTask, object2: TestTask): Operation[] { return compare((object1 as any).metadata, (object2 as any).metadata); } @@ -66,9 +60,6 @@ describe('TasksService', () => { const notificationsService = {} as NotificationsService; const http = {} as HttpClient; const comparator = new DummyChangeAnalyzer() as any; - const dataBuildService = { - normalize: (object) => object - } as NormalizedObjectBuildService; const objectCache = { addPatch: () => { /* empty */ @@ -83,7 +74,6 @@ describe('TasksService', () => { return new TestService( requestService, rdbService, - dataBuildService, store, objectCache, halService, diff --git a/src/app/entity-groups/journal-entities/item-pages/journal/journal.component.spec.ts b/src/app/entity-groups/journal-entities/item-pages/journal/journal.component.spec.ts index 22bda8f056..3cd2ac1cce 100644 --- a/src/app/entity-groups/journal-entities/item-pages/journal/journal.component.spec.ts +++ b/src/app/entity-groups/journal-entities/item-pages/journal/journal.component.spec.ts @@ -6,7 +6,6 @@ import { Store } from '@ngrx/store'; import { TranslateLoader, TranslateModule } from '@ngx-translate/core'; import { Observable } from 'rxjs/internal/Observable'; import { GenericItemPageFieldComponent } from '../../../../+item-page/simple/field-components/specific-field/generic/generic-item-page-field.component'; -import { NormalizedObjectBuildService } from '../../../../core/cache/builders/normalized-object-build.service'; import { RemoteDataBuildService } from '../../../../core/cache/builders/remote-data-build.service'; import { ObjectCacheService } from '../../../../core/cache/object-cache.service'; import { BitstreamDataService } from '../../../../core/data/bitstream-data.service'; @@ -80,7 +79,6 @@ describe('JournalComponent', () => { { provide: UUIDService, useValue: {} }, { provide: Store, useValue: {} }, { provide: RemoteDataBuildService, useValue: {} }, - { provide: NormalizedObjectBuildService, useValue: {} }, { provide: CommunityDataService, useValue: {} }, { provide: HALEndpointService, useValue: {} }, { provide: HttpClient, useValue: {} }, diff --git a/src/app/entity-groups/research-entities/submission/item-list-elements/org-unit/org-unit-search-result-list-submission-element.component.spec.ts b/src/app/entity-groups/research-entities/submission/item-list-elements/org-unit/org-unit-search-result-list-submission-element.component.spec.ts index 2a49c1923d..e1520d9edd 100644 --- a/src/app/entity-groups/research-entities/submission/item-list-elements/org-unit/org-unit-search-result-list-submission-element.component.spec.ts +++ b/src/app/entity-groups/research-entities/submission/item-list-elements/org-unit/org-unit-search-result-list-submission-element.component.spec.ts @@ -7,7 +7,6 @@ import { Store } from '@ngrx/store'; import { TranslateService } from '@ngx-translate/core'; import { of as observableOf } from 'rxjs'; import { Observable } from 'rxjs/internal/Observable'; -import { NormalizedObjectBuildService } from '../../../../../core/cache/builders/normalized-object-build.service'; import { RemoteDataBuildService } from '../../../../../core/cache/builders/remote-data-build.service'; import { ObjectCacheService } from '../../../../../core/cache/object-cache.service'; import { BitstreamDataService } from '../../../../../core/data/bitstream-data.service'; @@ -111,7 +110,6 @@ describe('OrgUnitSearchResultListSubmissionElementComponent', () => { { provide: ObjectCacheService, useValue: {} }, { provide: UUIDService, useValue: {} }, { provide: RemoteDataBuildService, useValue: {} }, - { provide: NormalizedObjectBuildService, useValue: {} }, { provide: CommunityDataService, useValue: {} }, { provide: HALEndpointService, useValue: {} }, { provide: HttpClient, useValue: {} }, diff --git a/src/app/entity-groups/research-entities/submission/item-list-elements/person/person-search-result-list-submission-element.component.spec.ts b/src/app/entity-groups/research-entities/submission/item-list-elements/person/person-search-result-list-submission-element.component.spec.ts index ff320c7552..0949ebea7e 100644 --- a/src/app/entity-groups/research-entities/submission/item-list-elements/person/person-search-result-list-submission-element.component.spec.ts +++ b/src/app/entity-groups/research-entities/submission/item-list-elements/person/person-search-result-list-submission-element.component.spec.ts @@ -7,7 +7,6 @@ import { Store } from '@ngrx/store'; import { TranslateService } from '@ngx-translate/core'; import { of as observableOf } from 'rxjs'; import { Observable } from 'rxjs/internal/Observable'; -import { NormalizedObjectBuildService } from '../../../../../core/cache/builders/normalized-object-build.service'; import { RemoteDataBuildService } from '../../../../../core/cache/builders/remote-data-build.service'; import { ObjectCacheService } from '../../../../../core/cache/object-cache.service'; import { BitstreamDataService } from '../../../../../core/data/bitstream-data.service'; @@ -105,7 +104,6 @@ describe('PersonSearchResultListElementSubmissionComponent', () => { { provide: ObjectCacheService, useValue: {} }, { provide: UUIDService, useValue: {} }, { provide: RemoteDataBuildService, useValue: {} }, - { provide: NormalizedObjectBuildService, useValue: {} }, { provide: CommunityDataService, useValue: {} }, { provide: HALEndpointService, useValue: {} }, { provide: HttpClient, useValue: {} }, diff --git a/src/app/shared/mocks/mock-remote-data-build.service.ts b/src/app/shared/mocks/mock-remote-data-build.service.ts index 1cec4c3277..5098c77e34 100644 --- a/src/app/shared/mocks/mock-remote-data-build.service.ts +++ b/src/app/shared/mocks/mock-remote-data-build.service.ts @@ -1,7 +1,6 @@ import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; import { RemoteDataBuildService } from '../../core/cache/builders/remote-data-build.service'; -import { NormalizedObject } from '../../core/cache/models/normalized-object.model'; import { PaginatedList } from '../../core/data/paginated-list'; import { RemoteData } from '../../core/data/remote-data'; import { RequestEntry } from '../../core/data/request.reducer'; @@ -22,7 +21,7 @@ export function getMockRemoteDataBuildService(toRemoteDataObservable$?: Observab } }, buildSingle: (href$: string | Observable) => createSuccessfulRemoteDataObject$({}), - build: (normalized: NormalizedObject) => Object.create({}), + build: (obj: any) => Object.create({}), buildList: (href$: string | Observable) => { if (hasValue(buildList$)) { return buildList$; @@ -47,7 +46,7 @@ export function getMockRemoteDataBuildServiceHrefMap(toRemoteDataObservable$?: O } }, buildSingle: (href$: string | Observable) => createSuccessfulRemoteDataObject$({}), - build: (normalized: NormalizedObject) => Object.create({}), + build: (obj: any) => Object.create({}), buildList: (href$: string | Observable) => { if (typeof href$ === 'string') { if (hasValue(buildListHrefMap$[href$])) { diff --git a/src/app/shared/object-detail/my-dspace-result-detail-element/item-detail-preview/item-detail-preview.component.spec.ts b/src/app/shared/object-detail/my-dspace-result-detail-element/item-detail-preview/item-detail-preview.component.spec.ts index 37139e7652..5e0c483982 100644 --- a/src/app/shared/object-detail/my-dspace-result-detail-element/item-detail-preview/item-detail-preview.component.spec.ts +++ b/src/app/shared/object-detail/my-dspace-result-detail-element/item-detail-preview/item-detail-preview.component.spec.ts @@ -7,7 +7,6 @@ import { TranslateLoader, TranslateModule } from '@ngx-translate/core'; import { of as observableOf } from 'rxjs'; import { Observable } from 'rxjs/internal/Observable'; -import { NormalizedObjectBuildService } from '../../../../core/cache/builders/normalized-object-build.service'; import { RemoteDataBuildService } from '../../../../core/cache/builders/remote-data-build.service'; import { ObjectCacheService } from '../../../../core/cache/object-cache.service'; import { BitstreamDataService } from '../../../../core/data/bitstream-data.service'; @@ -103,7 +102,6 @@ describe('ItemDetailPreviewComponent', () => { { provide: UUIDService, useValue: {} }, { provide: Store, useValue: {} }, { provide: RemoteDataBuildService, useValue: {} }, - { provide: NormalizedObjectBuildService, useValue: {} }, { provide: CommunityDataService, useValue: {} }, { provide: HALEndpointService, useValue: {} }, { provide: NotificationsService, useValue: {} }, diff --git a/src/app/shared/object-grid/search-result-grid-element/collection-search-result/collection-search-result-grid-element.component.spec.ts b/src/app/shared/object-grid/search-result-grid-element/collection-search-result/collection-search-result-grid-element.component.spec.ts index 672168b956..c14e3f6df1 100644 --- a/src/app/shared/object-grid/search-result-grid-element/collection-search-result/collection-search-result-grid-element.component.spec.ts +++ b/src/app/shared/object-grid/search-result-grid-element/collection-search-result/collection-search-result-grid-element.component.spec.ts @@ -4,7 +4,6 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { By } from '@angular/platform-browser'; import { Store } from '@ngrx/store'; import { of as observableOf } from 'rxjs'; -import { NormalizedObjectBuildService } from '../../../../core/cache/builders/normalized-object-build.service'; import { RemoteDataBuildService } from '../../../../core/cache/builders/remote-data-build.service'; import { ObjectCacheService } from '../../../../core/cache/object-cache.service'; import { CommunityDataService } from '../../../../core/data/community-data.service'; @@ -63,7 +62,6 @@ describe('CollectionSearchResultGridElementComponent', () => { { provide: UUIDService, useValue: {} }, { provide: Store, useValue: {} }, { provide: RemoteDataBuildService, useValue: {} }, - { provide: NormalizedObjectBuildService, useValue: {} }, { provide: CommunityDataService, useValue: {} }, { provide: HALEndpointService, useValue: {} }, { provide: NotificationsService, useValue: {} }, diff --git a/src/app/shared/object-grid/search-result-grid-element/community-search-result/community-search-result-grid-element.component.spec.ts b/src/app/shared/object-grid/search-result-grid-element/community-search-result/community-search-result-grid-element.component.spec.ts index 8ca58384e8..0ea72b52d5 100644 --- a/src/app/shared/object-grid/search-result-grid-element/community-search-result/community-search-result-grid-element.component.spec.ts +++ b/src/app/shared/object-grid/search-result-grid-element/community-search-result/community-search-result-grid-element.component.spec.ts @@ -4,7 +4,6 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { By } from '@angular/platform-browser'; import { Store } from '@ngrx/store'; import { of as observableOf } from 'rxjs'; -import { NormalizedObjectBuildService } from '../../../../core/cache/builders/normalized-object-build.service'; import { RemoteDataBuildService } from '../../../../core/cache/builders/remote-data-build.service'; import { ObjectCacheService } from '../../../../core/cache/object-cache.service'; import { CommunityDataService } from '../../../../core/data/community-data.service'; @@ -63,7 +62,6 @@ describe('CommunitySearchResultGridElementComponent', () => { { provide: UUIDService, useValue: {} }, { provide: Store, useValue: {} }, { provide: RemoteDataBuildService, useValue: {} }, - { provide: NormalizedObjectBuildService, useValue: {} }, { provide: CommunityDataService, useValue: {} }, { provide: HALEndpointService, useValue: {} }, { provide: NotificationsService, useValue: {} }, diff --git a/src/app/shared/object-grid/search-result-grid-element/item-search-result/publication/publication-search-result-grid-element.component.spec.ts b/src/app/shared/object-grid/search-result-grid-element/item-search-result/publication/publication-search-result-grid-element.component.spec.ts index 158690290f..47531e044c 100644 --- a/src/app/shared/object-grid/search-result-grid-element/item-search-result/publication/publication-search-result-grid-element.component.spec.ts +++ b/src/app/shared/object-grid/search-result-grid-element/item-search-result/publication/publication-search-result-grid-element.component.spec.ts @@ -6,7 +6,6 @@ import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { Store } from '@ngrx/store'; import { Observable } from 'rxjs/internal/Observable'; import { of as observableOf } from 'rxjs/internal/observable/of'; -import { NormalizedObjectBuildService } from '../../../../../core/cache/builders/normalized-object-build.service'; import { RemoteDataBuildService } from '../../../../../core/cache/builders/remote-data-build.service'; import { ObjectCacheService } from '../../../../../core/cache/object-cache.service'; import { BitstreamDataService } from '../../../../../core/data/bitstream-data.service'; @@ -109,7 +108,6 @@ export function getEntityGridElementTestComponent(component, searchResultWithMet { provide: UUIDService, useValue: {} }, { provide: Store, useValue: {} }, { provide: RemoteDataBuildService, useValue: {} }, - { provide: NormalizedObjectBuildService, useValue: {} }, { provide: CommunityDataService, useValue: {} }, { provide: HALEndpointService, useValue: {} }, { provide: HttpClient, useValue: {} }, diff --git a/src/app/shared/search/facet-value.model.ts b/src/app/shared/search/facet-value.model.ts index d2cc521356..685b5ba704 100644 --- a/src/app/shared/search/facet-value.model.ts +++ b/src/app/shared/search/facet-value.model.ts @@ -1,9 +1,11 @@ -import { autoserialize, autoserializeAs } from 'cerialize'; +import { autoserialize, autoserializeAs, deserialize } from 'cerialize'; +import { HALLink } from '../../core/shared/hal-link.model'; +import { HALResource } from '../../core/shared/hal-resource.model'; /** * Class representing possible values for a certain filter */ -export class FacetValue { +export class FacetValue implements HALResource { /** * The display label of the facet value */ @@ -23,8 +25,11 @@ export class FacetValue { count: number; /** - * The REST url to add this filter value + * The HALLinks for this FacetValue */ - @autoserialize - search: string; + @deserialize + _links: { + self: HALLink + search: HALLink + } } diff --git a/src/app/shared/search/search-filters/search-filter/search-authority-filter/search-authority-filter.component.ts b/src/app/shared/search/search-filters/search-filter/search-authority-filter/search-authority-filter.component.ts index 99e9bfac2e..5dc930f67f 100644 --- a/src/app/shared/search/search-filters/search-filter/search-authority-filter/search-authority-filter.component.ts +++ b/src/app/shared/search/search-filters/search-filter/search-authority-filter/search-authority-filter.component.ts @@ -23,7 +23,7 @@ export class SearchAuthorityFilterComponent extends SearchFacetFilterComponent i * Retrieve facet value from search link */ protected getFacetValue(facet: FacetValue): string { - const search = facet.search; + const search = facet._links.search.href; const hashes = search.slice(search.indexOf('?') + 1).split('&'); const params = {}; hashes.map((hash) => { diff --git a/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-option/search-facet-option.component.ts b/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-option/search-facet-option.component.ts index 512cd5501c..04e810edda 100644 --- a/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-option/search-facet-option.component.ts +++ b/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-option/search-facet-option.component.ts @@ -113,7 +113,7 @@ export class SearchFacetOptionComponent implements OnInit, OnDestroy { */ private getFacetValue(): string { if (this.filterConfig.type === FilterType.authority) { - const search = this.filterValue.search; + const search = this.filterValue._links.search.href; const hashes = search.slice(search.indexOf('?') + 1).split('&'); const params = {}; hashes.map((hash) => { diff --git a/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-selected-option/search-facet-selected-option.component.ts b/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-selected-option/search-facet-selected-option.component.ts index 0cf54d88f5..f58a903b0c 100644 --- a/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-selected-option/search-facet-selected-option.component.ts +++ b/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-selected-option/search-facet-selected-option.component.ts @@ -102,7 +102,7 @@ export class SearchFacetSelectedOptionComponent implements OnInit, OnDestroy { */ private getFacetValue(facetValue: FacetValue): string { if (this.filterConfig.type === FilterType.authority) { - const search = facetValue.search; + const search = facetValue._links.search.href; const hashes = search.slice(search.indexOf('?') + 1).split('&'); const params = {}; hashes.map((hash) => { diff --git a/src/app/shared/search/search-filters/search-filter/search-facet-filter/search-facet-filter.component.ts b/src/app/shared/search/search-filters/search-filter/search-facet-filter/search-facet-filter.component.ts index 1d6a85b95b..df0c53f543 100644 --- a/src/app/shared/search/search-filters/search-filter/search-facet-filter/search-facet-filter.component.ts +++ b/src/app/shared/search/search-filters/search-filter/search-facet-filter/search-facet-filter.component.ts @@ -320,7 +320,7 @@ export class SearchFacetFilterComponent implements OnInit, OnDestroy { * Prevent unnecessary rerendering */ trackUpdate(index, value: FacetValue) { - return value ? value.search : undefined; + return value ? value._links.search.href : undefined; } } diff --git a/src/app/shared/search/search-filters/search-filter/search-range-filter/search-range-filter.component.spec.ts b/src/app/shared/search/search-filters/search-filter/search-range-filter/search-range-filter.component.spec.ts index 530b4e6b71..72840b3ffe 100644 --- a/src/app/shared/search/search-filters/search-filter/search-range-filter/search-range-filter.component.spec.ts +++ b/src/app/shared/search/search-filters/search-filter/search-range-filter/search-range-filter.component.spec.ts @@ -45,17 +45,38 @@ describe('SearchRangeFilterComponent', () => { label: value1, value: value1, count: 52, - search: '' + _links: { + self: { + href:'' + }, + search: { + href: '' + } + } }, { label: value2, value: value2, count: 20, - search: '' + _links: { + self: { + href:'' + }, + search: { + href: '' + } + } }, { label: value3, value: value3, count: 5, - search: '' + _links: { + self: { + href:'' + }, + search: { + href: '' + } + } } ]; diff --git a/src/app/thumbnail/thumbnail.component.ts b/src/app/thumbnail/thumbnail.component.ts index b79d5235e1..15cef22e07 100644 --- a/src/app/thumbnail/thumbnail.component.ts +++ b/src/app/thumbnail/thumbnail.component.ts @@ -1,4 +1,4 @@ -import { Component, Input } from '@angular/core'; +import { Component, Input, OnInit } from '@angular/core'; import { Bitstream } from '../core/shared/bitstream.model'; import { hasValue } from '../shared/empty.util'; @@ -13,16 +13,9 @@ import { hasValue } from '../shared/empty.util'; styleUrls: ['./thumbnail.component.scss'], templateUrl: './thumbnail.component.html' }) -export class ThumbnailComponent { +export class ThumbnailComponent implements OnInit { - private _thumbnail: Bitstream; - - get thumbnail(): Bitstream { - return this._thumbnail; - }; - - @Input() set thumbnail(t: Bitstream) { - this._thumbnail = t; + ngOnInit(): void { if (hasValue(this.thumbnail) && hasValue(this.thumbnail._links) && hasValue(this.thumbnail._links.content) && this.thumbnail._links.content.href) { this.src = this.thumbnail._links.content.href; } else { @@ -30,6 +23,8 @@ export class ThumbnailComponent { } } + @Input() thumbnail: Bitstream; + /** * The default 'holder.js' image */ From 10bb457897d824bcd6e711abc4fb211b876ebecc Mon Sep 17 00:00:00 2001 From: Marie Verdonck Date: Fri, 14 Feb 2020 18:58:55 +0100 Subject: [PATCH 24/38] 68405: test fixes --- src/app/core/shared/page-info.model.ts | 8 +-- .../models/submission-object.model.ts | 6 ++- src/app/shared/mocks/mock-submission.ts | 52 ------------------- ...arch-result-list-element.component.spec.ts | 2 - .../form/submission-form.component.ts | 24 ++++----- 5 files changed, 21 insertions(+), 71 deletions(-) diff --git a/src/app/core/shared/page-info.model.ts b/src/app/core/shared/page-info.model.ts index c077c30b4c..d05080bfbb 100644 --- a/src/app/core/shared/page-info.model.ts +++ b/src/app/core/shared/page-info.model.ts @@ -65,7 +65,7 @@ export class PageInfo implements HALResource { } get last(): string { - if (hasValue(this._links.last)) { + if (hasValue(this._links) && hasValue(this._links.last)) { return this._links.last.href; } else { return undefined; @@ -73,7 +73,7 @@ export class PageInfo implements HALResource { } get next(): string { - if (hasValue(this._links.next)) { + if (hasValue(this._links) && hasValue(this._links.next)) { return this._links.next.href; } else { return undefined; @@ -81,7 +81,7 @@ export class PageInfo implements HALResource { } get prev(): string { - if (hasValue(this._links.prev)) { + if (hasValue(this._links) && hasValue(this._links.prev)) { return this._links.prev.href; } else { return undefined; @@ -89,7 +89,7 @@ export class PageInfo implements HALResource { } get first(): string { - if (hasValue(this._links.first)) { + if (hasValue(this._links) && hasValue(this._links.first)) { return this._links.first.href; } else { return undefined; diff --git a/src/app/core/submission/models/submission-object.model.ts b/src/app/core/submission/models/submission-object.model.ts index 237a838e3c..3a50484d76 100644 --- a/src/app/core/submission/models/submission-object.model.ts +++ b/src/app/core/submission/models/submission-object.model.ts @@ -1,4 +1,4 @@ -import { autoserialize, autoserializeAs, deserialize, inheritSerialization } from 'cerialize'; +import { autoserialize, deserialize, inheritSerialization } from 'cerialize'; import { Observable } from 'rxjs'; import { link } from '../../cache/builders/build-decorators'; @@ -68,6 +68,10 @@ export abstract class SubmissionObject extends DSpaceObject implements Cacheable submitter: HALLink; }; + get self(): string { + return this._links.self.href; + } + /** * The submission item * Will be undefined unless the item HALLink has been resolved. diff --git a/src/app/shared/mocks/mock-submission.ts b/src/app/shared/mocks/mock-submission.ts index a9c7fae654..082eec4c71 100644 --- a/src/app/shared/mocks/mock-submission.ts +++ b/src/app/shared/mocks/mock-submission.ts @@ -127,7 +127,6 @@ export const mockSubmissionRestResponse = [ content: 'https://rest.api/dspace-spring-rest/api/core/bitstreams/3f859425-ffbd-4b0e-bf91-bfeb458a7425/content', format: [], bundleName: null, - self: 'https://rest.api/dspace-spring-rest/api/core/bitstreams/3f859425-ffbd-4b0e-bf91-bfeb458a7425', id: '3f859425-ffbd-4b0e-bf91-bfeb458a7425', uuid: '3f859425-ffbd-4b0e-bf91-bfeb458a7425', type: 'bitstream', @@ -140,7 +139,6 @@ export const mockSubmissionRestResponse = [ } } ], - self: 'https://rest.api/dspace-spring-rest/api/core/collections/1c11f3f1-ba1f-4f36-908a-3f1ea9a557eb', id: '1c11f3f1-ba1f-4f36-908a-3f1ea9a557eb', uuid: '1c11f3f1-ba1f-4f36-908a-3f1ea9a557eb', type: 'collection', @@ -198,7 +196,6 @@ export const mockSubmissionRestResponse = [ isDiscoverable: true, isWithdrawn: false, bitstreams: 'https://rest.api/dspace-spring-rest/api/core/items/6f344222-6980-4738-8192-b808d79af8a5/bitstreams', - self: 'https://rest.api/dspace-spring-rest/api/core/items/6f344222-6980-4738-8192-b808d79af8a5', id: '6f344222-6980-4738-8192-b808d79af8a5', uuid: '6f344222-6980-4738-8192-b808d79af8a5', type: 'item', @@ -229,7 +226,6 @@ export const mockSubmissionRestResponse = [ self: { href: 'https://rest.api/dspace-spring-rest/api/config/submissionsections/extraction' }, config: '' }, - self: 'https://rest.api/dspace-spring-rest/api/config/submissionsections/extraction' }, { mandatory: true, @@ -243,7 +239,6 @@ export const mockSubmissionRestResponse = [ self: { href: 'https://rest.api/dspace-spring-rest/api/config/submissionsections/collection' }, config: '' }, - self: 'https://rest.api/dspace-spring-rest/api/config/submissionsections/collection' }, { header: 'submit.progressbar.describe.stepone', @@ -254,7 +249,6 @@ export const mockSubmissionRestResponse = [ self: { href: 'https://rest.api/dspace-spring-rest/api/config/submissionsections/traditionalpageone' }, config: { href: 'https://rest.api/dspace-spring-rest/api/config/submissionforms/traditionalpageone' } }, - self: 'https://rest.api/dspace-spring-rest/api/config/submissionsections/traditionalpageone' }, { header: 'submit.progressbar.describe.steptwo', @@ -265,7 +259,6 @@ export const mockSubmissionRestResponse = [ self: { href: 'https://rest.api/dspace-spring-rest/api/config/submissionsections/traditionalpagetwo' }, config: { href: 'https://rest.api/dspace-spring-rest/api/config/submissionforms/traditionalpagetwo' } }, - self: 'https://rest.api/dspace-spring-rest/api/config/submissionsections/traditionalpagetwo' }, { header: 'submit.progressbar.upload', @@ -276,7 +269,6 @@ export const mockSubmissionRestResponse = [ self: { href: 'https://rest.api/dspace-spring-rest/api/config/submissionsections/upload' }, config: { href: 'https://rest.api/dspace-spring-rest/api/config/submissionuploads/upload' } }, - self: 'https://rest.api/dspace-spring-rest/api/config/submissionsections/upload' }, { header: 'submit.progressbar.license', @@ -291,7 +283,6 @@ export const mockSubmissionRestResponse = [ self: { href: 'https://rest.api/dspace-spring-rest/api/config/submissionsections/license' }, config: '' }, - self: 'https://rest.api/dspace-spring-rest/api/config/submissionsections/license' } ], name: 'traditional', @@ -301,12 +292,10 @@ export const mockSubmissionRestResponse = [ sections: { href: 'https://rest.api/dspace-spring-rest/api/config/submissiondefinitions/traditional/sections' }, self: { href: 'https://rest.api/dspace-spring-rest/api/config/submissiondefinitions/traditional' } }, - self: 'https://rest.api/dspace-spring-rest/api/config/submissiondefinitions/traditional' } ], submitter: [], errors: [], - self: 'https://rest.api/dspace-spring-rest/api/submission/workspaceitems/826', type: 'workspaceitem', _links: { collection: { href: 'https://rest.api/dspace-spring-rest/api/submission/workspaceitems/826/collection' }, @@ -335,7 +324,6 @@ export const mockSubmissionObject = { groupUUID: '11cc35e5-a11d-4b64-b5b9-0052a5d15509', id: 20, uuid: 'resource-policy-20', - self: 'https://rest.api/dspace-spring-rest/api/authz/resourcePolicies/20', type: 'resourcePolicy', _links: { self: { href: 'https://rest.api/dspace-spring-rest/api/authz/resourcePolicies/20' } @@ -348,7 +336,6 @@ export const mockSubmissionObject = { content: 'https://rest.api/dspace-spring-rest/api/core/bitstreams/3f859425-ffbd-4b0e-bf91-bfeb458a7425/content', format: 'https://rest.api/dspace-spring-rest/api/core/bitstreams/3f859425-ffbd-4b0e-bf91-bfeb458a7425/format', bundleName: null, - self: 'https://rest.api/dspace-spring-rest/api/core/bitstreams/3f859425-ffbd-4b0e-bf91-bfeb458a7425', id: '3f859425-ffbd-4b0e-bf91-bfeb458a7425', uuid: '3f859425-ffbd-4b0e-bf91-bfeb458a7425', type: 'bitstream', @@ -360,7 +347,6 @@ export const mockSubmissionObject = { self: { href: 'https://rest.api/dspace-spring-rest/api/core/bitstreams/3f859425-ffbd-4b0e-bf91-bfeb458a7425' } } }, - self: 'https://rest.api/dspace-spring-rest/api/core/collections/1c11f3f1-ba1f-4f36-908a-3f1ea9a557eb', id: '1c11f3f1-ba1f-4f36-908a-3f1ea9a557eb', uuid: '1c11f3f1-ba1f-4f36-908a-3f1ea9a557eb', type: 'collection', @@ -425,7 +411,6 @@ export const mockSubmissionObject = { }, page: [] }, - self: 'https://rest.api/dspace-spring-rest/api/core/items/cae8af78-c874-4468-af79-e6c996aa8270', id: 'cae8af78-c874-4468-af79-e6c996aa8270', uuid: 'cae8af78-c874-4468-af79-e6c996aa8270', type: 'item', @@ -460,7 +445,6 @@ export const mockSubmissionObject = { self: { href: 'https://rest.api/dspace-spring-rest/api/config/submissionsections/collection' }, config: '' }, - self: 'https://rest.api/dspace-spring-rest/api/config/submissionsections/collection' }, { header: 'submit.progressbar.describe.stepone', @@ -471,7 +455,6 @@ export const mockSubmissionObject = { self: { href: 'https://rest.api/dspace-spring-rest/api/config/submissionsections/traditionalpageone' }, config: { href: 'https://rest.api/dspace-spring-rest/api/config/submissionforms/traditionalpageone' } }, - self: 'https://rest.api/dspace-spring-rest/api/config/submissionsections/traditionalpageone' }, { header: 'submit.progressbar.describe.steptwo', @@ -482,7 +465,6 @@ export const mockSubmissionObject = { self: { href: 'https://rest.api/dspace-spring-rest/api/config/submissionsections/traditionalpagetwo' }, config: { href: 'https://rest.api/dspace-spring-rest/api/config/submissionforms/traditionalpagetwo' } }, - self: 'https://rest.api/dspace-spring-rest/api/config/submissionsections/traditionalpagetwo' }, { header: 'submit.progressbar.upload', @@ -493,7 +475,6 @@ export const mockSubmissionObject = { self: { href: 'https://rest.api/dspace-spring-rest/api/config/submissionsections/upload' }, config: { href: 'https://rest.api/dspace-spring-rest/api/config/submissionuploads/upload' } }, - self: 'https://rest.api/dspace-spring-rest/api/config/submissionsections/upload' }, { header: 'submit.progressbar.license', @@ -508,7 +489,6 @@ export const mockSubmissionObject = { self: { href: 'https://rest.api/dspace-spring-rest/api/config/submissionsections/license' }, config: '' }, - self: 'https://rest.api/dspace-spring-rest/api/config/submissionsections/license' } ] }, @@ -519,7 +499,6 @@ export const mockSubmissionObject = { sections: { href: 'https://rest.api/dspace-spring-rest/api/config/submissiondefinitions/traditional/sections' }, self: { href: 'https://rest.api/dspace-spring-rest/api/config/submissiondefinitions/traditional' } }, - self: 'https://rest.api/dspace-spring-rest/api/config/submissiondefinitions/traditional', collections: { pageInfo: { elementsPerPage: 0, @@ -539,7 +518,6 @@ export const mockSubmissionObject = { email: 'dspacedemo+submit@gmail.com', requireCertificate: false, selfRegistered: false, - self: 'https://rest.api/dspace-spring-rest/api/eperson/epersons/99423c27-b642-5tg6-a9cd-6d910e68dca5', id: '99423c27-b642-5tg6-a9cd-6d910e68dca5', uuid: '99423c27-b642-5tg6-a9cd-6d910e68dca5', type: 'eperson', @@ -581,7 +559,6 @@ export const mockSubmissionObject = { ] } ], - self: 'https://rest.api/dspace-spring-rest/api/submission/workspaceitems/826', type: 'workspaceitem', _links: { collection: { href: 'https://rest.api/dspace-spring-rest/api/submission/workspaceitems/826/collection' }, @@ -609,7 +586,6 @@ export const mockSubmissionObjectNew = { groupUUID: '11cc35e5-a11d-4b64-b5b9-0052a5d15509', id: 20, uuid: 'resource-policy-20', - self: 'https://rest.api/dspace-spring-rest/api/authz/resourcePolicies/20', type: 'resourcePolicy', _links: { self: { href: 'https://rest.api/dspace-spring-rest/api/authz/resourcePolicies/20' } @@ -622,7 +598,6 @@ export const mockSubmissionObjectNew = { content: 'https://rest.api/dspace-spring-rest/api/core/bitstreams/3f859425-ffbd-4b0e-bf91-bfeb458a7425/content', format: 'https://rest.api/dspace-spring-rest/api/core/bitstreams/3f859425-ffbd-4b0e-bf91-bfeb458a7425/format', bundleName: null, - self: 'https://rest.api/dspace-spring-rest/api/core/bitstreams/3f859425-ffbd-4b0e-bf91-bfeb458a7425', id: '3f859425-ffbd-4b0e-bf91-bfeb458a7425', uuid: '3f859425-ffbd-4b0e-bf91-bfeb458a7425', type: 'bitstream', @@ -634,7 +609,6 @@ export const mockSubmissionObjectNew = { self: { href: 'https://rest.api/dspace-spring-rest/api/core/bitstreams/3f859425-ffbd-4b0e-bf91-bfeb458a7425' } } }, - self: 'https://rest.api/dspace-spring-rest/api/core/collections/45f2f3f1-ba1f-4f36-908a-3f1ea9a557eb', id: '45f2f3f1-ba1f-4f36-908a-3f1ea9a557eb', uuid: '45f2f3f1-ba1f-4f36-908a-3f1ea9a557eb', type: 'collection', @@ -699,7 +673,6 @@ export const mockSubmissionObjectNew = { }, page: [] }, - self: 'https://rest.api/dspace-spring-rest/api/core/items/cae8af78-c874-4468-af79-e6c996aa8270', id: 'cae8af78-c874-4468-af79-e6c996aa8270', uuid: 'cae8af78-c874-4468-af79-e6c996aa8270', type: 'item', @@ -734,7 +707,6 @@ export const mockSubmissionObjectNew = { self: { href: 'https://rest.api/dspace-spring-rest/api/config/submissionsections/collection' }, config: '' }, - self: 'https://rest.api/dspace-spring-rest/api/config/submissionsections/collection' }, { header: 'submit.progressbar.describe.stepone', @@ -745,7 +717,6 @@ export const mockSubmissionObjectNew = { self: { href: 'https://rest.api/dspace-spring-rest/api/config/submissionsections/traditionalpageone' }, config: { href: 'https://rest.api/dspace-spring-rest/api/config/submissionforms/traditionalpageone' } }, - self: 'https://rest.api/dspace-spring-rest/api/config/submissionsections/traditionalpageone' }, { header: 'submit.progressbar.describe.steptwo', @@ -756,7 +727,6 @@ export const mockSubmissionObjectNew = { self: { href: 'https://rest.api/dspace-spring-rest/api/config/submissionsections/traditionalpagetwo' }, config: { href: 'https://rest.api/dspace-spring-rest/api/config/submissionforms/traditionalpagetwo' } }, - self: 'https://rest.api/dspace-spring-rest/api/config/submissionsections/traditionalpagetwo' }, { header: 'submit.progressbar.upload', @@ -767,7 +737,6 @@ export const mockSubmissionObjectNew = { self: { href: 'https://rest.api/dspace-spring-rest/api/config/submissionsections/upload' }, config: { href: 'https://rest.api/dspace-spring-rest/api/config/submissionuploads/upload' } }, - self: 'https://rest.api/dspace-spring-rest/api/config/submissionsections/upload' }, { header: 'submit.progressbar.license', @@ -782,7 +751,6 @@ export const mockSubmissionObjectNew = { self: { href: 'https://rest.api/dspace-spring-rest/api/config/submissionsections/license' }, config: '' }, - self: 'https://rest.api/dspace-spring-rest/api/config/submissionsections/license' } ] }, @@ -793,7 +761,6 @@ export const mockSubmissionObjectNew = { sections: { href: 'https://rest.api/dspace-spring-rest/api/config/submissiondefinitions/traditional/sections' }, self: { href: 'https://rest.api/dspace-spring-rest/api/config/submissiondefinitions/traditional' } }, - self: 'https://rest.api/dspace-spring-rest/api/config/submissiondefinitions/traditional', collections: { pageInfo: { elementsPerPage: 0, @@ -813,7 +780,6 @@ export const mockSubmissionObjectNew = { email: 'dspacedemo+submit@gmail.com', requireCertificate: false, selfRegistered: false, - self: 'https://rest.api/dspace-spring-rest/api/eperson/epersons/99423c27-b642-4bb9-a9cd-45gh23e68dca5', id: '99423c27-b642-4bb9-a9cd-45gh23e68dca5', uuid: '99423c27-b642-4bb9-a9cd-45gh23e68dca5', type: 'eperson', @@ -838,7 +804,6 @@ export const mockSubmissionObjectNew = { lastModified: '2019-01-09T10:17:33.738+0000', sections: {}, errors: [], - self: 'https://rest.api/dspace-spring-rest/api/submission/workspaceitems/826', type: 'workspaceitem', _links: { collection: { href: 'https://rest.api/dspace-spring-rest/api/submission/workspaceitems/826/collection' }, @@ -870,7 +835,6 @@ export const mockSubmissionDefinitionResponse = { self: { href: 'https://rest.api/dspace-spring-rest/api/config/submissionsections/extraction' }, config: '' }, - self: 'https://rest.api/dspace-spring-rest/api/config/submissionsections/extraction' }, { mandatory: true, @@ -884,7 +848,6 @@ export const mockSubmissionDefinitionResponse = { self: { href: 'https://rest.api/dspace-spring-rest/api/config/submissionsections/collection' }, config: '' }, - self: 'https://rest.api/dspace-spring-rest/api/config/submissionsections/collection' }, { header: 'submit.progressbar.describe.stepone', @@ -895,7 +858,6 @@ export const mockSubmissionDefinitionResponse = { self: { href: 'https://rest.api/dspace-spring-rest/api/config/submissionsections/traditionalpageone' }, config: { href: 'https://rest.api/dspace-spring-rest/api/config/submissionforms/traditionalpageone' } }, - self: 'https://rest.api/dspace-spring-rest/api/config/submissionsections/traditionalpageone' }, { header: 'submit.progressbar.describe.steptwo', @@ -906,7 +868,6 @@ export const mockSubmissionDefinitionResponse = { self: { href: 'https://rest.api/dspace-spring-rest/api/config/submissionsections/traditionalpagetwo' }, config: { href: 'https://rest.api/dspace-spring-rest/api/config/submissionforms/traditionalpagetwo' } }, - self: 'https://rest.api/dspace-spring-rest/api/config/submissionsections/traditionalpagetwo' }, { header: 'submit.progressbar.upload', @@ -917,7 +878,6 @@ export const mockSubmissionDefinitionResponse = { self: { href: 'https://rest.api/dspace-spring-rest/api/config/submissionsections/upload' }, config: { href: 'https://rest.api/dspace-spring-rest/api/config/submissionuploads/upload' } }, - self: 'https://rest.api/dspace-spring-rest/api/config/submissionsections/upload' }, { header: 'submit.progressbar.license', @@ -932,7 +892,6 @@ export const mockSubmissionDefinitionResponse = { self: { href: 'https://rest.api/dspace-spring-rest/api/config/submissionsections/license' }, config: '' }, - self: 'https://rest.api/dspace-spring-rest/api/config/submissionsections/license' } ], name: 'traditional', @@ -942,7 +901,6 @@ export const mockSubmissionDefinitionResponse = { sections: { href: 'https://rest.api/dspace-spring-rest/api/config/submissiondefinitions/traditional/sections' }, self: { href: 'https://rest.api/dspace-spring-rest/api/config/submissiondefinitions/traditional' } }, - self: 'https://rest.api/dspace-spring-rest/api/config/submissiondefinitions/traditional' } as any; export const mockSubmissionDefinition: SubmissionDefinitionsModel = { @@ -960,7 +918,6 @@ export const mockSubmissionDefinition: SubmissionDefinitionsModel = { self: { href: 'https://rest.api/dspace-spring-rest/api/config/submissionsections/extraction' }, config: '' }, - self: 'https://rest.api/dspace-spring-rest/api/config/submissionsections/extraction' }, { mandatory: true, @@ -974,7 +931,6 @@ export const mockSubmissionDefinition: SubmissionDefinitionsModel = { self: { href: 'https://rest.api/dspace-spring-rest/api/config/submissionsections/collection' }, config: '' }, - self: 'https://rest.api/dspace-spring-rest/api/config/submissionsections/collection' }, { header: 'submit.progressbar.describe.stepone', @@ -985,7 +941,6 @@ export const mockSubmissionDefinition: SubmissionDefinitionsModel = { self: { href: 'https://rest.api/dspace-spring-rest/api/config/submissionsections/traditionalpageone' }, config: { href: 'https://rest.api/dspace-spring-rest/api/config/submissionforms/traditionalpageone' } }, - self: 'https://rest.api/dspace-spring-rest/api/config/submissionsections/traditionalpageone' }, { header: 'submit.progressbar.describe.steptwo', @@ -996,7 +951,6 @@ export const mockSubmissionDefinition: SubmissionDefinitionsModel = { self: { href: 'https://rest.api/dspace-spring-rest/api/config/submissionsections/traditionalpagetwo' }, config: { href: 'https://rest.api/dspace-spring-rest/api/config/submissionforms/traditionalpagetwo' } }, - self: 'https://rest.api/dspace-spring-rest/api/config/submissionsections/traditionalpagetwo' }, { header: 'submit.progressbar.upload', @@ -1007,7 +961,6 @@ export const mockSubmissionDefinition: SubmissionDefinitionsModel = { self: { href: 'https://rest.api/dspace-spring-rest/api/config/submissionsections/upload' }, config: { href: 'https://rest.api/dspace-spring-rest/api/config/submissionuploads/upload' } }, - self: 'https://rest.api/dspace-spring-rest/api/config/submissionsections/upload' }, { header: 'submit.progressbar.license', @@ -1022,7 +975,6 @@ export const mockSubmissionDefinition: SubmissionDefinitionsModel = { self: { href: 'https://rest.api/dspace-spring-rest/api/config/submissionsections/license' }, config: '' }, - self: 'https://rest.api/dspace-spring-rest/api/config/submissionsections/license' } ]), name: 'traditional', @@ -1032,7 +984,6 @@ export const mockSubmissionDefinition: SubmissionDefinitionsModel = { sections: { href: 'https://rest.api/dspace-spring-rest/api/config/submissiondefinitions/traditional/sections' }, self: { href: 'https://rest.api/dspace-spring-rest/api/config/submissiondefinitions/traditional' } }, - self: 'https://rest.api/dspace-spring-rest/api/config/submissiondefinitions/traditional' } as any; export const mockSubmissionState: SubmissionObjectState = Object.assign({}, { @@ -1339,7 +1290,6 @@ export const mockUploadConfigResponse = { _links: { self: { href: 'https://rest.api/dspace-spring-rest/api/config/submissionforms/bitstream-metadata' } }, - self: 'https://rest.api/dspace-spring-rest/api/config/submissionforms/bitstream-metadata' }, required: true, maxSize: 536870912, @@ -1349,7 +1299,6 @@ export const mockUploadConfigResponse = { metadata: { href: 'https://rest.api/dspace-spring-rest/api/config/submissionuploads/upload/metadata' }, self: { href: 'https://rest.api/dspace-spring-rest/api/config/submissionuploads/upload' } }, - self: 'https://rest.api/dspace-spring-rest/api/config/submissionuploads/upload' }; // Clone the object and change one property @@ -1388,7 +1337,6 @@ export const mockAccessConditionOptions = [ export const mockGroup = Object.assign(new Group(), { handle: null, permanent: true, - self: 'https://rest.api/dspace-spring-rest/api/eperson/groups/123456-g1', id: '123456-g', uuid: '123456-g', type: 'group', diff --git a/src/app/shared/object-list/my-dspace-result-list-element/workspace-item-search-result/workspace-item-search-result-list-element.component.spec.ts b/src/app/shared/object-list/my-dspace-result-list-element/workspace-item-search-result/workspace-item-search-result-list-element.component.spec.ts index 95dc3745de..87ffc86856 100644 --- a/src/app/shared/object-list/my-dspace-result-list-element/workspace-item-search-result/workspace-item-search-result-list-element.component.spec.ts +++ b/src/app/shared/object-list/my-dspace-result-list-element/workspace-item-search-result/workspace-item-search-result-list-element.component.spec.ts @@ -8,7 +8,6 @@ import { ItemDataService } from '../../../../core/data/item-data.service'; import { Item } from '../../../../core/shared/item.model'; import { WorkspaceItem } from '../../../../core/submission/models/workspaceitem.model'; -import { getMockLinkService } from '../../../mocks/mock-link-service'; import { MyDspaceItemStatusType } from '../../../object-collection/shared/mydspace-item-status/my-dspace-item-status-type'; import { WorkflowItemSearchResult } from '../../../object-collection/shared/workflow-item-search-result.model'; import { createSuccessfulRemoteDataObject } from '../../../testing/utils'; @@ -89,7 +88,6 @@ describe('WorkspaceItemSearchResultListElementComponent', () => { }); it('should have properly status', () => { - expect(linkService.resolveLink).toHaveBeenCalled(); expect(component.status).toEqual(MyDspaceItemStatusType.WORKSPACE); }); }); diff --git a/src/app/submission/form/submission-form.component.ts b/src/app/submission/form/submission-form.component.ts index 3ea07f9ae7..0b8cfce619 100644 --- a/src/app/submission/form/submission-form.component.ts +++ b/src/app/submission/form/submission-form.component.ts @@ -1,19 +1,19 @@ import { ChangeDetectorRef, Component, Input, OnChanges, OnDestroy, SimpleChanges } from '@angular/core'; -import { of as observableOf, Observable, Subscription } from 'rxjs'; -import { distinctUntilChanged, filter, flatMap, map, switchMap } from 'rxjs/operators'; +import { Observable, of as observableOf, Subscription } from 'rxjs'; +import { distinctUntilChanged, filter, map, switchMap } from 'rxjs/operators'; +import { AuthService } from '../../core/auth/auth.service'; +import { SubmissionDefinitionsModel } from '../../core/config/models/config-submission-definitions.model'; +import { Collection } from '../../core/shared/collection.model'; +import { HALEndpointService } from '../../core/shared/hal-endpoint.service'; +import { SubmissionObject } from '../../core/submission/models/submission-object.model'; +import { WorkspaceitemSectionsObject } from '../../core/submission/models/workspaceitem-sections.model'; import { hasValue, isNotEmpty } from '../../shared/empty.util'; -import { SubmissionObjectEntry } from '../objects/submission-objects.reducer'; -import { WorkspaceitemSectionsObject } from '../../core/submission/models/workspaceitem-sections.model'; -import { SubmissionDefinitionsModel } from '../../core/config/models/config-submission-definitions.model'; -import { SubmissionService } from '../submission.service'; -import { AuthService } from '../../core/auth/auth.service'; -import { SectionDataObject } from '../sections/models/section-data.model'; import { UploaderOptions } from '../../shared/uploader/uploader-options.model'; -import { HALEndpointService } from '../../core/shared/hal-endpoint.service'; -import { Collection } from '../../core/shared/collection.model'; -import { SubmissionObject } from '../../core/submission/models/submission-object.model'; +import { SubmissionObjectEntry } from '../objects/submission-objects.reducer'; +import { SectionDataObject } from '../sections/models/section-data.model'; +import { SubmissionService } from '../submission.service'; /** * This component represents the submission form. @@ -189,7 +189,7 @@ export class SubmissionFormComponent implements OnChanges, OnDestroy { this.submissionService.resetSubmissionObject( this.collectionId, this.submissionId, - submissionObject.self, + submissionObject._links.self.href, this.submissionDefinition, this.sections); } else { From 7f76769bff34459f4524707f89498a0f8499bf27 Mon Sep 17 00:00:00 2001 From: Art Lowel Date: Mon, 17 Feb 2020 10:30:16 +0100 Subject: [PATCH 25/38] switch to typedObject decorator, which no longer needs explict type param --- src/app/core/auth/models/auth-status.model.ts | 4 ++-- .../core/cache/builders/build-decorators.ts | 19 ++++--------------- .../config-submission-definition.model.ts | 4 ++-- .../config-submission-definitions.model.ts | 4 ++-- .../models/config-submission-form.model.ts | 4 ++-- .../models/config-submission-forms.model.ts | 4 ++-- .../models/config-submission-section.model.ts | 4 ++-- .../config-submission-sections.model.ts | 4 ++-- .../models/config-submission-uploads.model.ts | 4 ++-- .../data/base-response-parsing.service.ts | 6 +++--- src/app/core/eperson/models/eperson.model.ts | 4 ++-- src/app/core/eperson/models/group.model.ts | 4 ++-- .../integration/models/authority.value.ts | 4 ++-- src/app/core/metadata/metadata-field.model.ts | 4 ++-- .../core/metadata/metadata-schema.model.ts | 4 ++-- .../registry-metadatafields-response.model.ts | 4 ++-- src/app/core/shared/bitstream-format.model.ts | 4 ++-- src/app/core/shared/bitstream.model.ts | 4 ++-- .../core/shared/browse-definition.model.ts | 4 ++-- src/app/core/shared/browse-entry.model.ts | 4 ++-- src/app/core/shared/bundle.model.ts | 4 ++-- src/app/core/shared/collection.model.ts | 4 ++-- src/app/core/shared/community.model.ts | 4 ++-- src/app/core/shared/dspace-object.model.ts | 4 ++-- .../shared/external-source-entry.model.ts | 4 ++-- src/app/core/shared/external-source.model.ts | 4 ++-- .../item-relationships/item-type.model.ts | 4 ++-- .../relationship-type.model.ts | 4 ++-- .../item-relationships/relationship.model.ts | 4 ++-- src/app/core/shared/item.model.ts | 4 ++-- src/app/core/shared/license.model.ts | 4 ++-- src/app/core/shared/resource-policy.model.ts | 4 ++-- src/app/core/shared/site.model.ts | 4 ++-- .../submission/models/workflowitem.model.ts | 4 ++-- .../submission/models/workspaceitem.model.ts | 4 ++-- .../tasks/models/claimed-task-object.model.ts | 4 ++-- .../tasks/models/pool-task-object.model.ts | 4 ++-- .../core/tasks/models/task-object.model.ts | 4 ++-- 38 files changed, 79 insertions(+), 90 deletions(-) diff --git a/src/app/core/auth/models/auth-status.model.ts b/src/app/core/auth/models/auth-status.model.ts index 86ae9f3a49..df6cc5490f 100644 --- a/src/app/core/auth/models/auth-status.model.ts +++ b/src/app/core/auth/models/auth-status.model.ts @@ -1,6 +1,6 @@ import { autoserialize, deserialize, deserializeAs } from 'cerialize'; import { Observable } from 'rxjs'; -import { link, resourceType } from '../../cache/builders/build-decorators'; +import { link, typedObject } from '../../cache/builders/build-decorators'; import { IDToUUIDSerializer } from '../../cache/id-to-uuid-serializer'; import { CacheableObject } from '../../cache/object-cache.reducer'; import { RemoteData } from '../../data/remote-data'; @@ -16,7 +16,7 @@ import { AuthTokenInfo } from './auth-token-info.model'; /** * Object that represents the authenticated status of a user */ -@resourceType(AuthStatus.type) +@typedObject export class AuthStatus implements CacheableObject { static type = AUTH_STATUS; diff --git a/src/app/core/cache/builders/build-decorators.ts b/src/app/core/cache/builders/build-decorators.ts index 17bbc4a8b4..3c1415b9a4 100644 --- a/src/app/core/cache/builders/build-decorators.ts +++ b/src/app/core/cache/builders/build-decorators.ts @@ -1,12 +1,11 @@ import 'reflect-metadata'; import { hasNoValue, hasValue } from '../../../shared/empty.util'; import { DataService } from '../../data/data.service'; -import { PaginatedList } from '../../data/paginated-list'; import { GenericConstructor } from '../../shared/generic-constructor'; import { HALResource } from '../../shared/hal-resource.model'; -import { CacheableObject, TypedObject } from '../object-cache.reducer'; import { ResourceType } from '../../shared/resource-type'; +import { CacheableObject, TypedObject } from '../object-cache.reducer'; const resolvedLinkKey = Symbol('resolvedLink'); @@ -17,12 +16,10 @@ const linkMap = new Map(); /** * Decorator function to map a ResourceType to its class - * @param value The ResourceType to map + * @param target The contructor of the typed class to map */ -export function resourceType(value: ResourceType) { - return function decorator(objectConstructor: GenericConstructor) { - typeMap.set(value.value, objectConstructor); - } +export function typedObject(target: typeof TypedObject) { + typeMap.set(target.type.value, target); } /** @@ -74,14 +71,6 @@ export function resolvedLink, K extends keyof T>(prov }; } -export function getResolvedLinkMetadata(target: any, propertyKey: string) { - return Reflect.getMetadata(resolvedLinkKey, target, propertyKey); -} - -export function getResolvedLinks(target: any) { - return resolvedLinkMap.get(target); -} - export class LinkDefinition { resourceType: ResourceType; isList = false; diff --git a/src/app/core/config/models/config-submission-definition.model.ts b/src/app/core/config/models/config-submission-definition.model.ts index 54ca948e62..1437ae32b1 100644 --- a/src/app/core/config/models/config-submission-definition.model.ts +++ b/src/app/core/config/models/config-submission-definition.model.ts @@ -1,5 +1,5 @@ import { autoserialize, deserialize } from 'cerialize'; -import { resourceType } from '../../cache/builders/build-decorators'; +import { typedObject } from '../../cache/builders/build-decorators'; import { PaginatedList } from '../../data/paginated-list'; import { HALLink } from '../../shared/hal-link.model'; import { ResourceType } from '../../shared/resource-type'; @@ -9,7 +9,7 @@ import { ConfigObject } from './config.model'; /** * Class for the configuration describing the submission */ -@resourceType(SubmissionDefinitionModel.type) +@typedObject export class SubmissionDefinitionModel extends ConfigObject { static type = new ResourceType('submissiondefinition'); diff --git a/src/app/core/config/models/config-submission-definitions.model.ts b/src/app/core/config/models/config-submission-definitions.model.ts index 534f044b08..1fdf571806 100644 --- a/src/app/core/config/models/config-submission-definitions.model.ts +++ b/src/app/core/config/models/config-submission-definitions.model.ts @@ -1,9 +1,9 @@ import { inheritSerialization } from 'cerialize'; -import { resourceType } from '../../cache/builders/build-decorators'; +import { typedObject } from '../../cache/builders/build-decorators'; import { SubmissionDefinitionModel } from './config-submission-definition.model'; import { ResourceType } from '../../shared/resource-type'; -@resourceType(SubmissionDefinitionsModel.type) +@typedObject @inheritSerialization(SubmissionDefinitionModel) export class SubmissionDefinitionsModel extends SubmissionDefinitionModel { static type = new ResourceType('submissiondefinitions'); diff --git a/src/app/core/config/models/config-submission-form.model.ts b/src/app/core/config/models/config-submission-form.model.ts index 3fac904d45..d3fcfa9738 100644 --- a/src/app/core/config/models/config-submission-form.model.ts +++ b/src/app/core/config/models/config-submission-form.model.ts @@ -1,5 +1,5 @@ import { autoserialize, inheritSerialization } from 'cerialize'; -import { resourceType } from '../../cache/builders/build-decorators'; +import { typedObject } from '../../cache/builders/build-decorators'; import { ConfigObject } from './config.model'; import { FormFieldModel } from '../../../shared/form/builder/models/form-field.model'; import { ResourceType } from '../../shared/resource-type'; @@ -14,7 +14,7 @@ export interface FormRowModel { /** * A model class for a NormalizedObject. */ -@resourceType(SubmissionFormModel.type) +@typedObject @inheritSerialization(ConfigObject) export class SubmissionFormModel extends ConfigObject { static type = new ResourceType('submissionform'); diff --git a/src/app/core/config/models/config-submission-forms.model.ts b/src/app/core/config/models/config-submission-forms.model.ts index aabce33ea5..8130bf3264 100644 --- a/src/app/core/config/models/config-submission-forms.model.ts +++ b/src/app/core/config/models/config-submission-forms.model.ts @@ -1,12 +1,12 @@ import { inheritSerialization } from 'cerialize'; -import { resourceType } from '../../cache/builders/build-decorators'; +import { typedObject } from '../../cache/builders/build-decorators'; import { SubmissionFormModel } from './config-submission-form.model'; import { ResourceType } from '../../shared/resource-type'; /** * A model class for a NormalizedObject. */ -@resourceType(SubmissionFormsModel.type) +@typedObject @inheritSerialization(SubmissionFormModel) export class SubmissionFormsModel extends SubmissionFormModel { static type = new ResourceType('submissionforms'); diff --git a/src/app/core/config/models/config-submission-section.model.ts b/src/app/core/config/models/config-submission-section.model.ts index 3c657c3d2a..d589e6a648 100644 --- a/src/app/core/config/models/config-submission-section.model.ts +++ b/src/app/core/config/models/config-submission-section.model.ts @@ -1,6 +1,6 @@ import { autoserialize, deserialize } from 'cerialize'; import { SectionsType } from '../../../submission/sections/sections-type'; -import { resourceType } from '../../cache/builders/build-decorators'; +import { typedObject } from '../../cache/builders/build-decorators'; import { HALLink } from '../../shared/hal-link.model'; import { ResourceType } from '../../shared/resource-type'; import { ConfigObject } from './config.model'; @@ -13,7 +13,7 @@ export interface SubmissionSectionVisibility { other: any } -@resourceType(SubmissionSectionModel.type) +@typedObject export class SubmissionSectionModel extends ConfigObject { static type = new ResourceType('submissionsection'); diff --git a/src/app/core/config/models/config-submission-sections.model.ts b/src/app/core/config/models/config-submission-sections.model.ts index a87e0cb3d6..7f78712273 100644 --- a/src/app/core/config/models/config-submission-sections.model.ts +++ b/src/app/core/config/models/config-submission-sections.model.ts @@ -1,9 +1,9 @@ import { inheritSerialization } from 'cerialize'; -import { resourceType } from '../../cache/builders/build-decorators'; +import { typedObject } from '../../cache/builders/build-decorators'; import { SubmissionSectionModel } from './config-submission-section.model'; import { ResourceType } from '../../shared/resource-type'; -@resourceType(SubmissionSectionsModel.type) +@typedObject @inheritSerialization(SubmissionSectionModel) export class SubmissionSectionsModel extends SubmissionSectionModel { static type = new ResourceType('submissionsections'); diff --git a/src/app/core/config/models/config-submission-uploads.model.ts b/src/app/core/config/models/config-submission-uploads.model.ts index 6a9aace270..b88ce4e0f8 100644 --- a/src/app/core/config/models/config-submission-uploads.model.ts +++ b/src/app/core/config/models/config-submission-uploads.model.ts @@ -1,11 +1,11 @@ import { autoserialize } from 'cerialize'; -import { resourceType } from '../../cache/builders/build-decorators'; +import { typedObject } from '../../cache/builders/build-decorators'; import { ConfigObject } from './config.model'; import { AccessConditionOption } from './config-access-condition-option.model'; import { SubmissionFormsModel } from './config-submission-forms.model'; import { ResourceType } from '../../shared/resource-type'; -@resourceType(SubmissionUploadsModel.type) +@typedObject export class SubmissionUploadsModel extends ConfigObject { static type = new ResourceType('submissionupload'); /** diff --git a/src/app/core/data/base-response-parsing.service.ts b/src/app/core/data/base-response-parsing.service.ts index a1aea3ee38..3615ab4023 100644 --- a/src/app/core/data/base-response-parsing.service.ts +++ b/src/app/core/data/base-response-parsing.service.ts @@ -111,10 +111,10 @@ export abstract class BaseResponseParsingService { protected deserialize(obj): any { const type: string = obj.type; if (hasValue(type)) { - const normObjConstructor = getClassForType(type) as GenericConstructor; + const objConstructor = getClassForType(type) as GenericConstructor; - if (hasValue(normObjConstructor)) { - const serializer = new this.serializerConstructor(normObjConstructor); + if (hasValue(objConstructor)) { + const serializer = new this.serializerConstructor(objConstructor); return serializer.deserialize(obj); } else { return null; diff --git a/src/app/core/eperson/models/eperson.model.ts b/src/app/core/eperson/models/eperson.model.ts index d7048eb6ba..a0e6266311 100644 --- a/src/app/core/eperson/models/eperson.model.ts +++ b/src/app/core/eperson/models/eperson.model.ts @@ -1,6 +1,6 @@ import { autoserialize, deserialize, inheritSerialization } from 'cerialize'; import { Observable } from 'rxjs'; -import { link, resourceType } from '../../cache/builders/build-decorators'; +import { link, typedObject } from '../../cache/builders/build-decorators'; import { PaginatedList } from '../../data/paginated-list'; import { RemoteData } from '../../data/remote-data'; @@ -10,7 +10,7 @@ import { EPERSON } from './eperson.resource-type'; import { Group } from './group.model'; import { GROUP } from './group.resource-type'; -@resourceType(EPerson.type) +@typedObject @inheritSerialization(DSpaceObject) export class EPerson extends DSpaceObject { static type = EPERSON; diff --git a/src/app/core/eperson/models/group.model.ts b/src/app/core/eperson/models/group.model.ts index 28a121d410..3dae9bf864 100644 --- a/src/app/core/eperson/models/group.model.ts +++ b/src/app/core/eperson/models/group.model.ts @@ -1,6 +1,6 @@ import { autoserialize, deserialize, inheritSerialization } from 'cerialize'; import { Observable } from 'rxjs'; -import { link, resourceType } from '../../cache/builders/build-decorators'; +import { link, typedObject } from '../../cache/builders/build-decorators'; import { PaginatedList } from '../../data/paginated-list'; import { RemoteData } from '../../data/remote-data'; @@ -8,7 +8,7 @@ import { DSpaceObject } from '../../shared/dspace-object.model'; import { HALLink } from '../../shared/hal-link.model'; import { GROUP } from './group.resource-type'; -@resourceType(Group.type) +@typedObject @inheritSerialization(DSpaceObject) export class Group extends DSpaceObject { static type = GROUP; diff --git a/src/app/core/integration/models/authority.value.ts b/src/app/core/integration/models/authority.value.ts index 55e0fba99d..9fb64a2555 100644 --- a/src/app/core/integration/models/authority.value.ts +++ b/src/app/core/integration/models/authority.value.ts @@ -2,7 +2,7 @@ import { autoserialize, deserialize, inheritSerialization } from 'cerialize'; import { isNotEmpty } from '../../../shared/empty.util'; import { PLACEHOLDER_PARENT_METADATA } from '../../../shared/form/builder/ds-dynamic-form-ui/models/relation-group/dynamic-relation-group.model'; import { OtherInformation } from '../../../shared/form/builder/models/form-field-metadata-value.model'; -import { resourceType } from '../../cache/builders/build-decorators'; +import { typedObject } from '../../cache/builders/build-decorators'; import { HALLink } from '../../shared/hal-link.model'; import { MetadataValueInterface } from '../../shared/metadata.models'; import { AUTHORITY_VALUE } from './authority.resource-type'; @@ -11,7 +11,7 @@ import { IntegrationModel } from './integration.model'; /** * Class representing an authority object */ -@resourceType(AuthorityValue.type) +@typedObject @inheritSerialization(IntegrationModel) export class AuthorityValue extends IntegrationModel implements MetadataValueInterface { static type = AUTHORITY_VALUE; diff --git a/src/app/core/metadata/metadata-field.model.ts b/src/app/core/metadata/metadata-field.model.ts index d4931a127d..44a0f14e82 100644 --- a/src/app/core/metadata/metadata-field.model.ts +++ b/src/app/core/metadata/metadata-field.model.ts @@ -1,7 +1,7 @@ import { autoserialize, deserialize } from 'cerialize'; import { isNotEmpty } from '../../shared/empty.util'; import { ListableObject } from '../../shared/object-collection/shared/listable-object.model'; -import { link, resourceType } from '../cache/builders/build-decorators'; +import { link, typedObject } from '../cache/builders/build-decorators'; import { GenericConstructor } from '../shared/generic-constructor'; import { HALLink } from '../shared/hal-link.model'; import { HALResource } from '../shared/hal-resource.model'; @@ -13,7 +13,7 @@ import { MetadataSchema } from './metadata-schema.model'; /** * Class the represents a metadata field */ -@resourceType(MetadataField.type) +@typedObject export class MetadataField extends ListableObject implements HALResource { static type = METADATA_FIELD; diff --git a/src/app/core/metadata/metadata-schema.model.ts b/src/app/core/metadata/metadata-schema.model.ts index 9adfcc2479..d4d94b8780 100644 --- a/src/app/core/metadata/metadata-schema.model.ts +++ b/src/app/core/metadata/metadata-schema.model.ts @@ -1,6 +1,6 @@ import { autoserialize, deserialize } from 'cerialize'; import { ListableObject } from '../../shared/object-collection/shared/listable-object.model'; -import { resourceType } from '../cache/builders/build-decorators'; +import { typedObject } from '../cache/builders/build-decorators'; import { GenericConstructor } from '../shared/generic-constructor'; import { HALLink } from '../shared/hal-link.model'; import { HALResource } from '../shared/hal-resource.model'; @@ -11,7 +11,7 @@ import { METADATA_SCHEMA } from './metadata-schema.resource-type'; /** * Class that represents a metadata schema */ -@resourceType(MetadataSchema.type) +@typedObject export class MetadataSchema extends ListableObject implements HALResource { static type = METADATA_SCHEMA; diff --git a/src/app/core/registry/registry-metadatafields-response.model.ts b/src/app/core/registry/registry-metadatafields-response.model.ts index 2bdaade0b7..5dc492ab0f 100644 --- a/src/app/core/registry/registry-metadatafields-response.model.ts +++ b/src/app/core/registry/registry-metadatafields-response.model.ts @@ -1,5 +1,5 @@ import { autoserialize, deserialize } from 'cerialize'; -import { resourceType } from '../cache/builders/build-decorators'; +import { typedObject } from '../cache/builders/build-decorators'; import { MetadataField } from '../metadata/metadata-field.model'; import { METADATA_FIELD } from '../metadata/metadata-field.resource-type'; import { HALLink } from '../shared/hal-link.model'; @@ -10,7 +10,7 @@ import { excludeFromEquals } from '../utilities/equals.decorators'; /** * Class that represents a response with a registry's metadata fields */ -@resourceType(RegistryMetadatafieldsResponse.type) +@typedObject export class RegistryMetadatafieldsResponse { static type = METADATA_FIELD; diff --git a/src/app/core/shared/bitstream-format.model.ts b/src/app/core/shared/bitstream-format.model.ts index 0ba284fcc5..1fdb707aaf 100644 --- a/src/app/core/shared/bitstream-format.model.ts +++ b/src/app/core/shared/bitstream-format.model.ts @@ -1,5 +1,5 @@ import { autoserialize, deserialize, deserializeAs } from 'cerialize'; -import { resourceType } from '../cache/builders/build-decorators'; +import { typedObject } from '../cache/builders/build-decorators'; import { IDToUUIDSerializer } from '../cache/id-to-uuid-serializer'; import { CacheableObject } from '../cache/object-cache.reducer'; import { excludeFromEquals } from '../utilities/equals.decorators'; @@ -11,7 +11,7 @@ import { ResourceType } from './resource-type'; /** * Model class for a Bitstream Format */ -@resourceType(BitstreamFormat.type) +@typedObject export class BitstreamFormat implements CacheableObject { static type = BITSTREAM_FORMAT; diff --git a/src/app/core/shared/bitstream.model.ts b/src/app/core/shared/bitstream.model.ts index da8c39cd8b..d4060f96a6 100644 --- a/src/app/core/shared/bitstream.model.ts +++ b/src/app/core/shared/bitstream.model.ts @@ -1,6 +1,6 @@ import { autoserialize, deserialize, inheritSerialization } from 'cerialize'; import { Observable } from 'rxjs'; -import { link, resourceType } from '../cache/builders/build-decorators'; +import { link, typedObject } from '../cache/builders/build-decorators'; import { RemoteData } from '../data/remote-data'; import { BitstreamFormat } from './bitstream-format.model'; import { BITSTREAM_FORMAT } from './bitstream-format.resource-type'; @@ -9,7 +9,7 @@ import { DSpaceObject } from './dspace-object.model'; import { HALLink } from './hal-link.model'; import { HALResource } from './hal-resource.model'; -@resourceType(Bitstream.type) +@typedObject @inheritSerialization(DSpaceObject) export class Bitstream extends DSpaceObject implements HALResource { static type = BITSTREAM; diff --git a/src/app/core/shared/browse-definition.model.ts b/src/app/core/shared/browse-definition.model.ts index 73badd4729..e1d0e0bf01 100644 --- a/src/app/core/shared/browse-definition.model.ts +++ b/src/app/core/shared/browse-definition.model.ts @@ -1,5 +1,5 @@ import { autoserialize, autoserializeAs, deserialize } from 'cerialize'; -import { resourceType } from '../cache/builders/build-decorators'; +import { typedObject } from '../cache/builders/build-decorators'; import { TypedObject } from '../cache/object-cache.reducer'; import { excludeFromEquals } from '../utilities/equals.decorators'; import { BROWSE_DEFINITION } from './browse-definition.resource-type'; @@ -7,7 +7,7 @@ import { HALLink } from './hal-link.model'; import { ResourceType } from './resource-type'; import { SortOption } from './sort-option.model'; -@resourceType(BrowseDefinition.type) +@typedObject export class BrowseDefinition implements TypedObject { static type = BROWSE_DEFINITION; diff --git a/src/app/core/shared/browse-entry.model.ts b/src/app/core/shared/browse-entry.model.ts index a5e444ae5a..b5e971d069 100644 --- a/src/app/core/shared/browse-entry.model.ts +++ b/src/app/core/shared/browse-entry.model.ts @@ -1,6 +1,6 @@ import { autoserialize, autoserializeAs, deserialize } from 'cerialize'; import { ListableObject } from '../../shared/object-collection/shared/listable-object.model'; -import { resourceType } from '../cache/builders/build-decorators'; +import { typedObject } from '../cache/builders/build-decorators'; import { TypedObject } from '../cache/object-cache.reducer'; import { excludeFromEquals } from '../utilities/equals.decorators'; import { BROWSE_ENTRY } from './browse-entry.resource-type'; @@ -11,7 +11,7 @@ import { ResourceType } from './resource-type'; /** * Class object representing a browse entry */ -@resourceType(BrowseEntry.type) +@typedObject export class BrowseEntry extends ListableObject implements TypedObject { static type = BROWSE_ENTRY; diff --git a/src/app/core/shared/bundle.model.ts b/src/app/core/shared/bundle.model.ts index a5d1818a0d..c2fb25f5b7 100644 --- a/src/app/core/shared/bundle.model.ts +++ b/src/app/core/shared/bundle.model.ts @@ -1,10 +1,10 @@ import { deserialize, inheritSerialization } from 'cerialize'; -import { resourceType } from '../cache/builders/build-decorators'; +import { typedObject } from '../cache/builders/build-decorators'; import { BUNDLE } from './bundle.resource-type'; import { DSpaceObject } from './dspace-object.model'; import { HALLink } from './hal-link.model'; -@resourceType(Bundle.type) +@typedObject @inheritSerialization(DSpaceObject) export class Bundle extends DSpaceObject { static type = BUNDLE; diff --git a/src/app/core/shared/collection.model.ts b/src/app/core/shared/collection.model.ts index d7508c27cb..33a8fd444e 100644 --- a/src/app/core/shared/collection.model.ts +++ b/src/app/core/shared/collection.model.ts @@ -1,6 +1,6 @@ import { autoserialize, deserialize, inheritSerialization } from 'cerialize'; import { Observable } from 'rxjs'; -import { link, resourceType } from '../cache/builders/build-decorators'; +import { link, typedObject } from '../cache/builders/build-decorators'; import { PaginatedList } from '../data/paginated-list'; import { RemoteData } from '../data/remote-data'; import { Bitstream } from './bitstream.model'; @@ -13,7 +13,7 @@ import { LICENSE } from './license.resource-type'; import { ResourcePolicy } from './resource-policy.model'; import { RESOURCE_POLICY } from './resource-policy.resource-type'; -@resourceType(Collection.type) +@typedObject @inheritSerialization(DSpaceObject) export class Collection extends DSpaceObject { static type = COLLECTION; diff --git a/src/app/core/shared/community.model.ts b/src/app/core/shared/community.model.ts index b1b91a8207..66e71176f3 100644 --- a/src/app/core/shared/community.model.ts +++ b/src/app/core/shared/community.model.ts @@ -1,6 +1,6 @@ import { autoserialize, deserialize, inheritSerialization } from 'cerialize'; import { Observable } from 'rxjs'; -import { link, resourceType } from '../cache/builders/build-decorators'; +import { link, typedObject } from '../cache/builders/build-decorators'; import { PaginatedList } from '../data/paginated-list'; import { RemoteData } from '../data/remote-data'; import { Bitstream } from './bitstream.model'; @@ -11,7 +11,7 @@ import { COMMUNITY } from './community.resource-type'; import { DSpaceObject } from './dspace-object.model'; import { HALLink } from './hal-link.model'; -@resourceType(Community.type) +@typedObject @inheritSerialization(DSpaceObject) export class Community extends DSpaceObject { static type = COMMUNITY; diff --git a/src/app/core/shared/dspace-object.model.ts b/src/app/core/shared/dspace-object.model.ts index ff9981079a..7276926b50 100644 --- a/src/app/core/shared/dspace-object.model.ts +++ b/src/app/core/shared/dspace-object.model.ts @@ -1,7 +1,7 @@ import { autoserialize, autoserializeAs, deserialize, deserializeAs } from 'cerialize'; import { hasNoValue, isUndefined } from '../../shared/empty.util'; import { ListableObject } from '../../shared/object-collection/shared/listable-object.model'; -import { resourceType } from '../cache/builders/build-decorators'; +import { typedObject } from '../cache/builders/build-decorators'; import { CacheableObject } from '../cache/object-cache.reducer'; import { excludeFromEquals } from '../utilities/equals.decorators'; import { DSPACE_OBJECT } from './dspace-object.resource-type'; @@ -20,7 +20,7 @@ import { ResourceType } from './resource-type'; /** * An abstract model class for a DSpaceObject. */ -@resourceType(DSpaceObject.type) +@typedObject export class DSpaceObject extends ListableObject implements CacheableObject { /** * A string representing the kind of DSpaceObject, e.g. community, item, … diff --git a/src/app/core/shared/external-source-entry.model.ts b/src/app/core/shared/external-source-entry.model.ts index cfab5f93d6..876ca12f83 100644 --- a/src/app/core/shared/external-source-entry.model.ts +++ b/src/app/core/shared/external-source-entry.model.ts @@ -1,6 +1,6 @@ import { autoserialize, autoserializeAs, deserialize } from 'cerialize'; import { ListableObject } from '../../shared/object-collection/shared/listable-object.model'; -import { resourceType } from '../cache/builders/build-decorators'; +import { typedObject } from '../cache/builders/build-decorators'; import { excludeFromEquals } from '../utilities/equals.decorators'; import { EXTERNAL_SOURCE_ENTRY } from './external-source-entry.resource-type'; import { GenericConstructor } from './generic-constructor'; @@ -11,7 +11,7 @@ import { ResourceType } from './resource-type'; /** * Model class for a single entry from an external source */ -@resourceType(ExternalSourceEntry.type) +@typedObject export class ExternalSourceEntry extends ListableObject { static type = EXTERNAL_SOURCE_ENTRY; diff --git a/src/app/core/shared/external-source.model.ts b/src/app/core/shared/external-source.model.ts index f83d7a82db..718ac4ff49 100644 --- a/src/app/core/shared/external-source.model.ts +++ b/src/app/core/shared/external-source.model.ts @@ -1,5 +1,5 @@ import { autoserialize, deserialize, inheritSerialization } from 'cerialize'; -import { resourceType } from '../cache/builders/build-decorators'; +import { typedObject } from '../cache/builders/build-decorators'; import { CacheableObject } from '../cache/object-cache.reducer'; import { excludeFromEquals } from '../utilities/equals.decorators'; import { EXTERNAL_SOURCE } from './external-source.resource-type'; @@ -9,7 +9,7 @@ import { ResourceType } from './resource-type'; /** * Model class for an external source */ -@resourceType(ExternalSource.type) +@typedObject export class ExternalSource extends CacheableObject { static type = EXTERNAL_SOURCE; diff --git a/src/app/core/shared/item-relationships/item-type.model.ts b/src/app/core/shared/item-relationships/item-type.model.ts index e63c01ea8e..7ff7ba9e74 100644 --- a/src/app/core/shared/item-relationships/item-type.model.ts +++ b/src/app/core/shared/item-relationships/item-type.model.ts @@ -1,5 +1,5 @@ import { autoserialize, deserialize, deserializeAs } from 'cerialize'; -import { resourceType } from '../../cache/builders/build-decorators'; +import { typedObject } from '../../cache/builders/build-decorators'; import { IDToUUIDSerializer } from '../../cache/id-to-uuid-serializer'; import { CacheableObject } from '../../cache/object-cache.reducer'; import { excludeFromEquals } from '../../utilities/equals.decorators'; @@ -10,7 +10,7 @@ import { ITEM_TYPE } from './item-type.resource-type'; /** * Describes a type of Item */ -@resourceType(ItemType.type) +@typedObject export class ItemType implements CacheableObject { static type = ITEM_TYPE; diff --git a/src/app/core/shared/item-relationships/relationship-type.model.ts b/src/app/core/shared/item-relationships/relationship-type.model.ts index 087b984c41..437203bd51 100644 --- a/src/app/core/shared/item-relationships/relationship-type.model.ts +++ b/src/app/core/shared/item-relationships/relationship-type.model.ts @@ -1,6 +1,6 @@ import { autoserialize, deserialize, deserializeAs } from 'cerialize'; import { Observable } from 'rxjs'; -import { link, resourceType } from '../../cache/builders/build-decorators'; +import { link, typedObject } from '../../cache/builders/build-decorators'; import { IDToUUIDSerializer } from '../../cache/id-to-uuid-serializer'; import { CacheableObject } from '../../cache/object-cache.reducer'; import { RemoteData } from '../../data/remote-data'; @@ -14,7 +14,7 @@ import { RELATIONSHIP_TYPE } from './relationship-type.resource-type'; /** * Describes a type of Relationship between multiple possible Items */ -@resourceType(RelationshipType.type) +@typedObject export class RelationshipType implements CacheableObject { static type = RELATIONSHIP_TYPE; diff --git a/src/app/core/shared/item-relationships/relationship.model.ts b/src/app/core/shared/item-relationships/relationship.model.ts index 5d9251c0a4..4103208d89 100644 --- a/src/app/core/shared/item-relationships/relationship.model.ts +++ b/src/app/core/shared/item-relationships/relationship.model.ts @@ -1,6 +1,6 @@ import { autoserialize, deserialize, serialize, deserializeAs } from 'cerialize'; import { Observable } from 'rxjs'; -import { link, resourceType } from '../../cache/builders/build-decorators'; +import { link, typedObject } from '../../cache/builders/build-decorators'; import { IDToUUIDSerializer } from '../../cache/id-to-uuid-serializer'; import { CacheableObject } from '../../cache/object-cache.reducer'; import { RemoteData } from '../../data/remote-data'; @@ -16,7 +16,7 @@ import { RELATIONSHIP } from './relationship.resource-type'; /** * Describes a Relationship between two Items */ -@resourceType(Relationship.type) +@typedObject export class Relationship implements CacheableObject { static type = RELATIONSHIP; diff --git a/src/app/core/shared/item.model.ts b/src/app/core/shared/item.model.ts index 5221176ad5..e20cc1dbac 100644 --- a/src/app/core/shared/item.model.ts +++ b/src/app/core/shared/item.model.ts @@ -3,7 +3,7 @@ import { Observable } from 'rxjs/internal/Observable'; import { isEmpty } from '../../shared/empty.util'; import { DEFAULT_ENTITY_TYPE } from '../../shared/metadata-representation/metadata-representation.decorator'; import { ListableObject } from '../../shared/object-collection/shared/listable-object.model'; -import { link, resourceType } from '../cache/builders/build-decorators'; +import { link, typedObject } from '../cache/builders/build-decorators'; import { PaginatedList } from '../data/paginated-list'; import { RemoteData } from '../data/remote-data'; import { Bundle } from './bundle.model'; @@ -21,7 +21,7 @@ import { ITEM } from './item.resource-type'; /** * Class representing a DSpace Item */ -@resourceType(Item.type) +@typedObject @inheritSerialization(DSpaceObject) export class Item extends DSpaceObject { static type = ITEM; diff --git a/src/app/core/shared/license.model.ts b/src/app/core/shared/license.model.ts index 45a5f9f314..2b2477c1f8 100644 --- a/src/app/core/shared/license.model.ts +++ b/src/app/core/shared/license.model.ts @@ -1,9 +1,9 @@ import { autoserialize, inheritSerialization } from 'cerialize'; -import { resourceType } from '../cache/builders/build-decorators'; +import { typedObject } from '../cache/builders/build-decorators'; import { DSpaceObject } from './dspace-object.model'; import { LICENSE } from './license.resource-type'; -@resourceType(License.type) +@typedObject @inheritSerialization(DSpaceObject) export class License extends DSpaceObject { static type = LICENSE; diff --git a/src/app/core/shared/resource-policy.model.ts b/src/app/core/shared/resource-policy.model.ts index 29dc90d6a5..29f901c35b 100644 --- a/src/app/core/shared/resource-policy.model.ts +++ b/src/app/core/shared/resource-policy.model.ts @@ -1,5 +1,5 @@ import { autoserialize, deserialize, deserializeAs } from 'cerialize'; -import { resourceType } from '../cache/builders/build-decorators'; +import { typedObject } from '../cache/builders/build-decorators'; import { IDToUUIDSerializer } from '../cache/id-to-uuid-serializer'; import { ActionType } from '../cache/models/action-type.model'; import { CacheableObject } from '../cache/object-cache.reducer'; @@ -11,7 +11,7 @@ import { ResourceType } from './resource-type'; /** * Model class for a Resource Policy */ -@resourceType(ResourcePolicy.type) +@typedObject export class ResourcePolicy implements CacheableObject { static type = RESOURCE_POLICY; diff --git a/src/app/core/shared/site.model.ts b/src/app/core/shared/site.model.ts index 204c33f17a..befd4c1ae3 100644 --- a/src/app/core/shared/site.model.ts +++ b/src/app/core/shared/site.model.ts @@ -1,12 +1,12 @@ import { inheritSerialization } from 'cerialize'; -import { resourceType } from '../cache/builders/build-decorators'; +import { typedObject } from '../cache/builders/build-decorators'; import { DSpaceObject } from './dspace-object.model'; import { SITE } from './site.resource-type'; /** * Model class for the Site object */ -@resourceType(Site.type) +@typedObject @inheritSerialization(DSpaceObject) export class Site extends DSpaceObject { ​ diff --git a/src/app/core/submission/models/workflowitem.model.ts b/src/app/core/submission/models/workflowitem.model.ts index 5d53300b81..b8054a66d0 100644 --- a/src/app/core/submission/models/workflowitem.model.ts +++ b/src/app/core/submission/models/workflowitem.model.ts @@ -1,5 +1,5 @@ import { deserializeAs, inheritSerialization } from 'cerialize'; -import { inheritLinkAnnotations, resourceType } from '../../cache/builders/build-decorators'; +import { inheritLinkAnnotations, typedObject } from '../../cache/builders/build-decorators'; import { IDToUUIDSerializer } from '../../cache/id-to-uuid-serializer'; import { WORKFLOWITEM } from '../../eperson/models/workflowitem.resource-type'; import { SubmissionObject } from './submission-object.model'; @@ -7,7 +7,7 @@ import { SubmissionObject } from './submission-object.model'; /** * A model class for a WorkflowItem. */ -@resourceType(WorkflowItem.type) +@typedObject @inheritSerialization(SubmissionObject) @inheritLinkAnnotations(SubmissionObject) export class WorkflowItem extends SubmissionObject { diff --git a/src/app/core/submission/models/workspaceitem.model.ts b/src/app/core/submission/models/workspaceitem.model.ts index f25115ab52..b29d8c0efa 100644 --- a/src/app/core/submission/models/workspaceitem.model.ts +++ b/src/app/core/submission/models/workspaceitem.model.ts @@ -1,5 +1,5 @@ import { deserializeAs, inheritSerialization } from 'cerialize'; -import { inheritLinkAnnotations, resourceType } from '../../cache/builders/build-decorators'; +import { inheritLinkAnnotations, typedObject } from '../../cache/builders/build-decorators'; import { IDToUUIDSerializer } from '../../cache/id-to-uuid-serializer'; import { DSpaceObject } from '../../shared/dspace-object.model'; import { SubmissionObject } from './submission-object.model'; @@ -8,7 +8,7 @@ import { ResourceType } from '../../shared/resource-type'; /** * A model class for a WorkspaceItem. */ -@resourceType(WorkspaceItem.type) +@typedObject @inheritSerialization(SubmissionObject) @inheritLinkAnnotations(SubmissionObject) export class WorkspaceItem extends SubmissionObject { diff --git a/src/app/core/tasks/models/claimed-task-object.model.ts b/src/app/core/tasks/models/claimed-task-object.model.ts index 314bc3a1fa..9ec28bc2e0 100644 --- a/src/app/core/tasks/models/claimed-task-object.model.ts +++ b/src/app/core/tasks/models/claimed-task-object.model.ts @@ -1,5 +1,5 @@ import { inheritSerialization } from 'cerialize'; -import { resourceType } from '../../cache/builders/build-decorators'; +import { typedObject } from '../../cache/builders/build-decorators'; import { DSpaceObject } from '../../shared/dspace-object.model'; import { CLAIMED_TASK } from './claimed-task-object.resource-type'; import { TaskObject } from './task-object.model'; @@ -7,7 +7,7 @@ import { TaskObject } from './task-object.model'; /** * A model class for a ClaimedTask. */ -@resourceType(ClaimedTask.type) +@typedObject @inheritSerialization(DSpaceObject) export class ClaimedTask extends TaskObject { static type = CLAIMED_TASK; diff --git a/src/app/core/tasks/models/pool-task-object.model.ts b/src/app/core/tasks/models/pool-task-object.model.ts index 9938435f12..04fe572502 100644 --- a/src/app/core/tasks/models/pool-task-object.model.ts +++ b/src/app/core/tasks/models/pool-task-object.model.ts @@ -1,12 +1,12 @@ import { inheritSerialization } from 'cerialize'; -import { resourceType } from '../../cache/builders/build-decorators'; +import { typedObject } from '../../cache/builders/build-decorators'; import { POOL_TASK } from './pool-task-object.resource-type'; import { TaskObject } from './task-object.model'; /** * A model class for a PoolTask. */ -@resourceType(PoolTask.type) +@typedObject @inheritSerialization(TaskObject) export class PoolTask extends TaskObject { static type = POOL_TASK; diff --git a/src/app/core/tasks/models/task-object.model.ts b/src/app/core/tasks/models/task-object.model.ts index bab1b3b62b..2e035f134e 100644 --- a/src/app/core/tasks/models/task-object.model.ts +++ b/src/app/core/tasks/models/task-object.model.ts @@ -1,6 +1,6 @@ import { autoserialize, deserialize, inheritSerialization } from 'cerialize'; import { Observable } from 'rxjs'; -import { link, resourceType } from '../../cache/builders/build-decorators'; +import { link, typedObject } from '../../cache/builders/build-decorators'; import { CacheableObject } from '../../cache/object-cache.reducer'; import { RemoteData } from '../../data/remote-data'; @@ -16,7 +16,7 @@ import { TASK_OBJECT } from './task-object.resource-type'; /** * An abstract model class for a TaskObject. */ -@resourceType(TaskObject.type) +@typedObject @inheritSerialization(DSpaceObject) export class TaskObject extends DSpaceObject implements CacheableObject { static type = TASK_OBJECT; From 8551d730d899f39cfb8f99ff94fb42de9586fc03 Mon Sep 17 00:00:00 2001 From: Art Lowel Date: Mon, 17 Feb 2020 10:57:50 +0100 Subject: [PATCH 26/38] fix infinite thumbnail loop --- src/app/thumbnail/thumbnail.component.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/app/thumbnail/thumbnail.component.ts b/src/app/thumbnail/thumbnail.component.ts index 15cef22e07..d5758e786d 100644 --- a/src/app/thumbnail/thumbnail.component.ts +++ b/src/app/thumbnail/thumbnail.component.ts @@ -2,6 +2,8 @@ import { Component, Input, OnInit } from '@angular/core'; import { Bitstream } from '../core/shared/bitstream.model'; import { hasValue } from '../shared/empty.util'; +const placeholder = 'data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2293%22%20height%3D%22120%22%20viewBox%3D%220%200%2093%20120%22%20preserveAspectRatio%3D%22none%22%3E%3C!--%0ASource%20URL%3A%20holder.js%2F93x120%3Ftext%3DNo%20Thumbnail%0ACreated%20with%20Holder.js%202.8.2.%0ALearn%20more%20at%20http%3A%2F%2Fholderjs.com%0A(c)%202012-2015%20Ivan%20Malopinsky%20-%20http%3A%2F%2Fimsky.co%0A--%3E%3Cdefs%3E%3Cstyle%20type%3D%22text%2Fcss%22%3E%3C!%5BCDATA%5B%23holder_1543e460b05%20text%20%7B%20fill%3A%23AAAAAA%3Bfont-weight%3Abold%3Bfont-family%3AArial%2C%20Helvetica%2C%20Open%20Sans%2C%20sans-serif%2C%20monospace%3Bfont-size%3A10pt%20%7D%20%5D%5D%3E%3C%2Fstyle%3E%3C%2Fdefs%3E%3Cg%20id%3D%22holder_1543e460b05%22%3E%3Crect%20width%3D%2293%22%20height%3D%22120%22%20fill%3D%22%23FFFFFF%22%2F%3E%3Cg%3E%3Ctext%20x%3D%2235.6171875%22%20y%3D%2257%22%3ENo%3C%2Ftext%3E%3Ctext%20x%3D%2210.8125%22%20y%3D%2272%22%3EThumbnail%3C%2Ftext%3E%3C%2Fg%3E%3C%2Fg%3E%3C%2Fsvg%3E'; + /** * This component renders a given Bitstream as a thumbnail. * One input parameter of type Bitstream is expected. @@ -28,11 +30,15 @@ export class ThumbnailComponent implements OnInit { /** * The default 'holder.js' image */ - @Input() defaultImage? = 'data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2293%22%20height%3D%22120%22%20viewBox%3D%220%200%2093%20120%22%20preserveAspectRatio%3D%22none%22%3E%3C!--%0ASource%20URL%3A%20holder.js%2F93x120%3Ftext%3DNo%20Thumbnail%0ACreated%20with%20Holder.js%202.8.2.%0ALearn%20more%20at%20http%3A%2F%2Fholderjs.com%0A(c)%202012-2015%20Ivan%20Malopinsky%20-%20http%3A%2F%2Fimsky.co%0A--%3E%3Cdefs%3E%3Cstyle%20type%3D%22text%2Fcss%22%3E%3C!%5BCDATA%5B%23holder_1543e460b05%20text%20%7B%20fill%3A%23AAAAAA%3Bfont-weight%3Abold%3Bfont-family%3AArial%2C%20Helvetica%2C%20Open%20Sans%2C%20sans-serif%2C%20monospace%3Bfont-size%3A10pt%20%7D%20%5D%5D%3E%3C%2Fstyle%3E%3C%2Fdefs%3E%3Cg%20id%3D%22holder_1543e460b05%22%3E%3Crect%20width%3D%2293%22%20height%3D%22120%22%20fill%3D%22%23FFFFFF%22%2F%3E%3Cg%3E%3Ctext%20x%3D%2235.6171875%22%20y%3D%2257%22%3ENo%3C%2Ftext%3E%3Ctext%20x%3D%2210.8125%22%20y%3D%2272%22%3EThumbnail%3C%2Ftext%3E%3C%2Fg%3E%3C%2Fg%3E%3C%2Fsvg%3E'; + @Input() defaultImage? = placeholder; src: string; errorHandler(event) { - event.currentTarget.src = this.defaultImage; + if (event.currentTarget.src !== this.defaultImage) { + event.currentTarget.src = this.defaultImage; + } else { + event.currentTarget.src = placeholder; + } } } From 025948e3a0ca6ea044adcd0767a1cdea24d449f3 Mon Sep 17 00:00:00 2001 From: Art Lowel Date: Mon, 17 Feb 2020 14:45:28 +0100 Subject: [PATCH 27/38] refactor all remaining self links in mocks --- .../metadata-registry.component.spec.ts | 12 +++++- .../metadata-registry.reducers.spec.ts | 24 ++++++++++-- .../metadata-schema.component.spec.ts | 36 +++++++++++++++--- .../collection-item-mapper.component.spec.ts | 8 +++- .../collection-item-mapper.component.ts | 2 +- .../config-response-parsing.service.spec.ts | 11 +++--- .../data/search-response-parsing.service.ts | 4 -- src/app/core/shared/dspace-object.model.ts | 12 +++++- .../form/builder/form-builder.service.spec.ts | 8 +++- src/app/shared/mocks/mock-item.ts | 37 +++++++++++++++---- .../search-form/search-form.component.spec.ts | 12 +++++- .../search-results.component.spec.ts | 12 +++++- .../form/section-form.component.spec.ts | 5 ++- 13 files changed, 143 insertions(+), 40 deletions(-) diff --git a/src/app/+admin/admin-registries/metadata-registry/metadata-registry.component.spec.ts b/src/app/+admin/admin-registries/metadata-registry/metadata-registry.component.spec.ts index 674ae739d8..885cefdb40 100644 --- a/src/app/+admin/admin-registries/metadata-registry/metadata-registry.component.spec.ts +++ b/src/app/+admin/admin-registries/metadata-registry/metadata-registry.component.spec.ts @@ -26,13 +26,21 @@ describe('MetadataRegistryComponent', () => { const mockSchemasList = [ { id: 1, - self: 'https://dspace7.4science.it/dspace-spring-rest/api/core/metadataschemas/1', + _links: { + self: { + href: 'https://dspace7.4science.it/dspace-spring-rest/api/core/metadataschemas/1' + }, + }, prefix: 'dc', namespace: 'http://dublincore.org/documents/dcmi-terms/' }, { id: 2, - self: 'https://dspace7.4science.it/dspace-spring-rest/api/core/metadataschemas/2', + _links: { + self: { + href: 'https://dspace7.4science.it/dspace-spring-rest/api/core/metadataschemas/2' + }, + }, prefix: 'mock', namespace: 'http://dspace.org/mockschema' } diff --git a/src/app/+admin/admin-registries/metadata-registry/metadata-registry.reducers.spec.ts b/src/app/+admin/admin-registries/metadata-registry/metadata-registry.reducers.spec.ts index 2f7d606c60..48d1b89e7c 100644 --- a/src/app/+admin/admin-registries/metadata-registry/metadata-registry.reducers.spec.ts +++ b/src/app/+admin/admin-registries/metadata-registry/metadata-registry.reducers.spec.ts @@ -20,7 +20,11 @@ class NullAction extends MetadataRegistryEditSchemaAction { const schema: MetadataSchema = Object.assign(new MetadataSchema(), { id: 'schema-id', - self: 'http://rest.self/schema/dc', + _links: { + self: { + href: 'http://rest.self/schema/dc' + }, + }, prefix: 'dc', namespace: 'http://dublincore.org/documents/dcmi-terms/' }); @@ -28,7 +32,11 @@ const schema: MetadataSchema = Object.assign(new MetadataSchema(), const schema2: MetadataSchema = Object.assign(new MetadataSchema(), { id: 'another-schema-id', - self: 'http://rest.self/schema/dcterms', + _links: { + self: { + href: 'http://rest.self/schema/dcterms', + }, + }, prefix: 'dcterms', namespace: 'http://purl.org/dc/terms/' }); @@ -36,7 +44,11 @@ const schema2: MetadataSchema = Object.assign(new MetadataSchema(), const field: MetadataField = Object.assign(new MetadataField(), { id: 'author-field-id', - self: 'http://rest.self/field/author', + _links: { + self: { + href: 'http://rest.self/field/author', + }, + }, element: 'contributor', qualifier: 'author', scopeNote: 'Author of an item', @@ -46,7 +58,11 @@ const field: MetadataField = Object.assign(new MetadataField(), const field2: MetadataField = Object.assign(new MetadataField(), { id: 'title-field-id', - self: 'http://rest.self/field/title', + _links: { + self: { + href: 'http://rest.self/field/title', + }, + }, element: 'title', qualifier: null, scopeNote: 'Title of an item', diff --git a/src/app/+admin/admin-registries/metadata-schema/metadata-schema.component.spec.ts b/src/app/+admin/admin-registries/metadata-schema/metadata-schema.component.spec.ts index e0b0ef25a5..01ef191c4c 100644 --- a/src/app/+admin/admin-registries/metadata-schema/metadata-schema.component.spec.ts +++ b/src/app/+admin/admin-registries/metadata-schema/metadata-schema.component.spec.ts @@ -30,13 +30,21 @@ describe('MetadataSchemaComponent', () => { const mockSchemasList = [ { id: 1, - self: 'https://dspace7.4science.it/dspace-spring-rest/api/core/metadataschemas/1', + _links: { + self: { + href: 'https://dspace7.4science.it/dspace-spring-rest/api/core/metadataschemas/1', + }, + }, prefix: 'dc', namespace: 'http://dublincore.org/documents/dcmi-terms/' }, { id: 2, - self: 'https://dspace7.4science.it/dspace-spring-rest/api/core/metadataschemas/2', + _links: { + self: { + href: 'https://dspace7.4science.it/dspace-spring-rest/api/core/metadataschemas/2', + }, + }, prefix: 'mock', namespace: 'http://dspace.org/mockschema' } @@ -44,7 +52,11 @@ describe('MetadataSchemaComponent', () => { const mockFieldsList = [ { id: 1, - self: 'https://dspace7.4science.it/dspace-spring-rest/api/core/metadatafields/8', + _links: { + self: { + href: 'https://dspace7.4science.it/dspace-spring-rest/api/core/metadatafields/8', + }, + }, element: 'contributor', qualifier: 'advisor', scopeNote: null, @@ -52,7 +64,11 @@ describe('MetadataSchemaComponent', () => { }, { id: 2, - self: 'https://dspace7.4science.it/dspace-spring-rest/api/core/metadatafields/9', + _links: { + self: { + href: 'https://dspace7.4science.it/dspace-spring-rest/api/core/metadatafields/9', + }, + }, element: 'contributor', qualifier: 'author', scopeNote: null, @@ -60,7 +76,11 @@ describe('MetadataSchemaComponent', () => { }, { id: 3, - self: 'https://dspace7.4science.it/dspace-spring-rest/api/core/metadatafields/10', + _links: { + self: { + href: 'https://dspace7.4science.it/dspace-spring-rest/api/core/metadatafields/10', + }, + }, element: 'contributor', qualifier: 'editor', scopeNote: 'test scope note', @@ -68,7 +88,11 @@ describe('MetadataSchemaComponent', () => { }, { id: 4, - self: 'https://dspace7.4science.it/dspace-spring-rest/api/core/metadatafields/11', + _links: { + self: { + href: 'https://dspace7.4science.it/dspace-spring-rest/api/core/metadatafields/11', + }, + }, element: 'contributor', qualifier: 'illustrator', scopeNote: null, diff --git a/src/app/+collection-page/collection-item-mapper/collection-item-mapper.component.spec.ts b/src/app/+collection-page/collection-item-mapper/collection-item-mapper.component.spec.ts index 62a8d8dabb..14f6ed771b 100644 --- a/src/app/+collection-page/collection-item-mapper/collection-item-mapper.component.spec.ts +++ b/src/app/+collection-page/collection-item-mapper/collection-item-mapper.component.spec.ts @@ -1,3 +1,4 @@ +import { filter, tap } from 'rxjs/operators'; import { CollectionItemMapperComponent } from './collection-item-mapper.component'; import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { RouterTestingModule } from '@angular/router/testing'; @@ -52,7 +53,12 @@ describe('CollectionItemMapperComponent', () => { const mockCollection: Collection = Object.assign(new Collection(), { id: 'ce41d451-97ed-4a9c-94a1-7de34f16a9f4', - name: 'test-collection' + name: 'test-collection', + _links: { + self: { + href: 'https://rest.api/collections/ce41d451-97ed-4a9c-94a1-7de34f16a9f4' + } + } }); const mockCollectionRD: RemoteData = new RemoteData(false, false, true, null, mockCollection); const mockSearchOptions = of(new PaginatedSearchOptions({ diff --git a/src/app/+collection-page/collection-item-mapper/collection-item-mapper.component.ts b/src/app/+collection-page/collection-item-mapper/collection-item-mapper.component.ts index 44fb0ecfca..5189b1a24a 100644 --- a/src/app/+collection-page/collection-item-mapper/collection-item-mapper.component.ts +++ b/src/app/+collection-page/collection-item-mapper/collection-item-mapper.component.ts @@ -155,7 +155,7 @@ export class CollectionItemMapperComponent implements OnInit { map((collectionRD: RemoteData) => collectionRD.payload), switchMap((collection: Collection) => observableCombineLatest(ids.map((id: string) => - remove ? this.itemDataService.removeMappingFromCollection(id, collection.id) : this.itemDataService.mapToCollection(id, collection.self) + remove ? this.itemDataService.removeMappingFromCollection(id, collection.id) : this.itemDataService.mapToCollection(id, collection._links.self.href) )) ) ); diff --git a/src/app/core/config/config-response-parsing.service.spec.ts b/src/app/core/config/config-response-parsing.service.spec.ts index ecc4750c9c..87a7057078 100644 --- a/src/app/core/config/config-response-parsing.service.spec.ts +++ b/src/app/core/config/config-response-parsing.service.spec.ts @@ -169,7 +169,11 @@ describe('ConfigResponseParsingService', () => { totalElements: 4, totalPages: 1, currentPage: 1, - self: 'https://rest.api/config/submissiondefinitions/traditional/sections' + _links: { + self: { + href: 'https://rest.api/config/submissiondefinitions/traditional/sections' + }, + }, }); const definitions = Object.assign(new SubmissionDefinitionModel(), { @@ -180,7 +184,6 @@ describe('ConfigResponseParsingService', () => { sections: { href: 'https://rest.api/config/submissiondefinitions/traditional/sections' }, self: { href: 'https://rest.api/config/submissiondefinitions/traditional' } }, - self: 'https://rest.api/config/submissiondefinitions/traditional', sections: new PaginatedList(pageinfo, [ Object.assign(new SubmissionSectionModel(), { header: 'submit.progressbar.describe.stepone', @@ -195,7 +198,6 @@ describe('ConfigResponseParsingService', () => { self: { href: 'https://rest.api/config/submissionsections/traditionalpageone' }, config: { href: 'https://rest.api/config/submissionforms/traditionalpageone' } }, - self: 'https://rest.api/config/submissionsections/traditionalpageone', }), Object.assign(new SubmissionSectionModel(), { header: 'submit.progressbar.describe.steptwo', @@ -210,7 +212,6 @@ describe('ConfigResponseParsingService', () => { self: { href: 'https://rest.api/config/submissionsections/traditionalpagetwo' }, config: { href: 'https://rest.api/config/submissionforms/traditionalpagetwo' } }, - self: 'https://rest.api/config/submissionsections/traditionalpagetwo', }), Object.assign(new SubmissionSectionModel(), { header: 'submit.progressbar.upload', @@ -225,7 +226,6 @@ describe('ConfigResponseParsingService', () => { self: { href: 'https://rest.api/config/submissionsections/upload' }, config: { href: 'https://rest.api/config/submissionuploads/upload' } }, - self: 'https://rest.api/config/submissionsections/upload', }), Object.assign(new SubmissionSectionModel(), { header: 'submit.progressbar.license', @@ -239,7 +239,6 @@ describe('ConfigResponseParsingService', () => { _links: { self: { href: 'https://rest.api/config/submissionsections/license' } }, - self: 'https://rest.api/config/submissionsections/license', }) ]) }); diff --git a/src/app/core/data/search-response-parsing.service.ts b/src/app/core/data/search-response-parsing.service.ts index 5307a0bd94..ed47250922 100644 --- a/src/app/core/data/search-response-parsing.service.ts +++ b/src/app/core/data/search-response-parsing.service.ts @@ -42,10 +42,6 @@ export class SearchResponseParsingService implements ResponseParsingService { const dsoSelfLinks = payload._embedded.objects .filter((object) => hasValue(object._embedded)) .map((object) => object._embedded.indexableObject) - // we don't need embedded collections, bitstreamformats, etc for search results. - // And parsing them all takes up a lot of time. Throw them away to improve performance - // until objs until partial results are supported by the rest api - .map((dso) => Object.assign({}, dso, { _embedded: undefined })) .map((dso) => this.dsoParser.parse(request, { payload: dso, statusCode: data.statusCode, diff --git a/src/app/core/shared/dspace-object.model.ts b/src/app/core/shared/dspace-object.model.ts index 7276926b50..781588e575 100644 --- a/src/app/core/shared/dspace-object.model.ts +++ b/src/app/core/shared/dspace-object.model.ts @@ -52,12 +52,22 @@ export class DSpaceObject extends ListableObject implements CacheableObject { type: ResourceType; /** - * A shorthand for this DSpaceObject's self link + * A shorthand to get this DSpaceObject's self link */ get self(): string { return this._links.self.href; } + /** + * A shorthand to set this DSpaceObject's self link + */ + set self(v: string) { + debugger; + this._links.self = { + href: v + }; + } + /** * The name for this DSpaceObject */ diff --git a/src/app/shared/form/builder/form-builder.service.spec.ts b/src/app/shared/form/builder/form-builder.service.spec.ts index ea0957f689..2702f72d26 100644 --- a/src/app/shared/form/builder/form-builder.service.spec.ts +++ b/src/app/shared/form/builder/form-builder.service.spec.ts @@ -373,10 +373,14 @@ describe('FormBuilderService test suite', () => { ] } as FormRowModel ], - self: 'testFormConfiguration.url', + self: { + href: 'testFormConfiguration.url' +}, type: 'submissionform', _links: { - self: 'testFormConfiguration.url' + self: { + href: 'testFormConfiguration.url' +} } } as any; }); diff --git a/src/app/shared/mocks/mock-item.ts b/src/app/shared/mocks/mock-item.ts index 5b029558a9..a5b6a45d4a 100644 --- a/src/app/shared/mocks/mock-item.ts +++ b/src/app/shared/mocks/mock-item.ts @@ -12,7 +12,11 @@ export const MockBitstreamFormat1: BitstreamFormat = Object.assign(new Bitstream supportLevel: 0, internal: false, extensions: null, - self: 'https://dspace7.4science.it/dspace-spring-rest/api/core/bitstreamformats/10' + _links:{ + self: { + href: 'https://dspace7.4science.it/dspace-spring-rest/api/core/bitstreamformats/10' + } + } }); export const MockBitstreamFormat2: BitstreamFormat = Object.assign(new BitstreamFormat(), { @@ -22,7 +26,11 @@ export const MockBitstreamFormat2: BitstreamFormat = Object.assign(new Bitstream supportLevel: 0, internal: false, extensions: null, - self: 'https://dspace7.4science.it/dspace-spring-rest/api/core/bitstreamformats/4' + _links:{ + self: { + href: 'https://dspace7.4science.it/dspace-spring-rest/api/core/bitstreamformats/4' + } + } }); export const MockBitstream1: Bitstream = Object.assign(new Bitstream(), @@ -31,7 +39,11 @@ export const MockBitstream1: Bitstream = Object.assign(new Bitstream(), content: 'https://dspace7.4science.it/dspace-spring-rest/api/core/bitstreams/cf9b0c8e-a1eb-4b65-afd0-567366448713/content', format: observableOf(MockBitstreamFormat1), bundleName: 'ORIGINAL', - self: 'https://dspace7.4science.it/dspace-spring-rest/api/core/bitstreams/cf9b0c8e-a1eb-4b65-afd0-567366448713', + _links:{ + self: { + href: 'https://dspace7.4science.it/dspace-spring-rest/api/core/bitstreams/cf9b0c8e-a1eb-4b65-afd0-567366448713' + } + }, id: 'cf9b0c8e-a1eb-4b65-afd0-567366448713', uuid: 'cf9b0c8e-a1eb-4b65-afd0-567366448713', type: 'bitstream', @@ -50,7 +62,6 @@ export const MockBitstream2: Bitstream = Object.assign(new Bitstream(), { content: 'https://dspace7.4science.it/dspace-spring-rest/api/core/bitstreams/99b00f3c-1cc6-4689-8158-91965bee6b28/content', format: observableOf(MockBitstreamFormat2), bundleName: 'ORIGINAL', - self: 'https://dspace7.4science.it/dspace-spring-rest/api/core/bitstreams/99b00f3c-1cc6-4689-8158-91965bee6b28', id: '99b00f3c-1cc6-4689-8158-91965bee6b28', uuid: '99b00f3c-1cc6-4689-8158-91965bee6b28', type: 'bitstream', @@ -81,7 +92,11 @@ export const MockItem: Item = Object.assign(new Item(), { { name: 'ORIGINAL', bitstreams: observableOf(Object.assign({ - self: 'dspace-angular://aggregated/object/1507836003548', + _links: { + self: { + href: 'dspace-angular://aggregated/object/1507836003548', + } + }, requestPending: false, responsePending: false, isSuccessful: true, @@ -110,7 +125,11 @@ export const MockItem: Item = Object.assign(new Item(), { })) } ])), - self: 'https://dspace7.4science.it/dspace-spring-rest/api/core/items/0ec7ff22-f211-40ab-a69e-c819b0b1f357', + _links:{ + self: { + href: 'https://dspace7.4science.it/dspace-spring-rest/api/core/items/0ec7ff22-f211-40ab-a69e-c819b0b1f357' + } + }, id: '0ec7ff22-f211-40ab-a69e-c819b0b1f357', uuid: '0ec7ff22-f211-40ab-a69e-c819b0b1f357', type: 'item', @@ -215,7 +234,11 @@ export const MockItem: Item = Object.assign(new Item(), { ] }, owningCollection: observableOf({ - self: 'https://dspace7.4science.it/dspace-spring-rest/api/core/collections/1c11f3f1-ba1f-4f36-908a-3f1ea9a557eb', + _links: { + self: { + href: 'https://dspace7.4science.it/dspace-spring-rest/api/core/collections/1c11f3f1-ba1f-4f36-908a-3f1ea9a557eb' + } + }, requestPending: false, responsePending: false, isSuccessful: true, diff --git a/src/app/shared/search-form/search-form.component.spec.ts b/src/app/shared/search-form/search-form.component.spec.ts index 74ed4bb913..ffd8dd87a2 100644 --- a/src/app/shared/search-form/search-form.component.spec.ts +++ b/src/app/shared/search-form/search-form.component.spec.ts @@ -124,7 +124,11 @@ export const objects: DSpaceObject[] = [ scheduler: null } }, - self: 'https://dspace7.4science.it/dspace-spring-rest/api/core/communities/7669c72a-3f2a-451f-a3b9-9210e7a4c02f', + _links: { + self: { + href: 'https://dspace7.4science.it/dspace-spring-rest/api/core/communities/7669c72a-3f2a-451f-a3b9-9210e7a4c02f', + }, + }, id: '7669c72a-3f2a-451f-a3b9-9210e7a4c02f', uuid: '7669c72a-3f2a-451f-a3b9-9210e7a4c02f', type: Community.type, @@ -178,7 +182,11 @@ export const objects: DSpaceObject[] = [ scheduler: null } }, - self: 'https://dspace7.4science.it/dspace-spring-rest/api/core/communities/9076bd16-e69a-48d6-9e41-0238cb40d863', + _links: { + self: { + href: 'https://dspace7.4science.it/dspace-spring-rest/api/core/communities/9076bd16-e69a-48d6-9e41-0238cb40d863', + }, + }, id: '9076bd16-e69a-48d6-9e41-0238cb40d863', uuid: '9076bd16-e69a-48d6-9e41-0238cb40d863', type: Community.type, diff --git a/src/app/shared/search/search-results/search-results.component.spec.ts b/src/app/shared/search/search-results/search-results.component.spec.ts index d2c02717c9..60e91d6fc1 100644 --- a/src/app/shared/search/search-results/search-results.component.spec.ts +++ b/src/app/shared/search/search-results/search-results.component.spec.ts @@ -111,7 +111,11 @@ export const objects = [ scheduler: null } }, - self: 'https://dspace7.4science.it/dspace-spring-rest/api/core/communities/7669c72a-3f2a-451f-a3b9-9210e7a4c02f', + _links: { + self: { + href: 'https://dspace7.4science.it/dspace-spring-rest/api/core/communities/7669c72a-3f2a-451f-a3b9-9210e7a4c02f', + }, + }, id: '7669c72a-3f2a-451f-a3b9-9210e7a4c02f', uuid: '7669c72a-3f2a-451f-a3b9-9210e7a4c02f', type: Community.type, @@ -165,7 +169,11 @@ export const objects = [ scheduler: null } }, - self: 'https://dspace7.4science.it/dspace-spring-rest/api/core/communities/9076bd16-e69a-48d6-9e41-0238cb40d863', + _links: { + self: { + href: 'https://dspace7.4science.it/dspace-spring-rest/api/core/communities/9076bd16-e69a-48d6-9e41-0238cb40d863', + }, + }, id: '9076bd16-e69a-48d6-9e41-0238cb40d863', uuid: '9076bd16-e69a-48d6-9e41-0238cb40d863', type: Community.type, diff --git a/src/app/submission/sections/form/section-form.component.spec.ts b/src/app/submission/sections/form/section-form.component.spec.ts index be13c14941..d644e44df5 100644 --- a/src/app/submission/sections/form/section-form.component.spec.ts +++ b/src/app/submission/sections/form/section-form.component.spec.ts @@ -108,10 +108,11 @@ const testFormConfiguration = { ] } as FormRowModel, ], - self: 'testFormConfiguration.url', type: 'submissionform', _links: { - self: 'testFormConfiguration.url' + self: { + href: 'testFormConfiguration.url' + } } } as any; From dc73561575ad15c98067d0ff4fb091e38692df4a Mon Sep 17 00:00:00 2001 From: Art Lowel Date: Mon, 17 Feb 2020 15:43:24 +0100 Subject: [PATCH 28/38] fix SearchResultListElementComponent tests for workflow and workspace items --- ...search-result-list-element.component.spec.ts | 17 +++++++++-------- ...search-result-list-element.component.spec.ts | 13 +++++++++---- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/src/app/shared/object-list/my-dspace-result-list-element/workflow-item-search-result/workflow-item-search-result-list-element.component.spec.ts b/src/app/shared/object-list/my-dspace-result-list-element/workflow-item-search-result/workflow-item-search-result-list-element.component.spec.ts index 5aae862ed0..9cbbd666cd 100644 --- a/src/app/shared/object-list/my-dspace-result-list-element/workflow-item-search-result/workflow-item-search-result-list-element.component.spec.ts +++ b/src/app/shared/object-list/my-dspace-result-list-element/workflow-item-search-result/workflow-item-search-result-list-element.component.spec.ts @@ -1,14 +1,15 @@ import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; -import { cold } from 'jasmine-marbles'; import { of as observableOf } from 'rxjs'; +import { take } from 'rxjs/operators'; import { LinkService } from '../../../../core/cache/builders/link.service'; import { ItemDataService } from '../../../../core/data/item-data.service'; import { Item } from '../../../../core/shared/item.model'; import { WorkflowItem } from '../../../../core/submission/models/workflowitem.model'; +import { getMockLinkService } from '../../../mocks/mock-link-service'; import { MyDspaceItemStatusType } from '../../../object-collection/shared/mydspace-item-status/my-dspace-item-status-type'; import { WorkflowItemSearchResult } from '../../../object-collection/shared/workflow-item-search-result.model'; import { createSuccessfulRemoteDataObject } from '../../../testing/utils'; @@ -59,11 +60,7 @@ let linkService; describe('WorkflowItemSearchResultListElementComponent', () => { beforeEach(async(() => { - linkService = { - resolveLink() { - // mock - }, - }; + linkService = getMockLinkService(); TestBed.configureTestingModule({ imports: [NoopAnimationsModule], declarations: [WorkflowItemSearchResultListElementComponent], @@ -88,8 +85,12 @@ describe('WorkflowItemSearchResultListElementComponent', () => { fixture.detectChanges(); }); - it('should init item properly', () => { - expect(component.item$).toBeObservable(cold('a',{a: item})); + it('should init item properly', (done) => { + component.item$.pipe(take(1)).subscribe((i) => { + expect(linkService.resolveLink).toHaveBeenCalled(); + expect(i).toBe(item); + done(); + }); }); it('should have properly status', () => { diff --git a/src/app/shared/object-list/my-dspace-result-list-element/workspace-item-search-result/workspace-item-search-result-list-element.component.spec.ts b/src/app/shared/object-list/my-dspace-result-list-element/workspace-item-search-result/workspace-item-search-result-list-element.component.spec.ts index 87ffc86856..441800c8db 100644 --- a/src/app/shared/object-list/my-dspace-result-list-element/workspace-item-search-result/workspace-item-search-result-list-element.component.spec.ts +++ b/src/app/shared/object-list/my-dspace-result-list-element/workspace-item-search-result/workspace-item-search-result-list-element.component.spec.ts @@ -3,11 +3,13 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { of as observableOf } from 'rxjs'; +import { take } from 'rxjs/operators'; import { LinkService } from '../../../../core/cache/builders/link.service'; import { ItemDataService } from '../../../../core/data/item-data.service'; import { Item } from '../../../../core/shared/item.model'; import { WorkspaceItem } from '../../../../core/submission/models/workspaceitem.model'; +import { getMockLinkService } from '../../../mocks/mock-link-service'; import { MyDspaceItemStatusType } from '../../../object-collection/shared/mydspace-item-status/my-dspace-item-status-type'; import { WorkflowItemSearchResult } from '../../../object-collection/shared/workflow-item-search-result.model'; import { createSuccessfulRemoteDataObject } from '../../../testing/utils'; @@ -57,7 +59,7 @@ let linkService; describe('WorkspaceItemSearchResultListElementComponent', () => { beforeEach(async(() => { - linkService = getMockLinkService; + linkService = getMockLinkService(); TestBed.configureTestingModule({ imports: [NoopAnimationsModule], declarations: [WorkspaceItemSearchResultListElementComponent], @@ -82,9 +84,12 @@ describe('WorkspaceItemSearchResultListElementComponent', () => { fixture.detectChanges(); }); - it('should init item properly', () => { - expect(linkService.resolveLink).toHaveBeenCalled(); - expect(component.item$).toEqual(observableOf(item)); + it('should init item properly', (done) => { + component.item$.pipe(take(1)).subscribe((i) => { + expect(linkService.resolveLink).toHaveBeenCalled(); + expect(i).toBe(item); + done(); + }); }); it('should have properly status', () => { From 4d3f85fafe5b04b0d5f097b169451b1880c66fb6 Mon Sep 17 00:00:00 2001 From: Marie Verdonck Date: Mon, 17 Feb 2020 16:48:28 +0100 Subject: [PATCH 29/38] 68405: test fixes search-facet --- .../search-facet-option.component.spec.ts | 37 ++++++++------ ...ch-facet-selected-option.component.spec.ts | 48 +++++++++++++------ 2 files changed, 56 insertions(+), 29 deletions(-) diff --git a/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-option/search-facet-option.component.spec.ts b/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-option/search-facet-option.component.spec.ts index ff5db664db..43f47cc2b9 100644 --- a/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-option/search-facet-option.component.spec.ts +++ b/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-option/search-facet-option.component.spec.ts @@ -1,20 +1,20 @@ import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { TranslateModule } from '@ngx-translate/core'; -import { NoopAnimationsModule } from '@angular/platform-browser/animations'; -import { SearchFacetOptionComponent } from './search-facet-option.component'; -import { SearchFilterConfig } from '../../../../search-filter-config.model'; -import { FilterType } from '../../../../filter-type.model'; -import { FacetValue } from '../../../../facet-value.model'; import { FormsModule } from '@angular/forms'; -import { of as observableOf } from 'rxjs'; -import { SearchService } from '../../../../../../core/shared/search/search.service'; -import { SearchServiceStub } from '../../../../../testing/search-service-stub'; +import { By } from '@angular/platform-browser'; +import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { Router } from '@angular/router'; -import { RouterStub } from '../../../../../testing/router-stub'; +import { TranslateModule } from '@ngx-translate/core'; +import { of as observableOf } from 'rxjs'; import { SearchConfigurationService } from '../../../../../../core/shared/search/search-configuration.service'; import { SearchFilterService } from '../../../../../../core/shared/search/search-filter.service'; -import { By } from '@angular/platform-browser'; +import { SearchService } from '../../../../../../core/shared/search/search.service'; +import { RouterStub } from '../../../../../testing/router-stub'; +import { SearchServiceStub } from '../../../../../testing/search-service-stub'; +import { FacetValue } from '../../../../facet-value.model'; +import { FilterType } from '../../../../filter-type.model'; +import { SearchFilterConfig } from '../../../../search-filter-config.model'; +import { SearchFacetOptionComponent } from './search-facet-option.component'; describe('SearchFacetOptionComponent', () => { let comp: SearchFacetOptionComponent; @@ -47,21 +47,30 @@ describe('SearchFacetOptionComponent', () => { label: value2, value: value2, count: 20, - search: `` + _links: { + self: { href: 'selectedValue-self-link2' }, + search: { href: `` } + } }; const selectedValue: FacetValue = { label: value1, value: value1, count: 20, - search: `http://test.org/api/discover/search/objects?f.${filterName1}=${value1},${operator}` + _links: { + self: { href: 'selectedValue-self-link1' }, + search: { href: `http://test.org/api/discover/search/objects?f.${filterName1}=${value1},${operator}` } + } }; const authorityValue: FacetValue = { label: value2, value: value2, count: 20, - search: `http://test.org/api/discover/search/objects?f.${filterName2}=${value2},${operator}` + _links: { + self: { href: 'authorityValue-self-link2' }, + search: { href: `http://test.org/api/discover/search/objects?f.${filterName2}=${value2},${operator}` } + } }; const searchLink = '/search'; diff --git a/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-selected-option/search-facet-selected-option.component.spec.ts b/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-selected-option/search-facet-selected-option.component.spec.ts index 4ea6571a87..cfeda7d51c 100644 --- a/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-selected-option/search-facet-selected-option.component.spec.ts +++ b/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-selected-option/search-facet-selected-option.component.spec.ts @@ -1,19 +1,19 @@ import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { TranslateModule } from '@ngx-translate/core'; -import { NoopAnimationsModule } from '@angular/platform-browser/animations'; -import { SearchFilterConfig } from '../../../../search-filter-config.model'; -import { FilterType } from '../../../../filter-type.model'; import { FormsModule } from '@angular/forms'; -import { of as observableOf } from 'rxjs'; -import { SearchService } from '../../../../../../core/shared/search/search.service'; -import { SearchServiceStub } from '../../../../../testing/search-service-stub'; +import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { Router } from '@angular/router'; -import { RouterStub } from '../../../../../testing/router-stub'; +import { TranslateModule } from '@ngx-translate/core'; +import { of as observableOf } from 'rxjs'; import { SearchConfigurationService } from '../../../../../../core/shared/search/search-configuration.service'; import { SearchFilterService } from '../../../../../../core/shared/search/search-filter.service'; -import { SearchFacetSelectedOptionComponent } from './search-facet-selected-option.component'; +import { SearchService } from '../../../../../../core/shared/search/search.service'; +import { RouterStub } from '../../../../../testing/router-stub'; +import { SearchServiceStub } from '../../../../../testing/search-service-stub'; import { FacetValue } from '../../../../facet-value.model'; +import { FilterType } from '../../../../filter-type.model'; +import { SearchFilterConfig } from '../../../../search-filter-config.model'; +import { SearchFacetSelectedOptionComponent } from './search-facet-selected-option.component'; describe('SearchFacetSelectedOptionComponent', () => { let comp: SearchFacetSelectedOptionComponent; @@ -47,25 +47,37 @@ describe('SearchFacetSelectedOptionComponent', () => { label: value1, value: value1, count: 20, - search: `http://test.org/api/discover/search/objects?f.${filterName1}=${value1}` + _links: { + self: { href: 'selectedValue-self-link1' }, + search: { href: `http://test.org/api/discover/search/objects?f.${filterName1}=${value1}` } + } }; const selectedValue2: FacetValue = { label: value2, value: value2, count: 20, - search: `http://test.org/api/discover/search/objects?f.${filterName1}=${value2}` + _links: { + self: { href: 'selectedValue-self-link2' }, + search: { href: `http://test.org/api/discover/search/objects?f.${filterName1}=${value2}` } + } }; const selectedAuthorityValue: FacetValue = { label: label1, value: value1, count: 20, - search: `http://test.org/api/discover/search/objects?f.${filterName2}=${value1},${operator}` + _links: { + self: { href: 'selectedAuthorityValue-self-link1' }, + search: { href: `http://test.org/api/discover/search/objects?f.${filterName2}=${value1},${operator}` } + } }; const selectedAuthorityValue2: FacetValue = { label: label2, value: value2, count: 20, - search: `http://test.org/api/discover/search/objects?f.${filterName2}=${value2},${operator}` + _links: { + self: { href: 'selectedAuthorityValue-self-link2' }, + search: { href: `http://test.org/api/discover/search/objects?f.${filterName2}=${value2},${operator}` } + } }; const selectedValues = [selectedValue, selectedValue2]; const selectedAuthorityValues = [selectedAuthorityValue, selectedAuthorityValue2]; @@ -73,13 +85,19 @@ describe('SearchFacetSelectedOptionComponent', () => { label: value2, value: value2, count: 1, - search: '' + _links: { + self: { href: 'facetValue-self-link2' }, + search: { href: `` } + } }; const authorityValue: FacetValue = { label: label2, value: value2, count: 20, - search: `http://test.org/api/discover/search/objects?f.${filterName2}=${value2},${operator}` + _links: { + self: { href: 'authorityValue-self-link2' }, + search: { href: `http://test.org/api/discover/search/objects?f.${filterName2}=${value2},${operator}` } + } }; const selectedValues$ = observableOf(selectedValues); const selectedAuthorityValues$ = observableOf(selectedAuthorityValues); From 39f1766391f64c8920605cb3e27bb2e60705b505 Mon Sep 17 00:00:00 2001 From: Art Lowel Date: Mon, 17 Feb 2020 17:45:02 +0100 Subject: [PATCH 30/38] fixing tests --- .../core/cache/object-cache.service.spec.ts | 7 ++++--- .../config-submission-definition.model.ts | 3 ++- .../models/config-submission-section.model.ts | 3 ++- .../models/config-submission-uploads.model.ts | 3 ++- src/app/core/config/models/config.model.ts | 1 + .../core/data/collection-data.service.spec.ts | 2 +- .../core/data/external-source.service.spec.ts | 2 +- .../data/relationship-type.service.spec.ts | 2 +- .../dspace-rest-v2/dspace.serializer.spec.ts | 18 +++++++++--------- .../upload/section-upload.component.spec.ts | 4 +++- .../upload/section-upload.component.ts | 10 +++++++--- 11 files changed, 33 insertions(+), 22 deletions(-) diff --git a/src/app/core/cache/object-cache.service.spec.ts b/src/app/core/cache/object-cache.service.spec.ts index 461263d131..c3b7781d70 100644 --- a/src/app/core/cache/object-cache.service.spec.ts +++ b/src/app/core/cache/object-cache.service.spec.ts @@ -54,9 +54,10 @@ describe('ObjectCacheService', () => { beforeEach(() => { init(); store = new Store(undefined, undefined, undefined); - linkServiceStub = jasmine.createSpyObj({ - removeResolvedLinks: {} - }); + linkServiceStub = { + removeResolvedLinks: (a) => a + }; + spyOn(linkServiceStub, 'removeResolvedLinks').and.callThrough(); spyOn(store, 'dispatch'); service = new ObjectCacheService(store, linkServiceStub); diff --git a/src/app/core/config/models/config-submission-definition.model.ts b/src/app/core/config/models/config-submission-definition.model.ts index 1437ae32b1..f3e888d513 100644 --- a/src/app/core/config/models/config-submission-definition.model.ts +++ b/src/app/core/config/models/config-submission-definition.model.ts @@ -1,4 +1,4 @@ -import { autoserialize, deserialize } from 'cerialize'; +import { autoserialize, deserialize, inheritSerialization } from 'cerialize'; import { typedObject } from '../../cache/builders/build-decorators'; import { PaginatedList } from '../../data/paginated-list'; import { HALLink } from '../../shared/hal-link.model'; @@ -10,6 +10,7 @@ import { ConfigObject } from './config.model'; * Class for the configuration describing the submission */ @typedObject +@inheritSerialization(ConfigObject) export class SubmissionDefinitionModel extends ConfigObject { static type = new ResourceType('submissiondefinition'); diff --git a/src/app/core/config/models/config-submission-section.model.ts b/src/app/core/config/models/config-submission-section.model.ts index d589e6a648..5a9c3225ab 100644 --- a/src/app/core/config/models/config-submission-section.model.ts +++ b/src/app/core/config/models/config-submission-section.model.ts @@ -1,4 +1,4 @@ -import { autoserialize, deserialize } from 'cerialize'; +import { autoserialize, deserialize, inheritSerialization } from 'cerialize'; import { SectionsType } from '../../../submission/sections/sections-type'; import { typedObject } from '../../cache/builders/build-decorators'; import { HALLink } from '../../shared/hal-link.model'; @@ -14,6 +14,7 @@ export interface SubmissionSectionVisibility { } @typedObject +@inheritSerialization(ConfigObject) export class SubmissionSectionModel extends ConfigObject { static type = new ResourceType('submissionsection'); diff --git a/src/app/core/config/models/config-submission-uploads.model.ts b/src/app/core/config/models/config-submission-uploads.model.ts index b88ce4e0f8..b7733ee25d 100644 --- a/src/app/core/config/models/config-submission-uploads.model.ts +++ b/src/app/core/config/models/config-submission-uploads.model.ts @@ -1,4 +1,4 @@ -import { autoserialize } from 'cerialize'; +import { autoserialize, inheritSerialization } from 'cerialize'; import { typedObject } from '../../cache/builders/build-decorators'; import { ConfigObject } from './config.model'; import { AccessConditionOption } from './config-access-condition-option.model'; @@ -6,6 +6,7 @@ import { SubmissionFormsModel } from './config-submission-forms.model'; import { ResourceType } from '../../shared/resource-type'; @typedObject +@inheritSerialization(ConfigObject) export class SubmissionUploadsModel extends ConfigObject { static type = new ResourceType('submissionupload'); /** diff --git a/src/app/core/config/models/config.model.ts b/src/app/core/config/models/config.model.ts index 98ba3e147f..fabb16eb23 100644 --- a/src/app/core/config/models/config.model.ts +++ b/src/app/core/config/models/config.model.ts @@ -9,6 +9,7 @@ export abstract class ConfigObject implements CacheableObject { /** * The name for this configuration */ + @autoserialize public name: string; /** diff --git a/src/app/core/data/collection-data.service.spec.ts b/src/app/core/data/collection-data.service.spec.ts index c8f056bf19..96141d6a8a 100644 --- a/src/app/core/data/collection-data.service.spec.ts +++ b/src/app/core/data/collection-data.service.spec.ts @@ -126,7 +126,7 @@ describe('CollectionDataService', () => { notificationsService = new NotificationsServiceStub(); translate = getMockTranslateService(); - service = new CollectionDataService(requestService, rdbService, null, null, null, objectCache, halService, notificationsService, null, null, translate); + service = new CollectionDataService(requestService, rdbService, null, null, objectCache, halService, notificationsService, null, null, translate); } }); diff --git a/src/app/core/data/external-source.service.spec.ts b/src/app/core/data/external-source.service.spec.ts index 77a2a85dfd..f891b46883 100644 --- a/src/app/core/data/external-source.service.spec.ts +++ b/src/app/core/data/external-source.service.spec.ts @@ -49,7 +49,7 @@ describe('ExternalSourceService', () => { halService = jasmine.createSpyObj('halService', { getEndpoint: observableOf('external-sources-REST-endpoint') }); - service = new ExternalSourceService(requestService, rdbService, undefined, undefined, undefined, halService, undefined, undefined, undefined); + service = new ExternalSourceService(requestService, rdbService, undefined, undefined, halService, undefined, undefined, undefined); } beforeEach(() => { diff --git a/src/app/core/data/relationship-type.service.spec.ts b/src/app/core/data/relationship-type.service.spec.ts index 2322a692a7..bc81829559 100644 --- a/src/app/core/data/relationship-type.service.spec.ts +++ b/src/app/core/data/relationship-type.service.spec.ts @@ -11,7 +11,7 @@ import { PaginatedList } from './paginated-list'; import { RelationshipTypeService } from './relationship-type.service'; import { RequestService } from './request.service'; -describe('RelationshipTypeService', () => { +fdescribe('RelationshipTypeService', () => { let service: RelationshipTypeService; let requestService: RequestService; let restEndpointURL; diff --git a/src/app/core/dspace-rest-v2/dspace.serializer.spec.ts b/src/app/core/dspace-rest-v2/dspace.serializer.spec.ts index 36af99e073..b07a4f97d1 100644 --- a/src/app/core/dspace-rest-v2/dspace.serializer.spec.ts +++ b/src/app/core/dspace-rest-v2/dspace.serializer.spec.ts @@ -80,9 +80,9 @@ describe('DSpaceSerializer', () => { it('should turn a model in to a valid document', () => { const serializer = new DSpaceSerializer(TestModel); const doc = serializer.serialize(testModels[0]); - expect(testModels[0].id).toBe(doc.id); - expect(testModels[0].name).toBe(doc.name); - expect(testModels[0]._links).toBeUndefined(); + expect(doc.id).toBe(testModels[0].id); + expect(doc.name).toBe(testModels[0].name); + expect(doc._links).toBeUndefined(); }); }); @@ -93,12 +93,12 @@ describe('DSpaceSerializer', () => { const serializer = new DSpaceSerializer(TestModel); const doc = serializer.serializeArray(testModels); - expect(testModels[0].id).toBe(doc[0].id); - expect(testModels[0].name).toBe(doc[0].name); - expect(testModels[0]._links).toBeUndefined(); - expect(testModels[1].id).toBe(doc[1].id); - expect(testModels[1].name).toBe(doc[1].name); - expect(testModels[1]._links).toBeUndefined(); + expect(doc[0].id).toBe(testModels[0].id); + expect(doc[0].name).toBe(testModels[0].name); + expect(doc[0]._links).toBeUndefined(); + expect(doc[1].id).toBe(testModels[1].id); + expect(doc[1].name).toBe(testModels[1].name); + expect(doc[1]._links).toBeUndefined(); }); }); diff --git a/src/app/submission/sections/upload/section-upload.component.spec.ts b/src/app/submission/sections/upload/section-upload.component.spec.ts index af53a7ae6d..af865b81eb 100644 --- a/src/app/submission/sections/upload/section-upload.component.spec.ts +++ b/src/app/submission/sections/upload/section-upload.component.spec.ts @@ -197,7 +197,9 @@ describe('SubmissionSectionUploadComponent test suite', () => { submissionServiceStub.getSubmissionObject.and.returnValue(observableOf(submissionState)); - collectionDataService.findById.and.returnValue(createSuccessfulRemoteDataObject$(mockCollection)); + collectionDataService.findById.and.returnValue(createSuccessfulRemoteDataObject$(Object.assign(new Collection(), mockCollection, { + defaultAccessConditions: createSuccessfulRemoteDataObject$(mockDefaultAccessCondition) + }))); resourcePolicyService.findByHref.and.returnValue(createSuccessfulRemoteDataObject$(mockDefaultAccessCondition)); diff --git a/src/app/submission/sections/upload/section-upload.component.ts b/src/app/submission/sections/upload/section-upload.component.ts index 0a589ffc33..86da00c816 100644 --- a/src/app/submission/sections/upload/section-upload.component.ts +++ b/src/app/submission/sections/upload/section-upload.component.ts @@ -96,7 +96,7 @@ export class SubmissionSectionUploadComponent extends SectionModelComponent { public configMetadataForm$: Observable; /** - * List of available access conditions that could be setted to files + * List of available access conditions that could be set to files */ public availableAccessConditionOptions: AccessConditionOption[]; // List of accessConditions that an user can select @@ -161,10 +161,14 @@ export class SubmissionSectionUploadComponent extends SectionModelComponent { filter((submissionObject: SubmissionObjectEntry) => isNotUndefined(submissionObject) && !submissionObject.isLoading), filter((submissionObject: SubmissionObjectEntry) => isUndefined(this.collectionId) || this.collectionId !== submissionObject.collection), tap((submissionObject: SubmissionObjectEntry) => this.collectionId = submissionObject.collection), - flatMap((submissionObject: SubmissionObjectEntry) => this.collectionDataService.findById(submissionObject.collection, followLink('defaultAccessConditions'))), + flatMap((submissionObject: SubmissionObjectEntry) => this.collectionDataService.findById(submissionObject.collection)), filter((rd: RemoteData) => isNotUndefined((rd.payload))), tap((collectionRemoteData: RemoteData) => this.collectionName = collectionRemoteData.payload.name), - map((collectionRemoteData: RemoteData) => (collectionRemoteData.payload as any).defaultAccessConditions), + flatMap((collectionRemoteData: RemoteData) => { + return this.resourcePolicyService.findByHref( + (collectionRemoteData.payload as any)._links.defaultAccessConditions.href + ); + }), filter((defaultAccessConditionsRemoteData: RemoteData) => defaultAccessConditionsRemoteData.hasSucceeded), tap((defaultAccessConditionsRemoteData: RemoteData) => { From c5e807404077f0a34063f40b6191d2315e625085 Mon Sep 17 00:00:00 2001 From: Art Lowel Date: Mon, 17 Feb 2020 17:45:28 +0100 Subject: [PATCH 31/38] remove fdescribe --- src/app/core/data/relationship-type.service.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/core/data/relationship-type.service.spec.ts b/src/app/core/data/relationship-type.service.spec.ts index bc81829559..2322a692a7 100644 --- a/src/app/core/data/relationship-type.service.spec.ts +++ b/src/app/core/data/relationship-type.service.spec.ts @@ -11,7 +11,7 @@ import { PaginatedList } from './paginated-list'; import { RelationshipTypeService } from './relationship-type.service'; import { RequestService } from './request.service'; -fdescribe('RelationshipTypeService', () => { +describe('RelationshipTypeService', () => { let service: RelationshipTypeService; let requestService: RequestService; let restEndpointURL; From 08dedb2dc34eb3f5dc823ee2a8a8d4012e90a32a Mon Sep 17 00:00:00 2001 From: Art Lowel Date: Mon, 17 Feb 2020 18:01:55 +0100 Subject: [PATCH 32/38] fix lint errors --- .../builders/remote-data-build.service.ts | 4 +- src/app/core/cache/object-cache.service.ts | 2 +- src/app/core/data/data.service.spec.ts | 3 +- .../data/default-change-analyzer.service.ts | 3 -- src/app/core/data/entity-type-data.service.ts | 2 + src/app/core/data/license-data.service.ts | 2 + .../data/relationship-type.service.spec.ts | 1 - .../core/data/relationship.service.spec.ts | 1 - src/app/core/shared/content-source.model.ts | 2 +- src/app/core/shared/dspace-object.model.ts | 1 - src/app/core/shared/item.resource-type.ts | 2 +- .../form/builder/form-builder.service.spec.ts | 38 +++++++++---------- .../workspaceitem-actions.component.ts | 2 +- src/app/thumbnail/thumbnail.component.ts | 33 ++++++++++++---- 14 files changed, 55 insertions(+), 41 deletions(-) diff --git a/src/app/core/cache/builders/remote-data-build.service.ts b/src/app/core/cache/builders/remote-data-build.service.ts index a35998375c..f2dc5e4c6e 100644 --- a/src/app/core/cache/builders/remote-data-build.service.ts +++ b/src/app/core/cache/builders/remote-data-build.service.ts @@ -2,7 +2,6 @@ import { Injectable } from '@angular/core'; import { combineLatest as observableCombineLatest, Observable, of as observableOf, race as observableRace } from 'rxjs'; import { distinctUntilChanged, map, startWith, switchMap } from 'rxjs/operators'; import { - hasNoValue, hasValue, hasValueOperator, isEmpty, @@ -14,7 +13,6 @@ import { FollowLinkConfig } from '../../../shared/utils/follow-link-config.model import { PaginatedList } from '../../data/paginated-list'; import { RemoteData } from '../../data/remote-data'; import { RemoteDataError } from '../../data/remote-data-error'; -import { GetRequest } from '../../data/request.models'; import { RequestEntry } from '../../data/request.reducer'; import { RequestService } from '../../data/request.service'; import { @@ -136,7 +134,7 @@ export class RemoteDataBuildService { getResourceLinksFromResponse(), switchMap((resourceUUIDs: string[]) => { return this.objectCache.getList(resourceUUIDs).pipe( - map((objs: Array) => { + map((objs: T[]) => { return objs.map((obj: T) => { return this.build(obj, ...linksToFollow); }); diff --git a/src/app/core/cache/object-cache.service.ts b/src/app/core/cache/object-cache.service.ts index 269f61e847..53894df5f1 100644 --- a/src/app/core/cache/object-cache.service.ts +++ b/src/app/core/cache/object-cache.service.ts @@ -187,7 +187,7 @@ export class ObjectCacheService { * The type of the objects to get * @return Observable> */ - getList(selfLinks: string[]): Observable> { + getList(selfLinks: string[]): Observable { return observableCombineLatest( selfLinks.map((selfLink: string) => this.getObjectBySelfLink(selfLink)) ); diff --git a/src/app/core/data/data.service.spec.ts b/src/app/core/data/data.service.spec.ts index ddb77496e3..347dfa83a4 100644 --- a/src/app/core/data/data.service.spec.ts +++ b/src/app/core/data/data.service.spec.ts @@ -19,6 +19,7 @@ import { createSuccessfulRemoteDataObject$ } from '../../shared/testing/utils'; const endpoint = 'https://rest.api/core'; +/* tslint:disable:max-classes-per-file */ class TestService extends DataService { constructor( @@ -39,7 +40,6 @@ class TestService extends DataService { return observableOf(endpoint); } } - class DummyChangeAnalyzer implements ChangeAnalyzer { diff(object1: Item, object2: Item): Operation[] { return compare((object1 as any).metadata, (object2 as any).metadata); @@ -198,3 +198,4 @@ describe('DataService', () => { }); }); }); +/* tslint:enable:max-classes-per-file */ diff --git a/src/app/core/data/default-change-analyzer.service.ts b/src/app/core/data/default-change-analyzer.service.ts index d8cfb999dc..20218925fb 100644 --- a/src/app/core/data/default-change-analyzer.service.ts +++ b/src/app/core/data/default-change-analyzer.service.ts @@ -12,9 +12,6 @@ import { ChangeAnalyzer } from './change-analyzer'; */ @Injectable() export class DefaultChangeAnalyzer implements ChangeAnalyzer { - constructor() { - } - /** * Compare the metadata of two CacheableObject and return the differences as * a JsonPatch Operation Array diff --git a/src/app/core/data/entity-type-data.service.ts b/src/app/core/data/entity-type-data.service.ts index db958fe680..80b6beed81 100644 --- a/src/app/core/data/entity-type-data.service.ts +++ b/src/app/core/data/entity-type-data.service.ts @@ -18,6 +18,7 @@ import { RemoteData } from './remote-data'; import { FindListOptions } from './request.models'; import { RequestService } from './request.service'; +/* tslint:disable:max-classes-per-file */ class DataServiceImpl extends DataService { protected linkPath = 'entitytypes'; @@ -71,3 +72,4 @@ export class ItemTypeDataService { return this.dataService.findAllByHref(href, findListOptions, ...linksToFollow); } } +/* tslint:enable:max-classes-per-file */ diff --git a/src/app/core/data/license-data.service.ts b/src/app/core/data/license-data.service.ts index fbdc44f233..24b77a41a6 100644 --- a/src/app/core/data/license-data.service.ts +++ b/src/app/core/data/license-data.service.ts @@ -18,6 +18,7 @@ import { RemoteData } from './remote-data'; import { FindListOptions } from './request.models'; import { RequestService } from './request.service'; +/* tslint:disable:max-classes-per-file */ class DataServiceImpl extends DataService { protected linkPath = ''; @@ -59,3 +60,4 @@ export class LicenseDataService { return this.dataService.findAllByHref(href, findListOptions, ...linksToFollow); } } +/* tslint:enable:max-classes-per-file */ diff --git a/src/app/core/data/relationship-type.service.spec.ts b/src/app/core/data/relationship-type.service.spec.ts index 2322a692a7..0a86b4bc61 100644 --- a/src/app/core/data/relationship-type.service.spec.ts +++ b/src/app/core/data/relationship-type.service.spec.ts @@ -78,7 +78,6 @@ describe('RelationshipTypeService', () => { requestService, rdbService, null, - null, halService, objectCache, null, diff --git a/src/app/core/data/relationship.service.spec.ts b/src/app/core/data/relationship.service.spec.ts index 9dd9530fda..caf1e87469 100644 --- a/src/app/core/data/relationship.service.spec.ts +++ b/src/app/core/data/relationship.service.spec.ts @@ -104,7 +104,6 @@ describe('RelationshipService', () => { requestService, rdbService, null, - null, halService, objectCache, null, diff --git a/src/app/core/shared/content-source.model.ts b/src/app/core/shared/content-source.model.ts index 9e93e9d529..82cacd91ed 100644 --- a/src/app/core/shared/content-source.model.ts +++ b/src/app/core/shared/content-source.model.ts @@ -16,7 +16,7 @@ export enum ContentSourceHarvestType { /** * A model class that holds information about the Content Source of a Collection */ -export class ContentSource implements HALResource{ +export class ContentSource implements HALResource { /** * Unique identifier, this is necessary to store the ContentSource in FieldUpdates * Because the ContentSource coming from the REST API doesn't have a UUID, we're using the selflink diff --git a/src/app/core/shared/dspace-object.model.ts b/src/app/core/shared/dspace-object.model.ts index 781588e575..2e1afe9c8a 100644 --- a/src/app/core/shared/dspace-object.model.ts +++ b/src/app/core/shared/dspace-object.model.ts @@ -62,7 +62,6 @@ export class DSpaceObject extends ListableObject implements CacheableObject { * A shorthand to set this DSpaceObject's self link */ set self(v: string) { - debugger; this._links.self = { href: v }; diff --git a/src/app/core/shared/item.resource-type.ts b/src/app/core/shared/item.resource-type.ts index c21b83fde9..8371f6b9b5 100644 --- a/src/app/core/shared/item.resource-type.ts +++ b/src/app/core/shared/item.resource-type.ts @@ -1,4 +1,4 @@ -import { ResourceType } from "./resource-type"; +import { ResourceType } from './resource-type'; /** * The resource type for Item. diff --git a/src/app/shared/form/builder/form-builder.service.spec.ts b/src/app/shared/form/builder/form-builder.service.spec.ts index 2702f72d26..972abb68b5 100644 --- a/src/app/shared/form/builder/form-builder.service.spec.ts +++ b/src/app/shared/form/builder/form-builder.service.spec.ts @@ -276,7 +276,7 @@ describe('FormBuilderService test suite', () => { { fields: [ { - input: {type: 'lookup'}, + input: { type: 'lookup' }, label: 'Journal', mandatory: 'false', repeatable: false, @@ -291,7 +291,7 @@ describe('FormBuilderService test suite', () => { languageCodes: [] } as FormFieldModel, { - input: {type: 'onebox'}, + input: { type: 'onebox' }, label: 'Issue', mandatory: 'false', repeatable: false, @@ -304,7 +304,7 @@ describe('FormBuilderService test suite', () => { languageCodes: [] } as FormFieldModel, { - input: {type: 'name'}, + input: { type: 'name' }, label: 'Name', mandatory: 'false', repeatable: false, @@ -322,24 +322,24 @@ describe('FormBuilderService test suite', () => { fields: [ { hints: 'If the item has any identification numbers or codes associated with↵ it, please enter the types and the actual numbers or codes.', - input: {type: 'onebox'}, + input: { type: 'onebox' }, label: 'Identifiers', languageCodes: [], mandatory: 'false', repeatable: false, selectableMetadata: [ - {metadata: 'dc.identifier.issn', label: 'ISSN'}, - {metadata: 'dc.identifier.other', label: 'Other'}, - {metadata: 'dc.identifier.ismn', label: 'ISMN'}, - {metadata: 'dc.identifier.govdoc', label: 'Gov\'t Doc #'}, - {metadata: 'dc.identifier.uri', label: 'URI'}, - {metadata: 'dc.identifier.isbn', label: 'ISBN'}, - {metadata: 'dc.identifier.doi', label: 'DOI'}, - {metadata: 'dc.identifier.pmid', label: 'PubMed ID'}, - {metadata: 'dc.identifier.arxiv', label: 'arXiv'} + { metadata: 'dc.identifier.issn', label: 'ISSN' }, + { metadata: 'dc.identifier.other', label: 'Other' }, + { metadata: 'dc.identifier.ismn', label: 'ISMN' }, + { metadata: 'dc.identifier.govdoc', label: 'Gov\'t Doc #' }, + { metadata: 'dc.identifier.uri', label: 'URI' }, + { metadata: 'dc.identifier.isbn', label: 'ISBN' }, + { metadata: 'dc.identifier.doi', label: 'DOI' }, + { metadata: 'dc.identifier.pmid', label: 'PubMed ID' }, + { metadata: 'dc.identifier.arxiv', label: 'arXiv' } ] }, { - input: {type: 'onebox'}, + input: { type: 'onebox' }, label: 'Publisher', mandatory: 'false', repeatable: false, @@ -356,7 +356,7 @@ describe('FormBuilderService test suite', () => { { fields: [ { - input: {type: 'onebox'}, + input: { type: 'onebox' }, label: 'Conference', mandatory: 'false', repeatable: false, @@ -374,13 +374,13 @@ describe('FormBuilderService test suite', () => { } as FormRowModel ], self: { - href: 'testFormConfiguration.url' -}, + href: 'testFormConfiguration.url' + }, type: 'submissionform', _links: { self: { - href: 'testFormConfiguration.url' -} + href: 'testFormConfiguration.url' + } } } as any; }); diff --git a/src/app/shared/mydspace-actions/workspaceitem/workspaceitem-actions.component.ts b/src/app/shared/mydspace-actions/workspaceitem/workspaceitem-actions.component.ts index 59c1ae9a0e..5f2f31c53e 100644 --- a/src/app/shared/mydspace-actions/workspaceitem/workspaceitem-actions.component.ts +++ b/src/app/shared/mydspace-actions/workspaceitem/workspaceitem-actions.component.ts @@ -58,7 +58,7 @@ export class WorkspaceitemActionsComponent extends MyDSpaceActionsComponent Date: Tue, 18 Feb 2020 18:15:18 +0100 Subject: [PATCH 33/38] tests and documentation --- .../item-metadata/item-metadata.component.ts | 1 + .../edit-relationship-list.component.spec.ts | 5 + .../edit-relationship-list.component.ts | 31 ++- .../item-relationships.component.spec.ts | 3 + .../item-relationships.component.ts | 6 +- src/app/core/auth/auth.service.spec.ts | 19 +- src/app/core/auth/auth.service.ts | 8 +- src/app/core/auth/server-auth.service.ts | 2 +- .../core/cache/builders/build-decorators.ts | 46 ++++ .../core/cache/builders/link.service.spec.ts | 222 ++++++++++++++++++ src/app/core/cache/builders/link.service.ts | 25 +- .../builders/remote-data-build.service.ts | 17 +- src/app/core/data/entity-type.service.ts | 9 +- .../core/data/relationship.service.spec.ts | 55 +++-- src/app/core/data/relationship.service.ts | 19 +- src/app/core/shared/item.model.ts | 2 +- src/app/core/shared/search/search.service.ts | 3 +- .../mocks/mock-remote-data-build.service.ts | 2 - .../shared/utils/follow-link-config.model.ts | 30 +++ 19 files changed, 430 insertions(+), 75 deletions(-) create mode 100644 src/app/core/cache/builders/link.service.spec.ts diff --git a/src/app/+item-page/edit-item-page/item-metadata/item-metadata.component.ts b/src/app/+item-page/edit-item-page/item-metadata/item-metadata.component.ts index be657d71dc..71acceeb4c 100644 --- a/src/app/+item-page/edit-item-page/item-metadata/item-metadata.component.ts +++ b/src/app/+item-page/edit-item-page/item-metadata/item-metadata.component.ts @@ -1,4 +1,5 @@ import { Component, Inject } from '@angular/core'; +import { LinkService } from '../../../core/cache/builders/link.service'; import { Item } from '../../../core/shared/item.model'; import { ItemDataService } from '../../../core/data/item-data.service'; import { ObjectUpdatesService } from '../../../core/data/object-updates/object-updates.service'; diff --git a/src/app/+item-page/edit-item-page/item-relationships/edit-relationship-list/edit-relationship-list.component.spec.ts b/src/app/+item-page/edit-item-page/item-relationships/edit-relationship-list/edit-relationship-list.component.spec.ts index cef5e82957..0608eab2d8 100644 --- a/src/app/+item-page/edit-item-page/item-relationships/edit-relationship-list/edit-relationship-list.component.spec.ts +++ b/src/app/+item-page/edit-item-page/item-relationships/edit-relationship-list/edit-relationship-list.component.spec.ts @@ -3,15 +3,18 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { By } from '@angular/platform-browser'; import { TranslateModule } from '@ngx-translate/core'; import { of as observableOf } from 'rxjs/internal/observable/of'; +import { LinkService } from '../../../../core/cache/builders/link.service'; import { FieldChangeType } from '../../../../core/data/object-updates/object-updates.actions'; import { ObjectUpdatesService } from '../../../../core/data/object-updates/object-updates.service'; import { PaginatedList } from '../../../../core/data/paginated-list'; +import { RelationshipTypeService } from '../../../../core/data/relationship-type.service'; import { RemoteData } from '../../../../core/data/remote-data'; import { ItemType } from '../../../../core/shared/item-relationships/item-type.model'; import { RelationshipType } from '../../../../core/shared/item-relationships/relationship-type.model'; import { Relationship } from '../../../../core/shared/item-relationships/relationship.model'; import { Item } from '../../../../core/shared/item.model'; import { PageInfo } from '../../../../core/shared/page-info.model'; +import { getMockLinkService } from '../../../../shared/mocks/mock-link-service'; import { SharedModule } from '../../../../shared/shared.module'; import { EditRelationshipListComponent } from './edit-relationship-list.component'; @@ -152,6 +155,8 @@ describe('EditRelationshipListComponent', () => { declarations: [EditRelationshipListComponent], providers: [ { provide: ObjectUpdatesService, useValue: objectUpdatesService }, + { provide: RelationshipTypeService, useValue: {} }, + { provide: LinkService, useValue: getMockLinkService() }, ], schemas: [ NO_ERRORS_SCHEMA ] diff --git a/src/app/+item-page/edit-item-page/item-relationships/edit-relationship-list/edit-relationship-list.component.ts b/src/app/+item-page/edit-item-page/item-relationships/edit-relationship-list/edit-relationship-list.component.ts index 73e3e1f875..c17762e4a0 100644 --- a/src/app/+item-page/edit-item-page/item-relationships/edit-relationship-list/edit-relationship-list.component.ts +++ b/src/app/+item-page/edit-item-page/item-relationships/edit-relationship-list/edit-relationship-list.component.ts @@ -1,15 +1,21 @@ import { Component, Input, OnInit } from '@angular/core'; +import { LinkService } from '../../../../core/cache/builders/link.service'; import { ObjectUpdatesService } from '../../../../core/data/object-updates/object-updates.service'; import { Observable } from 'rxjs/internal/Observable'; import {FieldUpdate, FieldUpdates} from '../../../../core/data/object-updates/object-updates.reducer'; import {Item} from '../../../../core/shared/item.model'; -import {map, switchMap} from 'rxjs/operators'; +import { map, switchMap, tap } from 'rxjs/operators'; import {hasValue} from '../../../../shared/empty.util'; import {Relationship} from '../../../../core/shared/item-relationships/relationship.model'; import {RelationshipType} from '../../../../core/shared/item-relationships/relationship-type.model'; -import {getRemoteDataPayload, getSucceededRemoteData} from '../../../../core/shared/operators'; -import {combineLatest as observableCombineLatest, combineLatest} from 'rxjs'; -import {ItemType} from '../../../../core/shared/item-relationships/item-type.model'; +import { + getAllSucceededRemoteData, + getRemoteDataPayload, + getSucceededRemoteData +} from '../../../../core/shared/operators'; +import { combineLatest as observableCombineLatest } from 'rxjs'; +import { ItemType } from '../../../../core/shared/item-relationships/item-type.model'; +import { followLink } from '../../../../shared/utils/follow-link-config.model'; @Component({ selector: 'ds-edit-relationship-list', @@ -47,6 +53,7 @@ export class EditRelationshipListComponent implements OnInit { constructor( protected objectUpdatesService: ObjectUpdatesService, + protected linkService: LinkService ) { } @@ -71,7 +78,7 @@ export class EditRelationshipListComponent implements OnInit { */ private getLabel(): Observable { - return combineLatest([ + return observableCombineLatest([ this.relationshipType.leftType, this.relationshipType.rightType, ].map((itemTypeRD) => itemTypeRD.pipe( @@ -94,8 +101,20 @@ export class EditRelationshipListComponent implements OnInit { ngOnInit(): void { this.updates$ = this.item.relationships.pipe( + getAllSucceededRemoteData(), map((relationships) => relationships.payload.page.filter((relationship) => relationship)), - switchMap((itemRelationships) => + map((relationships: Relationship[]) => + relationships.map((relationship: Relationship) => { + this.linkService.resolveLinks( + relationship, + followLink('relationshipType'), + followLink('leftItem'), + followLink('rightItem'), + ); + return relationship; + }) + ), + switchMap((itemRelationships: Relationship[]) => observableCombineLatest( itemRelationships .map((relationship) => relationship.relationshipType.pipe( diff --git a/src/app/+item-page/edit-item-page/item-relationships/item-relationships.component.spec.ts b/src/app/+item-page/edit-item-page/item-relationships/item-relationships.component.spec.ts index 731e4885a6..c8bd577e04 100644 --- a/src/app/+item-page/edit-item-page/item-relationships/item-relationships.component.spec.ts +++ b/src/app/+item-page/edit-item-page/item-relationships/item-relationships.component.spec.ts @@ -26,6 +26,9 @@ import { INotification, Notification } from '../../../shared/notifications/models/notification.model'; +import { NotificationsService } from '../../../shared/notifications/notifications.service'; +import { SharedModule } from '../../../shared/shared.module'; +import { RouterStub } from '../../../shared/testing/router-stub'; import { ItemRelationshipsComponent } from './item-relationships.component'; let comp: any; diff --git a/src/app/+item-page/edit-item-page/item-relationships/item-relationships.component.ts b/src/app/+item-page/edit-item-page/item-relationships/item-relationships.component.ts index 7f6d32d902..36ccca357c 100644 --- a/src/app/+item-page/edit-item-page/item-relationships/item-relationships.component.ts +++ b/src/app/+item-page/edit-item-page/item-relationships/item-relationships.component.ts @@ -98,7 +98,11 @@ export class ItemRelationshipsComponent extends AbstractItemUpdateComponent impl this.relationshipTypes$ = this.entityType$.pipe( switchMap((entityType) => - this.entityTypeService.getEntityTypeRelationships(entityType.id).pipe( + this.entityTypeService.getEntityTypeRelationships( + entityType.id, + followLink('leftType'), + followLink('rightType')) + .pipe( getSucceededRemoteData(), getRemoteDataPayload(), map((relationshipTypes) => relationshipTypes.page), diff --git a/src/app/core/auth/auth.service.spec.ts b/src/app/core/auth/auth.service.spec.ts index 86794f257b..0928afcb19 100644 --- a/src/app/core/auth/auth.service.spec.ts +++ b/src/app/core/auth/auth.service.spec.ts @@ -5,6 +5,7 @@ import { ActivatedRoute, Router } from '@angular/router'; import { Store, StoreModule } from '@ngrx/store'; import { REQUEST } from '@nguniversal/express-engine/tokens'; import { of as observableOf } from 'rxjs'; +import { LinkService } from '../cache/builders/link.service'; import { authReducer, AuthState } from './auth.reducer'; import { NativeWindowRef, NativeWindowService } from '../services/window.service'; @@ -38,7 +39,7 @@ describe('AuthService test', () => { let storage: CookieService; let token: AuthTokenInfo; let authenticatedState; - let rdbService; + let linkService; function init() { mockStore = jasmine.createSpyObj('store', { @@ -58,8 +59,10 @@ describe('AuthService test', () => { }; authRequest = new AuthRequestServiceStub(); routeStub = new ActivatedRouteStub(); - rdbService = getMockRemoteDataBuildService(); - spyOn(rdbService, 'build').and.returnValue({authenticated: true, eperson: observableOf({payload: {}})}); + linkService = { + resolveLinks: {} + }; + spyOn(linkService, 'resolveLinks').and.returnValue({authenticated: true, eperson: observableOf({payload: {}})}); } @@ -80,7 +83,7 @@ describe('AuthService test', () => { { provide: RouteService, useValue: routeServiceStub }, { provide: ActivatedRoute, useValue: routeStub }, { provide: Store, useValue: mockStore }, - { provide: RemoteDataBuildService, useValue: rdbService }, + { provide: LinkService, useValue: linkService }, CookieService, AuthService ], @@ -143,7 +146,7 @@ describe('AuthService test', () => { { provide: REQUEST, useValue: {} }, { provide: Router, useValue: routerStub }, { provide: RouteService, useValue: routeServiceStub }, - { provide: RemoteDataBuildService, useValue: rdbService }, + { provide: RemoteDataBuildService, useValue: linkService }, CookieService, AuthService ] @@ -156,7 +159,7 @@ describe('AuthService test', () => { (state as any).core = Object.create({}); (state as any).core.auth = authenticatedState; }); - authService = new AuthService({}, window, undefined, authReqService, router, routeService, cookieService, store, rdbService); + authService = new AuthService({}, window, undefined, authReqService, router, routeService, cookieService, store, linkService); })); it('should return true when user is logged in', () => { @@ -195,7 +198,7 @@ describe('AuthService test', () => { { provide: REQUEST, useValue: {} }, { provide: Router, useValue: routerStub }, { provide: RouteService, useValue: routeServiceStub }, - { provide: RemoteDataBuildService, useValue: rdbService }, + { provide: RemoteDataBuildService, useValue: linkService }, ClientCookieService, CookieService, AuthService @@ -218,7 +221,7 @@ describe('AuthService test', () => { (state as any).core = Object.create({}); (state as any).core.auth = authenticatedState; }); - authService = new AuthService({}, window, undefined, authReqService, router, routeService, cookieService, store, rdbService); + authService = new AuthService({}, window, undefined, authReqService, router, routeService, cookieService, store, linkService); storage = (authService as any).storage; routeServiceMock = TestBed.get(RouteService); routerStub = TestBed.get(Router); diff --git a/src/app/core/auth/auth.service.ts b/src/app/core/auth/auth.service.ts index 69c468f32a..1da9f63b27 100644 --- a/src/app/core/auth/auth.service.ts +++ b/src/app/core/auth/auth.service.ts @@ -9,6 +9,7 @@ import { RouterReducerState } from '@ngrx/router-store'; import { select, Store } from '@ngrx/store'; import { CookieAttributes } from 'js-cookie'; import { followLink } from '../../shared/utils/follow-link-config.model'; +import { LinkService } from '../cache/builders/link.service'; import { EPerson } from '../eperson/models/eperson.model'; import { AuthRequestService } from './auth-request.service'; @@ -22,8 +23,7 @@ import { AppState, routerStateSelector } from '../../app.reducer'; import { ResetAuthenticationMessagesAction, SetRedirectUrlAction } from './auth.actions'; import { NativeWindowRef, NativeWindowService } from '../services/window.service'; import { Base64EncodeUrl } from '../../shared/utils/encode-decode.util'; -import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; -import {RouteService} from '../services/route.service'; +import { RouteService } from '../services/route.service'; export const LOGIN_ROUTE = '/login'; export const LOGOUT_ROUTE = '/logout'; @@ -50,7 +50,7 @@ export class AuthService { protected routeService: RouteService, protected storage: CookieService, protected store: Store, - protected rdbService: RemoteDataBuildService + protected linkService: LinkService ) { this.store.pipe( select(isAuthenticated), @@ -134,7 +134,7 @@ export class AuthService { headers = headers.append('Authorization', `Bearer ${token.accessToken}`); options.headers = headers; return this.authRequestService.getRequest('status', options).pipe( - map((status) => this.rdbService.build(status, followLink('eperson'))), + map((status) => this.linkService.resolveLinks(status, followLink('eperson'))), switchMap((status: AuthStatus) => { if (status.authenticated) { return status.eperson.pipe(map((eperson) => eperson.payload)); diff --git a/src/app/core/auth/server-auth.service.ts b/src/app/core/auth/server-auth.service.ts index f17f691a1f..eea2d83867 100644 --- a/src/app/core/auth/server-auth.service.ts +++ b/src/app/core/auth/server-auth.service.ts @@ -35,7 +35,7 @@ export class ServerAuthService extends AuthService { options.headers = headers; return this.authRequestService.getRequest('status', options).pipe( - map((status) => this.rdbService.build(status, followLink('eperson'))), + map((status) => this.linkService.resolveLinks(status, followLink('eperson'))), switchMap((status: AuthStatus) => { if (status.authenticated) { return status.eperson.pipe(map((eperson) => eperson.payload)); diff --git a/src/app/core/cache/builders/build-decorators.ts b/src/app/core/cache/builders/build-decorators.ts index 3c1415b9a4..a1119e5fec 100644 --- a/src/app/core/cache/builders/build-decorators.ts +++ b/src/app/core/cache/builders/build-decorators.ts @@ -33,6 +33,15 @@ export function getClassForType(type: string | ResourceType) { return typeMap.get(type); } +/** + * A class decorator to indicate that this class is a dataservice + * for a given resource type. + * + * "dataservice" in this context means that it has findByHref and + * findAllByHref methods. + * + * @param resourceType the resource type the class is a dataservice for + */ export function dataService(resourceType: ResourceType): any { return (target: any) => { if (hasNoValue(resourceType)) { @@ -48,6 +57,11 @@ export function dataService(resourceType: ResourceType): any { }; } +/** + * Return the dataservice matching the given resource type + * + * @param resourceType the resource type you want the matching dataservice for + */ export function getDataServiceFor(resourceType: ResourceType) { return dataServiceMap.get(resourceType.value); } @@ -71,6 +85,9 @@ export function resolvedLink, K extends keyof T>(prov }; } +/** + * A class to represent the data that can be set by the @link decorator + */ export class LinkDefinition { resourceType: ResourceType; isList = false; @@ -78,6 +95,19 @@ export class LinkDefinition { propertyName: keyof T; } +/** + * A property decorator to indicate that a certain property is the placeholder + * where the contents of a resolved link should be stored. + * + * e.g. if an Item has an hal link for bundles, and an item.bundles property + * this decorator should decorate that item.bundles property. + * + * @param resourceType the resource type of the object(s) the link retrieves + * @param isList an optional boolean indicating whether or not it concerns a list, + * defaults to false + * @param linkName an optional string in case the HALLink name differs from the + * property name + */ export const link = ( resourceType: ResourceType, isList = false, @@ -105,10 +135,20 @@ export const link = ( } }; +/** + * Returns all LinkDefinitions for a model class + * @param source + */ export const getLinkDefinitions = (source: GenericConstructor): Map> => { return linkMap.get(source); }; +/** + * Returns a specific LinkDefinition for a model class + * + * @param source the model class + * @param linkName the name of the link + */ export const getLinkDefinition = (source: GenericConstructor, linkName: keyof T['_links']): LinkDefinition => { const sourceMap = linkMap.get(source); if (hasValue(sourceMap)) { @@ -118,6 +158,12 @@ export const getLinkDefinition = (source: GenericConstruc } }; +/** + * A class level decorator to indicate you want to inherit @link annotations + * from a parent class. + * + * @param parent the parent class to inherit @link annotations from + */ export const inheritLinkAnnotations = (parent: any): any => { return (child: any) => { const parentMap: Map> = linkMap.get(parent) || new Map(); diff --git a/src/app/core/cache/builders/link.service.spec.ts b/src/app/core/cache/builders/link.service.spec.ts new file mode 100644 index 0000000000..21af7dda7c --- /dev/null +++ b/src/app/core/cache/builders/link.service.spec.ts @@ -0,0 +1,222 @@ +import { Injectable } from '@angular/core'; +import { TestBed } from '@angular/core/testing'; +import { followLink, FollowLinkConfig } from '../../../shared/utils/follow-link-config.model'; +import { FindListOptions } from '../../data/request.models'; +import { HALLink } from '../../shared/hal-link.model'; +import { HALResource } from '../../shared/hal-resource.model'; +import { ResourceType } from '../../shared/resource-type'; +import * as decorators from './build-decorators'; +import { getDataServiceFor } from './build-decorators'; +import { LinkService } from './link.service'; + +const spyOnFunction = (obj: T, func: keyof T) => { + const spy = jasmine.createSpy(func as string); + spyOnProperty(obj, func, 'get').and.returnValue(spy); + + return spy; +}; + +const TEST_MODEL = new ResourceType('testmodel'); +let result: any; + +/* tslint:disable:max-classes-per-file */ +class TestModel implements HALResource { + static type = TEST_MODEL; + + type = TEST_MODEL; + + value: string; + + _links: { + self: HALLink; + predecessor: HALLink; + successor: HALLink; + }; + + predecessor?: TestModel; + successor?: TestModel; +} + +@Injectable() +class TestDataService { + findAllByHref(href: string, findListOptions: FindListOptions = {}, ...linksToFollow: Array>) { + return 'findAllByHref' + } + findByHref(href: string, ...linksToFollow: Array>) { + return 'findByHref' + } +} + +let testDataService: TestDataService; + +let testModel: TestModel; + +describe('LinkService', () => { + let service: LinkService; + + beforeEach(() => { + testModel = Object.assign(new TestModel(), { + value: 'a test value', + _links: { + self: { + href: 'http://self.link' + }, + predecessor: { + href: 'http://predecessor.link' + }, + successor: { + href: 'http://successor.link' + }, + } + }); + testDataService = new TestDataService(); + spyOn(testDataService, 'findAllByHref').and.callThrough(); + spyOn(testDataService, 'findByHref').and.callThrough(); + TestBed.configureTestingModule({ + providers: [LinkService, { + provide: TestDataService, + useValue: testDataService + }] + }); + service = TestBed.get(LinkService); + }); + + describe('resolveLink', () => { + describe(`when the linkdefinition concerns a single object`, () => { + beforeEach(() => { + spyOnFunction(decorators, 'getLinkDefinition').and.returnValue({ + resourceType: TEST_MODEL, + linkName: 'predecessor', + propertyName: 'predecessor' + }); + spyOnFunction(decorators, 'getDataServiceFor').and.returnValue(TestDataService); + service.resolveLink(testModel, followLink('predecessor', {}, followLink('successor'))) + }); + it('should call dataservice.findByHref with the correct href and nested links', () => { + expect(testDataService.findByHref).toHaveBeenCalledWith(testModel._links.predecessor.href, followLink('successor')); + }); + }); + describe(`when the linkdefinition concerns a list`, () => { + beforeEach(() => { + spyOnFunction(decorators, 'getLinkDefinition').and.returnValue({ + resourceType: TEST_MODEL, + linkName: 'predecessor', + propertyName: 'predecessor', + isList: true + }); + spyOnFunction(decorators, 'getDataServiceFor').and.returnValue(TestDataService); + service.resolveLink(testModel, followLink('predecessor', { some: 'options '} as any, followLink('successor'))) + }); + it('should call dataservice.findAllByHref with the correct href, findListOptions, and nested links', () => { + expect(testDataService.findAllByHref).toHaveBeenCalledWith(testModel._links.predecessor.href, { some: 'options '} as any, followLink('successor')); + }); + }); + describe('either way', () => { + beforeEach(() => { + spyOnFunction(decorators, 'getLinkDefinition').and.returnValue({ + resourceType: TEST_MODEL, + linkName: 'predecessor', + propertyName: 'predecessor' + }); + spyOnFunction(decorators, 'getDataServiceFor').and.returnValue(TestDataService); + result = service.resolveLink(testModel, followLink('predecessor', {}, followLink('successor'))) + }); + + it('should call getLinkDefinition with the correct model and link', () => { + expect(decorators.getLinkDefinition).toHaveBeenCalledWith(testModel.constructor, 'predecessor'); + }); + + it('should call getDataServiceFor with the correct resource type', () => { + expect(decorators.getDataServiceFor).toHaveBeenCalledWith(TEST_MODEL); + }); + + it('should return the model with the resolved link', () => { + expect(result.type).toBe(TEST_MODEL); + expect(result.value).toBe('a test value'); + expect(result._links.self.href).toBe('http://self.link'); + expect(result.predecessor).toBe('findByHref'); + }); + }); + + describe(`when the specified link doesn't exist on the model's class`, () => { + beforeEach(() => { + spyOnFunction(decorators, 'getLinkDefinition').and.returnValue(undefined); + }); + it('should throw an error', () => { + expect(() => { + service.resolveLink(testModel, followLink('predecessor', {}, followLink('successor'))) + }).toThrow(); + }); + }); + + describe(`when there is no dataservice for the resourcetype in the link`, () => { + beforeEach(() => { + spyOnFunction(decorators, 'getLinkDefinition').and.returnValue({ + resourceType: TEST_MODEL, + linkName: 'predecessor', + propertyName: 'predecessor' + }); + spyOnFunction(decorators, 'getDataServiceFor').and.returnValue(undefined); + }); + it('should throw an error', () => { + expect(() => { + service.resolveLink(testModel, followLink('predecessor', {}, followLink('successor'))) + }).toThrow(); + }); + }); + }); + + describe('resolveLinks', () => { + beforeEach(() => { + spyOn(service, 'resolveLink'); + service.resolveLinks(testModel, followLink('predecessor'), followLink('successor')) + }); + + it('should call resolveLink with the model for each of the provided links', () => { + expect(service.resolveLink).toHaveBeenCalledWith(testModel, followLink('predecessor')); + expect(service.resolveLink).toHaveBeenCalledWith(testModel, followLink('successor')); + }); + + it('should return the model', () => { + expect(result.type).toBe(TEST_MODEL); + expect(result.value).toBe('a test value'); + expect(result._links.self.href).toBe('http://self.link'); + }); + }); + + describe('removeResolvedLinks', () => { + beforeEach(() => { + testModel.predecessor = 'predecessor value'; + testModel.successor = 'successor value'; + spyOnFunction(decorators, 'getLinkDefinitions').and.returnValue([ + { + resourceType: TEST_MODEL, + linkName: 'predecessor', + propertyName: 'predecessor', + }, + { + resourceType: TEST_MODEL, + linkName: 'successor', + propertyName: 'successor', + } + ]) + }); + + it('should return a new version of the object without any resolved links', () => { + result = service.removeResolvedLinks(testModel); + expect(result.value).toBe(testModel.value); + expect(result.type).toBe(testModel.type); + expect(result._links).toBe(testModel._links); + expect(result.predecessor).toBeUndefined(); + expect(result.successor).toBeUndefined(); + }); + + it('should leave the original object untouched', () => { + service.removeResolvedLinks(testModel); + expect(testModel.predecessor).toBe('predecessor value'); + expect(testModel.successor).toBe('successor value'); + }); + }); + +}); +/* tslint:enable:max-classes-per-file */ diff --git a/src/app/core/cache/builders/link.service.ts b/src/app/core/cache/builders/link.service.ts index 1b044ebee9..87f8eabd92 100644 --- a/src/app/core/cache/builders/link.service.ts +++ b/src/app/core/cache/builders/link.service.ts @@ -5,6 +5,10 @@ import { GenericConstructor } from '../../shared/generic-constructor'; import { HALResource } from '../../shared/hal-resource.model'; import { getDataServiceFor, getLinkDefinition, getLinkDefinitions, LinkDefinition } from './build-decorators'; +/** + * A Service to handle the resolving and removing + * of resolved HALLinks on HALResources + */ @Injectable({ providedIn: 'root' }) @@ -15,13 +19,26 @@ export class LinkService { ) { } - public resolveLinks(model: T, ...linksToFollow: Array>) { + /** + * Resolve the given {@link FollowLinkConfig}s for the given model + * + * @param model the {@link HALResource} to resolve the links for + * @param linksToFollow the {@link FollowLinkConfig}s to resolve + */ + public resolveLinks(model: T, ...linksToFollow: Array>): T { linksToFollow.forEach((linkToFollow: FollowLinkConfig) => { this.resolveLink(model, linkToFollow); }); + return model; } - public resolveLink(model, linkToFollow: FollowLinkConfig) { + /** + * Resolve the given {@link FollowLinkConfig} for the given model + * + * @param model the {@link HALResource} to resolve the link for + * @param linkToFollow the {@link FollowLinkConfig} to resolve + */ + public resolveLink(model, linkToFollow: FollowLinkConfig): T { const matchingLinkDef = getLinkDefinition(model.constructor, linkToFollow.name); if (hasNoValue(matchingLinkDef)) { @@ -50,10 +67,14 @@ export class LinkService { throw new Error(`Something went wrong when using @dataService(${matchingLinkDef.resourceType.value}) ${hasValue(service) ? '' : '(undefined) '}to resolve link ${linkToFollow.name} from ${href}`); } } + return model; } /** * Remove any resolved links that the model may have. + * + * @param model the {@link HALResource} to remove the links from + * @returns a copy of the given model, without resolved links. */ public removeResolvedLinks(model: T): T { const result = Object.assign(new (model.constructor as GenericConstructor)(), model); diff --git a/src/app/core/cache/builders/remote-data-build.service.ts b/src/app/core/cache/builders/remote-data-build.service.ts index f2dc5e4c6e..46b5f28465 100644 --- a/src/app/core/cache/builders/remote-data-build.service.ts +++ b/src/app/core/cache/builders/remote-data-build.service.ts @@ -80,9 +80,9 @@ export class RemoteDataBuildService { } }), hasValueOperator(), - map((obj: T) => { - return this.build(obj, ...linksToFollow); - }), + map((obj: T) => + this.linkService.resolveLinks(obj, ...linksToFollow) + ), startWith(undefined), distinctUntilChanged() ); @@ -135,9 +135,9 @@ export class RemoteDataBuildService { switchMap((resourceUUIDs: string[]) => { return this.objectCache.getList(resourceUUIDs).pipe( map((objs: T[]) => { - return objs.map((obj: T) => { - return this.build(obj, ...linksToFollow); - }); + return objs.map((obj: T) => + this.linkService.resolveLinks(obj, ...linksToFollow) + ); })); }), startWith([]), @@ -166,11 +166,6 @@ export class RemoteDataBuildService { return this.toRemoteDataObservable(requestEntry$, payload$); } - build(model: T, ...linksToFollow: Array>): T { - this.linkService.resolveLinks(model, ...linksToFollow); - return model; - } - aggregate(input: Array>>): Observable> { if (isEmpty(input)) { diff --git a/src/app/core/data/entity-type.service.ts b/src/app/core/data/entity-type.service.ts index 583601d898..5726aeb982 100644 --- a/src/app/core/data/entity-type.service.ts +++ b/src/app/core/data/entity-type.service.ts @@ -1,7 +1,7 @@ +import { FollowLinkConfig } from '../../shared/utils/follow-link-config.model'; import { DataService } from './data.service'; import { RequestService } from './request.service'; import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; -import { NormalizedObjectBuildService } from '../cache/builders/normalized-object-build.service'; import { Store } from '@ngrx/store'; import { CoreState } from '../core.reducers'; import { HALEndpointService } from '../shared/hal-endpoint.service'; @@ -25,11 +25,9 @@ import {ItemType} from '../shared/item-relationships/item-type.model'; export class EntityTypeService extends DataService { protected linkPath = 'entitytypes'; - protected forceBypassCache = false; constructor(protected requestService: RequestService, protected rdbService: RemoteDataBuildService, - protected dataBuildService: NormalizedObjectBuildService, protected store: Store, protected halService: HALEndpointService, protected objectCache: ObjectCacheService, @@ -56,8 +54,9 @@ export class EntityTypeService extends DataService { /** * Get the allowed relationship types for an entity type * @param entityTypeId + * @param linksToFollow List of {@link FollowLinkConfig} that indicate which HALLinks should be automatically resolved */ - getEntityTypeRelationships(entityTypeId: string): Observable>> { + getEntityTypeRelationships(entityTypeId: string, ...linksToFollow: Array>): Observable>> { const href$ = this.getRelationshipTypesEndpoint(entityTypeId); @@ -66,7 +65,7 @@ export class EntityTypeService extends DataService { this.requestService.configure(request); }); - return this.rdbService.buildList(href$); + return this.rdbService.buildList(href$, ...linksToFollow); } /** diff --git a/src/app/core/data/relationship.service.spec.ts b/src/app/core/data/relationship.service.spec.ts index caf1e87469..f5d370dc0b 100644 --- a/src/app/core/data/relationship.service.spec.ts +++ b/src/app/core/data/relationship.service.spec.ts @@ -33,25 +33,6 @@ describe('RelationshipService', () => { rightwardType: 'isPublicationOfAuthor' }); - const relationship1 = Object.assign(new Relationship(), { - _links: { - self: { href: relationshipsEndpointURL + '/2' } - }, - id: '2', - uuid: '2', - relationshipType: observableOf(new RemoteData(false, false, true, undefined, relationshipType)) - }); - const relationship2 = Object.assign(new Relationship(), { - _links: { - self: { href: relationshipsEndpointURL + '/3' } - }, - id: '3', - uuid: '3', - relationshipType: observableOf(new RemoteData(false, false, true, undefined, relationshipType)) - }); - - const relationships = [relationship1, relationship2]; - const item = Object.assign(new Item(), { id: 'publication', uuid: 'publication', @@ -76,6 +57,42 @@ describe('RelationshipService', () => { self: { href: restEndpointURL + '/author2' } } }); + + const relationship1 = Object.assign(new Relationship(), { + _links: { + self: { + href: relationshipsEndpointURL + '/2' + }, + leftItem: { + href: relatedItem1._links.self.href + }, + rightItem: { + href: item._links.self.href + } + }, + id: '2', + uuid: '2', + relationshipType: observableOf(new RemoteData(false, false, true, undefined, relationshipType)) + }); + const relationship2 = Object.assign(new Relationship(), { + _links: { + self: { + href: relationshipsEndpointURL + '/3' + }, + leftItem: { + href: relatedItem2._links.self.href + }, + rightItem: { + href: item._links.self.href + }, + }, + id: '3', + uuid: '3', + relationshipType: observableOf(new RemoteData(false, false, true, undefined, relationshipType)) + }); + + const relationships = [relationship1, relationship2]; + relationship1.leftItem = getRemotedataObservable(relatedItem1); relationship1.rightItem = getRemotedataObservable(item); relationship2.leftItem = getRemotedataObservable(relatedItem2); diff --git a/src/app/core/data/relationship.service.ts b/src/app/core/data/relationship.service.ts index 7df56252de..4dde567c99 100644 --- a/src/app/core/data/relationship.service.ts +++ b/src/app/core/data/relationship.service.ts @@ -446,19 +446,12 @@ export class RelationshipService extends DataService { clearRelatedCache(uuid: string): Observable { return this.findById(uuid).pipe( getSucceededRemoteData(), - switchMap((rd: RemoteData) => - observableCombineLatest( - rd.payload.leftItem.pipe(getSucceededRemoteData()), - rd.payload.rightItem.pipe(getSucceededRemoteData()) - ) - ), - take(1), - map(([leftItem, rightItem]) => { - this.objectCache.remove(leftItem.payload.self); - this.objectCache.remove(rightItem.payload.self); - this.requestService.removeByHrefSubstring(leftItem.payload.self); - this.requestService.removeByHrefSubstring(rightItem.payload.self); - }), + map((rd: RemoteData) => { + this.objectCache.remove(rd.payload._links.leftItem.href); + this.objectCache.remove(rd.payload._links.rightItem.href); + this.requestService.removeByHrefSubstring(rd.payload._links.leftItem.href); + this.requestService.removeByHrefSubstring(rd.payload._links.rightItem.href); + }) ); } } diff --git a/src/app/core/shared/item.model.ts b/src/app/core/shared/item.model.ts index e20cc1dbac..8f5038585d 100644 --- a/src/app/core/shared/item.model.ts +++ b/src/app/core/shared/item.model.ts @@ -87,7 +87,7 @@ export class Item extends DSpaceObject { * The list of Relationships this Item has with others * Will be undefined unless the relationships HALLink has been resolved. */ - @link(RELATIONSHIP) + @link(RELATIONSHIP, true) relationships?: Observable>>; /** diff --git a/src/app/core/shared/search/search.service.ts b/src/app/core/shared/search/search.service.ts index 125317298c..1a016e64f8 100644 --- a/src/app/core/shared/search/search.service.ts +++ b/src/app/core/shared/search/search.service.ts @@ -342,8 +342,7 @@ export class SearchService implements OnDestroy { switchMap((dsoRD: RemoteData) => { if ((dsoRD.payload as any).type === Community.type.value) { const community: Community = dsoRD.payload as Community; - this.linkService.resolveLink(community, followLink('subcommunities')); - this.linkService.resolveLink(community, followLink('collections')); + this.linkService.resolveLinks(community, followLink('subcommunities'), followLink('collections')); return observableCombineLatest(community.subcommunities, community.collections).pipe( map(([subCommunities, collections]) => { /*if this is a community, we also need to show the direct children*/ diff --git a/src/app/shared/mocks/mock-remote-data-build.service.ts b/src/app/shared/mocks/mock-remote-data-build.service.ts index 5098c77e34..2dff033a26 100644 --- a/src/app/shared/mocks/mock-remote-data-build.service.ts +++ b/src/app/shared/mocks/mock-remote-data-build.service.ts @@ -21,7 +21,6 @@ export function getMockRemoteDataBuildService(toRemoteDataObservable$?: Observab } }, buildSingle: (href$: string | Observable) => createSuccessfulRemoteDataObject$({}), - build: (obj: any) => Object.create({}), buildList: (href$: string | Observable) => { if (hasValue(buildList$)) { return buildList$; @@ -46,7 +45,6 @@ export function getMockRemoteDataBuildServiceHrefMap(toRemoteDataObservable$?: O } }, buildSingle: (href$: string | Observable) => createSuccessfulRemoteDataObject$({}), - build: (obj: any) => Object.create({}), buildList: (href$: string | Observable) => { if (typeof href$ === 'string') { if (hasValue(buildListHrefMap$[href$])) { diff --git a/src/app/shared/utils/follow-link-config.model.ts b/src/app/shared/utils/follow-link-config.model.ts index 1b0dfa3c08..d42ed7bb3f 100644 --- a/src/app/shared/utils/follow-link-config.model.ts +++ b/src/app/shared/utils/follow-link-config.model.ts @@ -1,12 +1,42 @@ import { FindListOptions } from '../../core/data/request.models'; import { HALResource } from '../../core/shared/hal-resource.model'; +/** + * A class to configure the retrieval of a HALLink + */ export class FollowLinkConfig { + /** + * The name of the link to fetch. + * Can only be a HALLink of the object you're working with + */ name: keyof R['_links']; + + /** + * {@link FindListOptions} for the query, + * allows you to resolve the link using a certain page, or sorted + * in a certain way + */ findListOptions?: FindListOptions; + + /** + * A list of {@link FollowLinkConfig}s to + * use on the retrieved object. + */ linksToFollow?: Array>; } +/** + * A factory function for {@link FollowLinkConfig}s, + * in order to create them in a less verbose way. + * + * @param linkName: the name of the link to fetch. + * Can only be a HALLink of the object you're working with + * @param findListOptions: {@link FindListOptions} for the query, + * allows you to resolve the link using a certain page, or sorted + * in a certain way + * @param linksToFollow: a list of {@link FollowLinkConfig}s to + * use on the retrieved object. + */ export const followLink = ( linkName: keyof R['_links'], findListOptions?: FindListOptions, From 6824ccb307edd81f80672ec28ebceabb75a4a405 Mon Sep 17 00:00:00 2001 From: Art Lowel Date: Tue, 18 Feb 2020 18:52:33 +0100 Subject: [PATCH 34/38] fix AoT issues --- .../core/cache/builders/build-decorators.ts | 4 +- .../core/cache/builders/link.service.spec.ts | 10 +-- .../core/cache/object-cache.service.spec.ts | 2 +- .../core/data/relationship.service.spec.ts | 62 ++++++++++--------- ...earch-facet-range-option.component.spec.ts | 18 +++++- .../search-facet-filter.component.spec.ts | 27 +++++++- 6 files changed, 80 insertions(+), 43 deletions(-) diff --git a/src/app/core/cache/builders/build-decorators.ts b/src/app/core/cache/builders/build-decorators.ts index a1119e5fec..50a70e051f 100644 --- a/src/app/core/cache/builders/build-decorators.ts +++ b/src/app/core/cache/builders/build-decorators.ts @@ -164,7 +164,7 @@ export const getLinkDefinition = (source: GenericConstruc * * @param parent the parent class to inherit @link annotations from */ -export const inheritLinkAnnotations = (parent: any): any => { +export function inheritLinkAnnotations(parent: any): any { return (child: any) => { const parentMap: Map> = linkMap.get(parent) || new Map(); const childMap: Map> = linkMap.get(child) || new Map(); @@ -177,4 +177,4 @@ export const inheritLinkAnnotations = (parent: any): any => { linkMap.set(child, childMap); } -}; +} diff --git a/src/app/core/cache/builders/link.service.spec.ts b/src/app/core/cache/builders/link.service.spec.ts index 21af7dda7c..b34aea320a 100644 --- a/src/app/core/cache/builders/link.service.spec.ts +++ b/src/app/core/cache/builders/link.service.spec.ts @@ -123,7 +123,7 @@ describe('LinkService', () => { }); it('should call getLinkDefinition with the correct model and link', () => { - expect(decorators.getLinkDefinition).toHaveBeenCalledWith(testModel.constructor, 'predecessor'); + expect(decorators.getLinkDefinition).toHaveBeenCalledWith(testModel.constructor as any, 'predecessor'); }); it('should call getDataServiceFor with the correct resource type', () => { @@ -186,8 +186,8 @@ describe('LinkService', () => { describe('removeResolvedLinks', () => { beforeEach(() => { - testModel.predecessor = 'predecessor value'; - testModel.successor = 'successor value'; + testModel.predecessor = 'predecessor value' as any; + testModel.successor = 'successor value' as any; spyOnFunction(decorators, 'getLinkDefinitions').and.returnValue([ { resourceType: TEST_MODEL, @@ -213,8 +213,8 @@ describe('LinkService', () => { it('should leave the original object untouched', () => { service.removeResolvedLinks(testModel); - expect(testModel.predecessor).toBe('predecessor value'); - expect(testModel.successor).toBe('successor value'); + expect(testModel.predecessor as any).toBe('predecessor value'); + expect(testModel.successor as any).toBe('successor value'); }); }); diff --git a/src/app/core/cache/object-cache.service.spec.ts b/src/app/core/cache/object-cache.service.spec.ts index c3b7781d70..e7c208e095 100644 --- a/src/app/core/cache/object-cache.service.spec.ts +++ b/src/app/core/cache/object-cache.service.spec.ts @@ -91,7 +91,7 @@ describe('ObjectCacheService', () => { // due to the implementation of spyOn above, this subscribe will be synchronous service.getObjectBySelfLink(selfLink).pipe(first()).subscribe((o) => { - expect(o.self).toBe(selfLink); + expect(o._links.self.href).toBe(selfLink); // this only works if testObj is an instance of TestClass expect(o instanceof Item).toBeTruthy(); } diff --git a/src/app/core/data/relationship.service.spec.ts b/src/app/core/data/relationship.service.spec.ts index f5d370dc0b..247dce1619 100644 --- a/src/app/core/data/relationship.service.spec.ts +++ b/src/app/core/data/relationship.service.spec.ts @@ -33,30 +33,9 @@ describe('RelationshipService', () => { rightwardType: 'isPublicationOfAuthor' }); - const item = Object.assign(new Item(), { - id: 'publication', - uuid: 'publication', - relationships: observableOf(new RemoteData(false, false, true, undefined, new PaginatedList(new PageInfo(), relationships))), - _links: { - relationships: { href: restEndpointURL + '/publication/relationships' }, - self: { href: restEndpointURL + '/publication' } - } - }); - - const relatedItem1 = Object.assign(new Item(), { - id: 'author1', - uuid: 'author1', - _links: { - self: { href: restEndpointURL + '/author1' } - } - }); - const relatedItem2 = Object.assign(new Item(), { - id: 'author2', - uuid: 'author2', - _links: { - self: { href: restEndpointURL + '/author2' } - } - }); + const ri1SelfLink = restEndpointURL + '/author1'; + const ri2SelfLink = restEndpointURL + '/author2'; + const itemSelfLink = restEndpointURL + '/publication'; const relationship1 = Object.assign(new Relationship(), { _links: { @@ -64,10 +43,10 @@ describe('RelationshipService', () => { href: relationshipsEndpointURL + '/2' }, leftItem: { - href: relatedItem1._links.self.href + href: ri1SelfLink }, rightItem: { - href: item._links.self.href + href: itemSelfLink } }, id: '2', @@ -80,18 +59,41 @@ describe('RelationshipService', () => { href: relationshipsEndpointURL + '/3' }, leftItem: { - href: relatedItem2._links.self.href + href: ri2SelfLink }, rightItem: { - href: item._links.self.href - }, + href: itemSelfLink + }, }, id: '3', uuid: '3', relationshipType: observableOf(new RemoteData(false, false, true, undefined, relationshipType)) }); - const relationships = [relationship1, relationship2]; + const relationships = [relationship1, relationship2]; const item = Object.assign(new Item(), { + id: 'publication', + uuid: 'publication', + relationships: observableOf(new RemoteData(false, false, true, undefined, new PaginatedList(new PageInfo(), relationships))), + _links: { + relationships: { href: restEndpointURL + '/publication/relationships' }, + self: { href: itemSelfLink } + } + }); + + const relatedItem1 = Object.assign(new Item(), { + id: 'author1', + uuid: 'author1', + _links: { + self: { href: ri1SelfLink } + } + }); + const relatedItem2 = Object.assign(new Item(), { + id: 'author2', + uuid: 'author2', + _links: { + self: { href: ri2SelfLink } + } + }); relationship1.leftItem = getRemotedataObservable(relatedItem1); relationship1.rightItem = getRemotedataObservable(item); diff --git a/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-range-option/search-facet-range-option.component.spec.ts b/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-range-option/search-facet-range-option.component.spec.ts index e6878dadd1..34fb64040c 100644 --- a/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-range-option/search-facet-range-option.component.spec.ts +++ b/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-range-option/search-facet-range-option.component.spec.ts @@ -38,7 +38,14 @@ describe('SearchFacetRangeOptionComponent', () => { label: value2, value: value2, count: 20, - search: '' + _links: { + self: { + href: '' + }, + search: { + href: '' + } + } }; const searchLink = '/search'; @@ -96,7 +103,14 @@ describe('SearchFacetRangeOptionComponent', () => { label: '50-60', value: '50-60', count: 20, - search: '' + _links: { + self: { + href: '' + }, + search: { + href: '' + } + } }; (comp as any).updateChangeParams(); expect(comp.changeQueryParams).toEqual({ diff --git a/src/app/shared/search/search-filters/search-filter/search-facet-filter/search-facet-filter.component.spec.ts b/src/app/shared/search/search-filters/search-filter/search-facet-filter/search-facet-filter.component.spec.ts index 1b66e29246..7695497750 100644 --- a/src/app/shared/search/search-filters/search-filter/search-facet-filter/search-facet-filter.component.spec.ts +++ b/src/app/shared/search/search-filters/search-filter/search-facet-filter/search-facet-filter.component.spec.ts @@ -39,17 +39,38 @@ describe('SearchFacetFilterComponent', () => { label: value1, value: value1, count: 52, - search: '' + _links: { + self: { + href: '' + }, + search: { + href: '' + } + } }, { label: value2, value: value2, count: 20, - search: '' + _links: { + self: { + href: '' + }, + search: { + href: '' + } + } }, { label: value3, value: value3, count: 5, - search: '' + _links: { + self: { + href: '' + }, + search: { + href: '' + } + } } ]; From df9e6b67f59aba26d705fa0355cf3915bb07b700 Mon Sep 17 00:00:00 2001 From: Art Lowel Date: Wed, 19 Feb 2020 17:51:25 +0100 Subject: [PATCH 35/38] improve thumbnailcomponent test coverage --- src/app/thumbnail/thumbnail.component.spec.ts | 54 ++++++++++++------- src/app/thumbnail/thumbnail.component.ts | 12 ++--- 2 files changed, 40 insertions(+), 26 deletions(-) diff --git a/src/app/thumbnail/thumbnail.component.spec.ts b/src/app/thumbnail/thumbnail.component.spec.ts index c76cd06b1b..da5529fb67 100644 --- a/src/app/thumbnail/thumbnail.component.spec.ts +++ b/src/app/thumbnail/thumbnail.component.spec.ts @@ -4,7 +4,7 @@ import { By } from '@angular/platform-browser'; import { Bitstream } from '../core/shared/bitstream.model'; import { SafeUrlPipe } from '../shared/utils/safe-url-pipe'; -import { ThumbnailComponent } from './thumbnail.component'; +import { THUMBNAIL_PLACEHOLDER, ThumbnailComponent } from './thumbnail.component'; describe('ThumbnailComponent', () => { let comp: ThumbnailComponent; @@ -25,26 +25,40 @@ describe('ThumbnailComponent', () => { el = de.nativeElement; }); - it('should display image', () => { - const thumbnail = new Bitstream(); - thumbnail._links = { - self: { href: 'self.url' }, - bundle: { href: 'bundle.url' }, - format: { href: 'format.url' }, - content: { href: 'content.url' }, - }; - comp.thumbnail = thumbnail; - fixture.detectChanges(); - const image: HTMLElement = de.query(By.css('img')).nativeElement; - expect(image.getAttribute('src')).toBe(comp.thumbnail._links.content.href); + describe('when the thumbnail exists', () => { + it('should display an image', () => { + const thumbnail = new Bitstream(); + thumbnail._links = { + self: { href: 'self.url' }, + bundle: { href: 'bundle.url' }, + format: { href: 'format.url' }, + content: { href: 'content.url' }, + }; + comp.thumbnail = thumbnail; + fixture.detectChanges(); + const image: HTMLElement = de.query(By.css('img')).nativeElement; + expect(image.getAttribute('src')).toBe(comp.thumbnail._links.content.href); + }); + }); + describe(`when the thumbnail doesn't exist`, () => { + describe('and there is a default image', () => { + it('should display the default image', () => { + comp.src = 'http://bit.stream'; + comp.defaultImage = 'http://default.img'; + comp.errorHandler(); + expect(comp.src).toBe(comp.defaultImage); + }); + }); + describe('and there is no default image', () => { + it('should display the placeholder', () => { + comp.src = 'http://default.img'; + comp.defaultImage = 'http://default.img'; + comp.errorHandler(); + expect(comp.src).toBe(THUMBNAIL_PLACEHOLDER); + }) + }); }); - it('should display placeholder', () => { - const thumbnail = new Bitstream(); - comp.thumbnail = thumbnail; - fixture.detectChanges(); - const image: HTMLElement = de.query(By.css('img')).nativeElement; - expect(image.getAttribute('src')).toBe(comp.defaultImage); - }); +; }); diff --git a/src/app/thumbnail/thumbnail.component.ts b/src/app/thumbnail/thumbnail.component.ts index 2134a87267..2bbd2bb2da 100644 --- a/src/app/thumbnail/thumbnail.component.ts +++ b/src/app/thumbnail/thumbnail.component.ts @@ -5,7 +5,7 @@ import { hasValue } from '../shared/empty.util'; /** * A fallback placeholder image as a base64 string */ -const placeholder = 'data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2293%22%20height%3D%22120%22%20viewBox%3D%220%200%2093%20120%22%20preserveAspectRatio%3D%22none%22%3E%3C!--%0ASource%20URL%3A%20holder.js%2F93x120%3Ftext%3DNo%20Thumbnail%0ACreated%20with%20Holder.js%202.8.2.%0ALearn%20more%20at%20http%3A%2F%2Fholderjs.com%0A(c)%202012-2015%20Ivan%20Malopinsky%20-%20http%3A%2F%2Fimsky.co%0A--%3E%3Cdefs%3E%3Cstyle%20type%3D%22text%2Fcss%22%3E%3C!%5BCDATA%5B%23holder_1543e460b05%20text%20%7B%20fill%3A%23AAAAAA%3Bfont-weight%3Abold%3Bfont-family%3AArial%2C%20Helvetica%2C%20Open%20Sans%2C%20sans-serif%2C%20monospace%3Bfont-size%3A10pt%20%7D%20%5D%5D%3E%3C%2Fstyle%3E%3C%2Fdefs%3E%3Cg%20id%3D%22holder_1543e460b05%22%3E%3Crect%20width%3D%2293%22%20height%3D%22120%22%20fill%3D%22%23FFFFFF%22%2F%3E%3Cg%3E%3Ctext%20x%3D%2235.6171875%22%20y%3D%2257%22%3ENo%3C%2Ftext%3E%3Ctext%20x%3D%2210.8125%22%20y%3D%2272%22%3EThumbnail%3C%2Ftext%3E%3C%2Fg%3E%3C%2Fg%3E%3C%2Fsvg%3E'; +export const THUMBNAIL_PLACEHOLDER = 'data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2293%22%20height%3D%22120%22%20viewBox%3D%220%200%2093%20120%22%20preserveAspectRatio%3D%22none%22%3E%3C!--%0ASource%20URL%3A%20holder.js%2F93x120%3Ftext%3DNo%20Thumbnail%0ACreated%20with%20Holder.js%202.8.2.%0ALearn%20more%20at%20http%3A%2F%2Fholderjs.com%0A(c)%202012-2015%20Ivan%20Malopinsky%20-%20http%3A%2F%2Fimsky.co%0A--%3E%3Cdefs%3E%3Cstyle%20type%3D%22text%2Fcss%22%3E%3C!%5BCDATA%5B%23holder_1543e460b05%20text%20%7B%20fill%3A%23AAAAAA%3Bfont-weight%3Abold%3Bfont-family%3AArial%2C%20Helvetica%2C%20Open%20Sans%2C%20sans-serif%2C%20monospace%3Bfont-size%3A10pt%20%7D%20%5D%5D%3E%3C%2Fstyle%3E%3C%2Fdefs%3E%3Cg%20id%3D%22holder_1543e460b05%22%3E%3Crect%20width%3D%2293%22%20height%3D%22120%22%20fill%3D%22%23FFFFFF%22%2F%3E%3Cg%3E%3Ctext%20x%3D%2235.6171875%22%20y%3D%2257%22%3ENo%3C%2Ftext%3E%3Ctext%20x%3D%2210.8125%22%20y%3D%2272%22%3EThumbnail%3C%2Ftext%3E%3C%2Fg%3E%3C%2Fg%3E%3C%2Fsvg%3E'; /** * This component renders a given Bitstream as a thumbnail. @@ -27,7 +27,7 @@ export class ThumbnailComponent implements OnInit { /** * The default image, used if the thumbnail isn't set or can't be downloaded */ - @Input() defaultImage? = placeholder; + @Input() defaultImage? = THUMBNAIL_PLACEHOLDER; /** * The src attribute used in the template to render the image. @@ -51,11 +51,11 @@ export class ThumbnailComponent implements OnInit { * If the image can't be found, use the defaultImage instead. * If that also can't be found, use the base64 placeholder. */ - errorHandler(event) { - if (event.currentTarget.src !== this.defaultImage) { - event.currentTarget.src = this.defaultImage; + errorHandler() { + if (this.src !== this.defaultImage) { + this.src = this.defaultImage; } else { - event.currentTarget.src = placeholder; + this.src = THUMBNAIL_PLACEHOLDER; } } } From 2c12446128ef5fe5cd5bf8244292bc30096f68cc Mon Sep 17 00:00:00 2001 From: Art Lowel Date: Wed, 19 Feb 2020 19:16:42 +0100 Subject: [PATCH 36/38] add tests for build decorators --- .../cache/builders/build-decorators.spec.ts | 83 +++++++++++++++++++ .../core/cache/builders/build-decorators.ts | 21 +---- src/app/thumbnail/thumbnail.component.spec.ts | 3 - 3 files changed, 84 insertions(+), 23 deletions(-) create mode 100644 src/app/core/cache/builders/build-decorators.spec.ts diff --git a/src/app/core/cache/builders/build-decorators.spec.ts b/src/app/core/cache/builders/build-decorators.spec.ts new file mode 100644 index 0000000000..e47cf1a80a --- /dev/null +++ b/src/app/core/cache/builders/build-decorators.spec.ts @@ -0,0 +1,83 @@ +import { HALLink } from '../../shared/hal-link.model'; +import { HALResource } from '../../shared/hal-resource.model'; +import { ResourceType } from '../../shared/resource-type'; +import { + dataService, + getDataServiceFor, + getLinkDefinition, + link, +} from './build-decorators'; + +/* tslint:disable:max-classes-per-file */ +class TestService {} +class AnotherTestService {} +class TestHALResource implements HALResource { + _links: { + self: HALLink; + foo: HALLink; + }; + + bar?: any +} +let testType; + +describe('build decorators', () => { + beforeEach(() => { + testType = new ResourceType('testType-' + new Date().getTime()); + }); + describe('@dataService/getDataServiceFor', () => { + + it('should register a resourcetype for a dataservice', () => { + dataService(testType)(TestService); + expect(getDataServiceFor(testType)).toBe(TestService); + }); + + describe(`when the resource type isn't specified`, () => { + it(`should throw an error`, () => { + expect(() => { + dataService(undefined)(TestService); + }).toThrow(); + }); + }); + + describe(`when there already is a registered dataservice for a resourcetype`, () => { + it(`should throw an error`, () => { + dataService(testType)(TestService); + expect(() => { + dataService(testType)(AnotherTestService); + }).toThrow(); + }); + }); + + }); + + describe(`@link/getLinkDefinitions`, () => { + it(`should register a link`, () => { + const target = new TestHALResource(); + link(testType, true, 'foo')(target, 'bar'); + const result = getLinkDefinition(TestHALResource, 'foo'); + expect(result.resourceType).toBe(testType); + expect(result.isList).toBe(true); + expect(result.linkName).toBe('foo'); + expect(result.propertyName).toBe('bar'); + }); + + describe(`when the linkname isn't specified`, () => { + it(`should use the propertyname`, () => { + const target = new TestHALResource(); + link(testType)(target, 'foo'); + const result = getLinkDefinition(TestHALResource, 'foo'); + expect(result.linkName).toBe('foo'); + expect(result.propertyName).toBe('foo'); + }); + }); + + describe(`when there's no @link`, () => { + it(`should return undefined`, () => { + const result = getLinkDefinition(TestHALResource, 'self'); + expect(result).toBeUndefined(); + }); + }); + }); +}); +/* tslint:enable:max-classes-per-file */ diff --git a/src/app/core/cache/builders/build-decorators.ts b/src/app/core/cache/builders/build-decorators.ts index 50a70e051f..e8382d02cf 100644 --- a/src/app/core/cache/builders/build-decorators.ts +++ b/src/app/core/cache/builders/build-decorators.ts @@ -66,25 +66,6 @@ export function getDataServiceFor(resourceType: Resou return dataServiceMap.get(resourceType.value); } -export function resolvedLink, K extends keyof T>(provider: GenericConstructor, methodName?: K, ...params: any[]): any { - return function r(target: any, propertyKey: string, descriptor: PropertyDescriptor) { - if (!target || !propertyKey) { - return; - } - - const metaDataList: string[] = resolvedLinkMap.get(target.constructor) || []; - if (metaDataList.indexOf(propertyKey) === -1) { - metaDataList.push(propertyKey); - } - resolvedLinkMap.set(target.constructor, metaDataList); - return Reflect.metadata(resolvedLinkKey, { - provider, - methodName, - params - }).apply(this, arguments); - }; -} - /** * A class to represent the data that can be set by the @link decorator */ @@ -124,7 +105,7 @@ export const link = ( linkName = propertyName as any; } - targetMap.set(propertyName, { + targetMap.set(linkName, { resourceType, isList, linkName, diff --git a/src/app/thumbnail/thumbnail.component.spec.ts b/src/app/thumbnail/thumbnail.component.spec.ts index da5529fb67..c4258aceb9 100644 --- a/src/app/thumbnail/thumbnail.component.spec.ts +++ b/src/app/thumbnail/thumbnail.component.spec.ts @@ -58,7 +58,4 @@ describe('ThumbnailComponent', () => { }) }); }); - -; - }); From f7f6600806e9fad0e6b694b41f59827835cf1c90 Mon Sep 17 00:00:00 2001 From: Art Lowel Date: Thu, 20 Feb 2020 09:28:46 +0100 Subject: [PATCH 37/38] remove event from errorHandler call --- src/app/thumbnail/thumbnail.component.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/thumbnail/thumbnail.component.html b/src/app/thumbnail/thumbnail.component.html index 87fd0251f5..dbf8f6732c 100644 --- a/src/app/thumbnail/thumbnail.component.html +++ b/src/app/thumbnail/thumbnail.component.html @@ -1,4 +1,4 @@
- +
From dea6638c1fa969384240aa252475cdc813977bef Mon Sep 17 00:00:00 2001 From: Art Lowel Date: Thu, 20 Feb 2020 11:00:43 +0100 Subject: [PATCH 38/38] add docs, process PR feedback --- src/app/core/auth/models/auth-status.model.ts | 4 +-- .../core/cache/builders/build-decorators.ts | 2 +- src/app/core/cache/builders/link.service.ts | 2 +- .../builders/remote-data-build.service.ts | 4 +-- .../models/config-submission-section.model.ts | 2 +- src/app/core/data/bitstream-data.service.ts | 32 +++++++++++++++++-- src/app/core/data/bundle-data.service.ts | 16 +++++++++- src/app/core/data/collection-data.service.ts | 2 +- src/app/core/data/data.service.ts | 22 ++++++------- src/app/core/data/entity-type-data.service.ts | 26 ++++++++++----- src/app/core/data/entity-type.service.ts | 2 +- src/app/core/data/license-data.service.ts | 22 +++++++++++++ src/app/core/data/resource-policy.service.ts | 22 +++++++++++++ src/app/core/eperson/eperson-data.service.ts | 3 ++ src/app/core/eperson/models/eperson.model.ts | 2 +- src/app/core/eperson/models/group.model.ts | 4 +-- .../integration/models/authority.value.ts | 2 +- src/app/core/metadata/metadata-field.model.ts | 4 +-- ...egistry-bitstreamformats-response.model.ts | 2 +- src/app/core/shared/bitstream-format.model.ts | 2 +- src/app/core/shared/bitstream.model.ts | 6 ++-- src/app/core/shared/bundle.model.ts | 2 +- src/app/core/shared/collection.model.ts | 8 ++--- src/app/core/shared/community.model.ts | 8 ++--- src/app/core/shared/content-source.model.ts | 2 +- .../shared/external-source-entry.model.ts | 2 +- src/app/core/shared/external-source.model.ts | 2 +- src/app/core/shared/hal-link.model.ts | 18 +++++++++++ src/app/core/shared/hal-resource.model.ts | 15 +++++++++ .../item-relationships/item-type.model.ts | 2 +- .../relationship-type.model.ts | 6 ++-- .../item-relationships/relationship.model.ts | 8 ++--- src/app/core/shared/item.model.ts | 8 ++--- src/app/core/shared/page-info.model.ts | 2 +- src/app/core/shared/resource-policy.model.ts | 2 +- .../models/submission-object.model.ts | 10 +++--- .../submission-object-data.service.ts | 2 +- .../submission-response-parsing.service.ts | 13 ++++++-- .../core/tasks/models/task-object.model.ts | 8 ++--- .../workspaceitem-actions.component.ts | 5 --- src/app/shared/search/facet-value.model.ts | 2 +- src/app/shared/search/search-result.model.ts | 2 +- .../shared/utils/follow-link-config.model.ts | 6 ++-- 43 files changed, 225 insertions(+), 91 deletions(-) diff --git a/src/app/core/auth/models/auth-status.model.ts b/src/app/core/auth/models/auth-status.model.ts index df6cc5490f..edad46a7bc 100644 --- a/src/app/core/auth/models/auth-status.model.ts +++ b/src/app/core/auth/models/auth-status.model.ts @@ -54,7 +54,7 @@ export class AuthStatus implements CacheableObject { authenticated: boolean; /** - * The HALLinks for this AuthStatus + * The {@link HALLink}s for this AuthStatus */ @deserialize _links: { @@ -64,7 +64,7 @@ export class AuthStatus implements CacheableObject { /** * The EPerson of this auth status - * Will be undefined unless the eperson HALLink has been resolved. + * Will be undefined unless the eperson {@link HALLink} has been resolved. */ @link(EPERSON) eperson?: Observable>; diff --git a/src/app/core/cache/builders/build-decorators.ts b/src/app/core/cache/builders/build-decorators.ts index e8382d02cf..4ba04bfa55 100644 --- a/src/app/core/cache/builders/build-decorators.ts +++ b/src/app/core/cache/builders/build-decorators.ts @@ -86,7 +86,7 @@ export class LinkDefinition { * @param resourceType the resource type of the object(s) the link retrieves * @param isList an optional boolean indicating whether or not it concerns a list, * defaults to false - * @param linkName an optional string in case the HALLink name differs from the + * @param linkName an optional string in case the {@link HALLink} name differs from the * property name */ export const link = ( diff --git a/src/app/core/cache/builders/link.service.ts b/src/app/core/cache/builders/link.service.ts index 87f8eabd92..c41a5484a1 100644 --- a/src/app/core/cache/builders/link.service.ts +++ b/src/app/core/cache/builders/link.service.ts @@ -7,7 +7,7 @@ import { getDataServiceFor, getLinkDefinition, getLinkDefinitions, LinkDefinitio /** * A Service to handle the resolving and removing - * of resolved HALLinks on HALResources + * of resolved {@link HALLink}s on HALResources */ @Injectable({ providedIn: 'root' diff --git a/src/app/core/cache/builders/remote-data-build.service.ts b/src/app/core/cache/builders/remote-data-build.service.ts index 46b5f28465..94c660d672 100644 --- a/src/app/core/cache/builders/remote-data-build.service.ts +++ b/src/app/core/cache/builders/remote-data-build.service.ts @@ -38,7 +38,7 @@ export class RemoteDataBuildService { * Creates a single {@link RemoteData} object based on the response of a request to the REST server, with a list of * {@link FollowLinkConfig} that indicate which embedded info should be added to the object * @param href$ Observable href of object we want to retrieve - * @param linksToFollow List of {@link FollowLinkConfig} that indicate which HALLinks should be automatically resolved + * @param linksToFollow List of {@link FollowLinkConfig} that indicate which {@link HALLink}s should be automatically resolved */ buildSingle(href$: string | Observable, ...linksToFollow: Array>): Observable> { if (typeof href$ === 'string') { @@ -122,7 +122,7 @@ export class RemoteDataBuildService { * Creates a list of {@link RemoteData} objects based on the response of a request to the REST server, with a list of * {@link FollowLinkConfig} that indicate which embedded info should be added to the objects * @param href$ Observable href of objects we want to retrieve - * @param linksToFollow List of {@link FollowLinkConfig} that indicate which HALLinks should be automatically resolved + * @param linksToFollow List of {@link FollowLinkConfig} that indicate which {@link HALLink}s should be automatically resolved */ buildList(href$: string | Observable, ...linksToFollow: Array>): Observable>> { if (typeof href$ === 'string') { diff --git a/src/app/core/config/models/config-submission-section.model.ts b/src/app/core/config/models/config-submission-section.model.ts index 5a9c3225ab..d8249297b1 100644 --- a/src/app/core/config/models/config-submission-section.model.ts +++ b/src/app/core/config/models/config-submission-section.model.ts @@ -43,7 +43,7 @@ export class SubmissionSectionModel extends ConfigObject { visibility: SubmissionSectionVisibility; /** - * The HALLinks for this SubmissionSectionModel + * The {@link HALLink}s for this SubmissionSectionModel */ @deserialize _links: { diff --git a/src/app/core/data/bitstream-data.service.ts b/src/app/core/data/bitstream-data.service.ts index e1d55598e4..408dceb56e 100644 --- a/src/app/core/data/bitstream-data.service.ts +++ b/src/app/core/data/bitstream-data.service.ts @@ -25,12 +25,18 @@ import { RemoteDataError } from './remote-data-error'; import { FindListOptions } from './request.models'; import { RequestService } from './request.service'; +/** + * A service to retrieve {@link Bitstream}s from the REST API + */ @Injectable({ providedIn: 'root' }) @dataService(BITSTREAM) export class BitstreamDataService extends DataService { + /** + * The HAL path to the bitstream endpoint + */ protected linkPath = 'bitstreams'; constructor( @@ -49,7 +55,7 @@ export class BitstreamDataService extends DataService { } /** - * Retrieves the bitstreams in a given bundle + * Retrieves the {@link Bitstream}s in a given bundle * * @param bundle the bundle to retrieve bitstreams from * @param options options for the find all request @@ -60,9 +66,9 @@ export class BitstreamDataService extends DataService { /** * Retrieves the thumbnail for the given item - * @returns {Observable>} the first bitstream in the THUMBNAIL bundle + * @returns {Observable>} the first bitstream in the THUMBNAIL bundle */ - // TODO should be implemented rest side. Item should get a thumbnail link + // TODO should be implemented rest side. {@link Item} should get a thumbnail link public getThumbnailFor(item: Item): Observable> { return this.bundleService.findByItemAndName(item, 'THUMBNAIL').pipe( switchMap((bundleRD: RemoteData) => { @@ -89,6 +95,15 @@ export class BitstreamDataService extends DataService { ); } + /** + * Retrieve the matching thumbnail for a {@link Bitstream}. + * + * The {@link Item} is technically redundant, but is available + * in all current use cases, and having it simplifies this method + * + * @param item The {@link Item} the {@link Bitstream} and its thumbnail are a part of + * @param bitstreamInOriginal The original {@link Bitstream} to find the thumbnail for + */ // TODO should be implemented rest side public getMatchingThumbnail(item: Item, bitstreamInOriginal: Bitstream): Observable> { return this.bundleService.findByItemAndName(item, 'THUMBNAIL').pipe( @@ -129,6 +144,17 @@ export class BitstreamDataService extends DataService { ); } + /** + * Retrieve all {@link Bitstream}s in a certain {@link Bundle}. + * + * The {@link Item} is technically redundant, but is available + * in all current use cases, and having it simplifies this method + * + * @param item the {@link Item} the {@link Bundle} is a part of + * @param bundleName the name of the {@link Bundle} we want to find {@link Bitstream}s for + * @param options the {@link FindListOptions} for the request + * @param linksToFollow the {@link FollowLinkConfig}s for the request + */ public findAllByItemAndBundleName(item: Item, bundleName: string, options?: FindListOptions, ...linksToFollow: Array>): Observable>> { return this.bundleService.findByItemAndName(item, bundleName).pipe( switchMap((bundleRD: RemoteData) => { diff --git a/src/app/core/data/bundle-data.service.ts b/src/app/core/data/bundle-data.service.ts index 5a5d52b637..64d58eb8ec 100644 --- a/src/app/core/data/bundle-data.service.ts +++ b/src/app/core/data/bundle-data.service.ts @@ -22,7 +22,7 @@ import { FindListOptions } from './request.models'; import { RequestService } from './request.service'; /** - * A service responsible for fetching/sending data from/to the REST API on the bundles endpoint + * A service to retrieve {@link Bundle}s from the REST API */ @Injectable( {providedIn: 'root'} @@ -43,10 +43,24 @@ export class BundleDataService extends DataService { super(); } + /** + * Retrieve all {@link Bundle}s in the given {@link Item} + * + * @param item the {@link Item} the {@link Bundle}s are a part of + * @param options the {@link FindListOptions} for the request + * @param linksToFollow the {@link FollowLinkConfig}s for the request + */ findAllByItem(item: Item, options?: FindListOptions, ...linksToFollow: Array>): Observable>> { return this.findAllByHref(item._links.bundles.href, options, ...linksToFollow); } + /** + * Retrieve a {@link Bundle} in the given {@link Item} by name + * + * @param item the {@link Item} the {@link Bundle}s are a part of + * @param bundleName the name of the {@link Bundle} to retrieve + * @param linksToFollow the {@link FollowLinkConfig}s for the request + */ // TODO should be implemented rest side findByItemAndName(item: Item, bundleName: string, ...linksToFollow: Array>): Observable> { return this.findAllByItem(item, { elementsPerPage: Number.MAX_SAFE_INTEGER }, ...linksToFollow).pipe( diff --git a/src/app/core/data/collection-data.service.ts b/src/app/core/data/collection-data.service.ts index 4c64b0a60b..6ae40f4ca9 100644 --- a/src/app/core/data/collection-data.service.ts +++ b/src/app/core/data/collection-data.service.ts @@ -209,7 +209,7 @@ export class CollectionDataService extends ComColDataService { * Fetches a list of items that are mapped to a collection * @param collectionId The id of the collection * @param searchOptions Search options to sort or filter out items - * @param linksToFollow List of {@link FollowLinkConfig} that indicate which HALLinks should be automatically resolved + * @param linksToFollow List of {@link FollowLinkConfig} that indicate which {@link HALLink}s should be automatically resolved */ getMappedItems(collectionId: string, searchOptions?: PaginatedSearchOptions, ...linksToFollow: Array>): Observable>> { const requestUuid = this.requestService.generateRequestId(); diff --git a/src/app/core/data/data.service.ts b/src/app/core/data/data.service.ts index 5d0b8774e1..3be1ef9768 100644 --- a/src/app/core/data/data.service.ts +++ b/src/app/core/data/data.service.ts @@ -152,7 +152,7 @@ export abstract class DataService { /** * Returns {@link RemoteData} of all object with a list of {@link FollowLinkConfig}, to indicate which embedded * info should be added to the objects - * @param linksToFollow List of {@link FollowLinkConfig} that indicate which HALLinks should be automatically resolved + * @param linksToFollow List of {@link FollowLinkConfig} that indicate which {@link HALLink}s should be automatically resolved */ findAll(options: FindListOptions = {}, ...linksToFollow: Array>): Observable>> { return this.findList(this.getFindAllHref(options), options, ...linksToFollow); @@ -160,9 +160,9 @@ export abstract class DataService { /** * Returns an observable of {@link RemoteData} of an object, based on href observable, - * with a list of {@link FollowLinkConfig}, to automatically resolve HALLinks of the object + * with a list of {@link FollowLinkConfig}, to automatically resolve {@link HALLink}s of the object * @param href$ Observable of href of object we want to retrieve - * @param linksToFollow List of {@link FollowLinkConfig} that indicate which HALLinks should be automatically resolved + * @param linksToFollow List of {@link FollowLinkConfig} that indicate which {@link HALLink}s should be automatically resolved */ protected findList(href$, options: FindListOptions, ...linksToFollow: Array>) { href$.pipe( @@ -189,9 +189,9 @@ export abstract class DataService { /** * Returns an observable of {@link RemoteData} of an object, based on its ID, with a list of {@link FollowLinkConfig}, - * to automatically resolve HALLinks of the object + * to automatically resolve {@link HALLink}s of the object * @param id ID of object we want to retrieve - * @param linksToFollow List of {@link FollowLinkConfig} that indicate which HALLinks should be automatically resolved + * @param linksToFollow List of {@link FollowLinkConfig} that indicate which {@link HALLink}s should be automatically resolved */ findById(id: string, ...linksToFollow: Array>): Observable> { @@ -213,9 +213,9 @@ export abstract class DataService { /** * Returns an observable of {@link RemoteData} of an object, based on an href, with a list of {@link FollowLinkConfig}, - * to automatically resolve HALLinks of the object - * @param href Href of object we want to retrieve - * @param linksToFollow List of {@link FollowLinkConfig} that indicate which HALLinks should be automatically resolved + * to automatically resolve {@link HALLink}s of the object + * @param href The url of object we want to retrieve + * @param linksToFollow List of {@link FollowLinkConfig} that indicate which {@link HALLink}s should be automatically resolved */ findByHref(href: string, ...linksToFollow: Array>): Observable> { const requestHref = this.buildHrefFromFindOptions(href, {}, []); @@ -229,9 +229,9 @@ export abstract class DataService { /** * Returns a list of observables of {@link RemoteData} of objects, based on an href, with a list of {@link FollowLinkConfig}, - * to automatically resolve HALLinks of the object - * @param id ID of object we want to retrieve - * @param linksToFollow List of {@link FollowLinkConfig} that indicate which HALLinks should be automatically resolved + * to automatically resolve {@link HALLink}s of the object + * @param href The url of object we want to retrieve + * @param linksToFollow List of {@link FollowLinkConfig} that indicate which {@link HALLink}s should be automatically resolved */ findAllByHref(href: string, findListOptions: FindListOptions = {}, ...linksToFollow: Array>): Observable>> { const requestHref = this.buildHrefFromFindOptions(href, findListOptions, []); diff --git a/src/app/core/data/entity-type-data.service.ts b/src/app/core/data/entity-type-data.service.ts index 80b6beed81..87de69b935 100644 --- a/src/app/core/data/entity-type-data.service.ts +++ b/src/app/core/data/entity-type-data.service.ts @@ -19,6 +19,10 @@ import { FindListOptions } from './request.models'; import { RequestService } from './request.service'; /* tslint:disable:max-classes-per-file */ + +/** + * A private DataService implementation to delegate specific methods to. + */ class DataServiceImpl extends DataService { protected linkPath = 'entitytypes'; @@ -35,9 +39,15 @@ class DataServiceImpl extends DataService { } } +/** + * A service to retrieve {@link ItemType}s from the REST API. + */ @Injectable() @dataService(ITEM_TYPE) export class ItemTypeDataService { + /** + * A private DataService instance to delegate specific methods to. + */ private dataService: DataServiceImpl; constructor( @@ -53,20 +63,20 @@ export class ItemTypeDataService { } /** - * Returns an observable of {@link RemoteData} of an object, based on an href, with a list of {@link FollowLinkConfig}, - * to automatically resolve HALLinks of the object - * @param href Href of object we want to retrieve - * @param linksToFollow List of {@link FollowLinkConfig} that indicate which HALLinks should be automatically resolved + * Returns an observable of {@link RemoteData} of an {@link ItemType}, based on an href, with a list of {@link FollowLinkConfig}, + * to automatically resolve {@link HALLink}s of the {@link ItemType} + * @param href The url of {@link ItemType} we want to retrieve + * @param linksToFollow List of {@link FollowLinkConfig} that indicate which {@link HALLink}s should be automatically resolved */ findByHref(href: string, ...linksToFollow: Array>): Observable> { return this.dataService.findByHref(href, ...linksToFollow); } /** - * Returns a list of observables of {@link RemoteData} of objects, based on an href, with a list of {@link FollowLinkConfig}, - * to automatically resolve HALLinks of the object - * @param id ID of object we want to retrieve - * @param linksToFollow List of {@link FollowLinkConfig} that indicate which HALLinks should be automatically resolved + * Returns a list of observables of {@link RemoteData} of {@link ItemType}s, based on an href, with a list of {@link FollowLinkConfig}, + * to automatically resolve {@link HALLink}s of the {@link ItemType} + * @param href The url of the {@link ItemType} we want to retrieve + * @param linksToFollow List of {@link FollowLinkConfig} that indicate which {@link HALLink}s should be automatically resolved */ findByAllHref(href: string, findListOptions: FindListOptions = {}, ...linksToFollow: Array>): Observable>> { return this.dataService.findAllByHref(href, findListOptions, ...linksToFollow); diff --git a/src/app/core/data/entity-type.service.ts b/src/app/core/data/entity-type.service.ts index 5726aeb982..b8e8b7cd9a 100644 --- a/src/app/core/data/entity-type.service.ts +++ b/src/app/core/data/entity-type.service.ts @@ -54,7 +54,7 @@ export class EntityTypeService extends DataService { /** * Get the allowed relationship types for an entity type * @param entityTypeId - * @param linksToFollow List of {@link FollowLinkConfig} that indicate which HALLinks should be automatically resolved + * @param linksToFollow List of {@link FollowLinkConfig} that indicate which {@link HALLink}s should be automatically resolved */ getEntityTypeRelationships(entityTypeId: string, ...linksToFollow: Array>): Observable>> { diff --git a/src/app/core/data/license-data.service.ts b/src/app/core/data/license-data.service.ts index 24b77a41a6..23637be596 100644 --- a/src/app/core/data/license-data.service.ts +++ b/src/app/core/data/license-data.service.ts @@ -19,6 +19,10 @@ import { FindListOptions } from './request.models'; import { RequestService } from './request.service'; /* tslint:disable:max-classes-per-file */ + +/** + * A private DataService implementation to delegate specific methods to. + */ class DataServiceImpl extends DataService { protected linkPath = ''; @@ -35,9 +39,15 @@ class DataServiceImpl extends DataService { } } +/** + * A service to retrieve {@link License}s from the REST API. + */ @Injectable() @dataService(LICENSE) export class LicenseDataService { + /** + * A private DataService instance to delegate specific methods to. + */ private dataService: DataServiceImpl; constructor( @@ -52,10 +62,22 @@ export class LicenseDataService { this.dataService = new DataServiceImpl(requestService, rdbService, null, objectCache, halService, notificationsService, http, comparator); } + /** + * Returns an observable of {@link RemoteData} of a {@link License}, based on an href, with a list of {@link FollowLinkConfig}, + * to automatically resolve {@link HALLink}s of the {@link License} + * @param href The URL of object we want to retrieve + * @param linksToFollow List of {@link FollowLinkConfig} that indicate which {@link HALLink}s should be automatically resolved + */ findByHref(href: string, ...linksToFollow: Array>): Observable> { return this.dataService.findByHref(href, ...linksToFollow); } + /** + * Returns a list of observables of {@link RemoteData} of {@link License}s, based on an href, with a list of {@link FollowLinkConfig}, + * to automatically resolve {@link HALLink}s of the {@link License} + * @param href The URL of object we want to retrieve + * @param linksToFollow List of {@link FollowLinkConfig} that indicate which {@link HALLink}s should be automatically resolved + */ findByAllHref(href: string, findListOptions: FindListOptions = {}, ...linksToFollow: Array>): Observable>> { return this.dataService.findAllByHref(href, findListOptions, ...linksToFollow); } diff --git a/src/app/core/data/resource-policy.service.ts b/src/app/core/data/resource-policy.service.ts index 9401168984..f66032925e 100644 --- a/src/app/core/data/resource-policy.service.ts +++ b/src/app/core/data/resource-policy.service.ts @@ -23,6 +23,10 @@ import { DefaultChangeAnalyzer } from '../data/default-change-analyzer.service'; import { PaginatedList } from './paginated-list'; /* tslint:disable:max-classes-per-file */ + +/** + * A private DataService implementation to delegate specific methods to. + */ class DataServiceImpl extends DataService { protected linkPath = 'resourcepolicies'; @@ -59,14 +63,32 @@ export class ResourcePolicyService { this.dataService = new DataServiceImpl(requestService, rdbService, null, objectCache, halService, notificationsService, http, comparator); } + /** + * Returns an observable of {@link RemoteData} of a {@link ResourcePolicy}, based on an href, with a list of {@link FollowLinkConfig}, + * to automatically resolve {@link HALLink}s of the {@link ResourcePolicy} + * @param href The url of {@link ResourcePolicy} we want to retrieve + * @param linksToFollow List of {@link FollowLinkConfig} that indicate which {@link HALLink}s should be automatically resolved + */ findByHref(href: string, ...linksToFollow: Array>): Observable> { return this.dataService.findByHref(href, ...linksToFollow); } + /** + * Returns a list of observables of {@link RemoteData} of {@link ResourcePolicy}s, based on an href, with a list of {@link FollowLinkConfig}, + * to automatically resolve {@link HALLink}s of the {@link ResourcePolicy} + * @param href The url of the {@link ResourcePolicy} we want to retrieve + * @param linksToFollow List of {@link FollowLinkConfig} that indicate which {@link HALLink}s should be automatically resolved + */ findAllByHref(href: string, findListOptions: FindListOptions = {}, ...linksToFollow: Array>): Observable>> { return this.dataService.findAllByHref(href, findListOptions, ...linksToFollow); } + /** + * Return the defaultAccessConditions {@link ResourcePolicy} list for a given {@link Collection} + * + * @param collection the {@link Collection} to retrieve the defaultAccessConditions for + * @param findListOptions the {@link FindListOptions} for the request + */ getDefaultAccessConditionsFor(collection: Collection, findListOptions?: FindListOptions): Observable>> { return this.dataService.findAllByHref(collection._links.defaultAccessConditions.href, findListOptions); } diff --git a/src/app/core/eperson/eperson-data.service.ts b/src/app/core/eperson/eperson-data.service.ts index 2c1a27f4e5..f41cfc3ca0 100644 --- a/src/app/core/eperson/eperson-data.service.ts +++ b/src/app/core/eperson/eperson-data.service.ts @@ -13,6 +13,9 @@ import { HALEndpointService } from '../shared/hal-endpoint.service'; import { EPerson } from './models/eperson.model'; import { EPERSON } from './models/eperson.resource-type'; +/** + * A service to retrieve {@link EPerson}s from the REST API + */ @Injectable() @dataService(EPERSON) export class EPersonDataService extends DataService { diff --git a/src/app/core/eperson/models/eperson.model.ts b/src/app/core/eperson/models/eperson.model.ts index a0e6266311..bb99022112 100644 --- a/src/app/core/eperson/models/eperson.model.ts +++ b/src/app/core/eperson/models/eperson.model.ts @@ -71,7 +71,7 @@ export class EPerson extends DSpaceObject { /** * The list of Groups this EPerson is part of - * Will be undefined unless the groups HALLink has been resolved. + * Will be undefined unless the groups {@link HALLink} has been resolved. */ @link(GROUP, true) public groups?: Observable>>; diff --git a/src/app/core/eperson/models/group.model.ts b/src/app/core/eperson/models/group.model.ts index 3dae9bf864..5d531800b8 100644 --- a/src/app/core/eperson/models/group.model.ts +++ b/src/app/core/eperson/models/group.model.ts @@ -26,7 +26,7 @@ export class Group extends DSpaceObject { public permanent: boolean; /** - * The HALLinks for this Group + * The {@link HALLink}s for this Group */ @deserialize _links: { @@ -36,7 +36,7 @@ export class Group extends DSpaceObject { /** * The list of Groups this Group is part of - * Will be undefined unless the groups HALLink has been resolved. + * Will be undefined unless the groups {@link HALLink} has been resolved. */ @link(GROUP, true) public groups?: Observable>>; diff --git a/src/app/core/integration/models/authority.value.ts b/src/app/core/integration/models/authority.value.ts index 9fb64a2555..4e0183603b 100644 --- a/src/app/core/integration/models/authority.value.ts +++ b/src/app/core/integration/models/authority.value.ts @@ -47,7 +47,7 @@ export class AuthorityValue extends IntegrationModel implements MetadataValueInt language: string; /** - * The HALLinks for this AuthorityValue + * The {@link HALLink}s for this AuthorityValue */ @deserialize _links: { diff --git a/src/app/core/metadata/metadata-field.model.ts b/src/app/core/metadata/metadata-field.model.ts index 44a0f14e82..ad7ec59b25 100644 --- a/src/app/core/metadata/metadata-field.model.ts +++ b/src/app/core/metadata/metadata-field.model.ts @@ -49,7 +49,7 @@ export class MetadataField extends ListableObject implements HALResource { scopeNote: string; /** - * The HALLinks for this MetadataField + * The {@link HALLink}s for this MetadataField */ @deserialize _links: { @@ -59,7 +59,7 @@ export class MetadataField extends ListableObject implements HALResource { /** * The MetadataSchema for this MetadataField - * Will be undefined unless the schema HALLink has been resolved. + * Will be undefined unless the schema {@link HALLink} has been resolved. */ // TODO the responseparsingservice assumes schemas are always embedded. This should use remotedata, and be a link instead. // @link(METADATA_SCHEMA) diff --git a/src/app/core/registry/registry-bitstreamformats-response.model.ts b/src/app/core/registry/registry-bitstreamformats-response.model.ts index 0e346db03d..4da30b4ffc 100644 --- a/src/app/core/registry/registry-bitstreamformats-response.model.ts +++ b/src/app/core/registry/registry-bitstreamformats-response.model.ts @@ -10,7 +10,7 @@ export class RegistryBitstreamformatsResponse { page: PageInfo; /** - * The HALLinks for this RegistryBitstreamformatsResponse + * The {@link HALLink}s for this RegistryBitstreamformatsResponse */ @deserialize _links: { diff --git a/src/app/core/shared/bitstream-format.model.ts b/src/app/core/shared/bitstream-format.model.ts index 1fdb707aaf..8aeba1e3cd 100644 --- a/src/app/core/shared/bitstream-format.model.ts +++ b/src/app/core/shared/bitstream-format.model.ts @@ -75,7 +75,7 @@ export class BitstreamFormat implements CacheableObject { id: string; /** - * The HALLinks for this BitstreamFormat + * The {@link HALLink}s for this BitstreamFormat */ @deserialize _links: { diff --git a/src/app/core/shared/bitstream.model.ts b/src/app/core/shared/bitstream.model.ts index d4060f96a6..231d44eeff 100644 --- a/src/app/core/shared/bitstream.model.ts +++ b/src/app/core/shared/bitstream.model.ts @@ -33,7 +33,7 @@ export class Bitstream extends DSpaceObject implements HALResource { bundleName: string; /** - * The HALLinks for this Bitstream + * The {@link HALLink}s for this Bitstream */ @deserialize _links: { @@ -45,14 +45,14 @@ export class Bitstream extends DSpaceObject implements HALResource { /** * The thumbnail for this Bitstream - * Needs to be resolved first, but isn't available as a HALLink yet + * Needs to be resolved first, but isn't available as a {@link HALLink} yet * Use BitstreamDataService.getThumbnailFor(…) for now. */ thumbnail?: Observable>; /** * The BitstreamFormat of this Bitstream - * Will be undefined unless the format HALLink has been resolved. + * Will be undefined unless the format {@link HALLink} has been resolved. */ @link(BITSTREAM_FORMAT) format?: Observable>; diff --git a/src/app/core/shared/bundle.model.ts b/src/app/core/shared/bundle.model.ts index c2fb25f5b7..c1164f0fc4 100644 --- a/src/app/core/shared/bundle.model.ts +++ b/src/app/core/shared/bundle.model.ts @@ -10,7 +10,7 @@ export class Bundle extends DSpaceObject { static type = BUNDLE; /** - * The HALLinks for this Bundle + * The {@link HALLink}s for this Bundle */ @deserialize _links: { diff --git a/src/app/core/shared/collection.model.ts b/src/app/core/shared/collection.model.ts index 33a8fd444e..d5c6221428 100644 --- a/src/app/core/shared/collection.model.ts +++ b/src/app/core/shared/collection.model.ts @@ -25,7 +25,7 @@ export class Collection extends DSpaceObject { handle: string; /** - * The HALLinks for this Collection + * The {@link HALLink}s for this Collection */ @deserialize _links: { @@ -40,21 +40,21 @@ export class Collection extends DSpaceObject { /** * The license for this Collection - * Will be undefined unless the license HALLink has been resolved. + * Will be undefined unless the license {@link HALLink} has been resolved. */ @link(LICENSE) license?: Observable>; /** * The logo for this Collection - * Will be undefined unless the logo HALLink has been resolved. + * Will be undefined unless the logo {@link HALLink} has been resolved. */ @link(BITSTREAM) logo?: Observable>; /** * The default access conditions for this Collection - * Will be undefined unless the defaultAccessConditions HALLink has been resolved. + * Will be undefined unless the defaultAccessConditions {@link HALLink} has been resolved. */ @link(RESOURCE_POLICY, true) defaultAccessConditions?: Observable>>; diff --git a/src/app/core/shared/community.model.ts b/src/app/core/shared/community.model.ts index 66e71176f3..703c4b3eef 100644 --- a/src/app/core/shared/community.model.ts +++ b/src/app/core/shared/community.model.ts @@ -23,7 +23,7 @@ export class Community extends DSpaceObject { handle: string; /** - * The HALLinks for this Community + * The {@link HALLink}s for this Community */ @deserialize _links: { @@ -35,21 +35,21 @@ export class Community extends DSpaceObject { /** * The logo for this Community - * Will be undefined unless the logo HALLink has been resolved. + * Will be undefined unless the logo {@link HALLink} has been resolved. */ @link(BITSTREAM) logo?: Observable>; /** * The list of Collections that are direct children of this Community - * Will be undefined unless the collections HALLink has been resolved. + * Will be undefined unless the collections {@link HALLink} has been resolved. */ @link(COLLECTION, true) collections?: Observable>>; /** * The list of Communities that are direct children of this Community - * Will be undefined unless the subcommunities HALLink has been resolved. + * Will be undefined unless the subcommunities {@link HALLink} has been resolved. */ @link(COMMUNITY, true) subcommunities?: Observable>>; diff --git a/src/app/core/shared/content-source.model.ts b/src/app/core/shared/content-source.model.ts index 82cacd91ed..3e530b6a3a 100644 --- a/src/app/core/shared/content-source.model.ts +++ b/src/app/core/shared/content-source.model.ts @@ -55,7 +55,7 @@ export class ContentSource implements HALResource { metadataConfigs: MetadataConfig[]; /** - * The HALLinks for this ContentSource + * The {@link HALLink}s for this ContentSource */ @deserialize _links: { diff --git a/src/app/core/shared/external-source-entry.model.ts b/src/app/core/shared/external-source-entry.model.ts index 876ca12f83..5836a01138 100644 --- a/src/app/core/shared/external-source-entry.model.ts +++ b/src/app/core/shared/external-source-entry.model.ts @@ -53,7 +53,7 @@ export class ExternalSourceEntry extends ListableObject { metadata: MetadataMap; /** - * The HALLinks for this ExternalSourceEntry + * The {@link HALLink}s for this ExternalSourceEntry */ @deserialize _links: { diff --git a/src/app/core/shared/external-source.model.ts b/src/app/core/shared/external-source.model.ts index 718ac4ff49..5005fbcd36 100644 --- a/src/app/core/shared/external-source.model.ts +++ b/src/app/core/shared/external-source.model.ts @@ -39,7 +39,7 @@ export class ExternalSource extends CacheableObject { hierarchical: boolean; /** - * The HALLinks for this ExternalSource + * The {@link HALLink}s for this ExternalSource */ @deserialize _links: { diff --git a/src/app/core/shared/hal-link.model.ts b/src/app/core/shared/hal-link.model.ts index 32c4c7c99f..88a136a4b2 100644 --- a/src/app/core/shared/hal-link.model.ts +++ b/src/app/core/shared/hal-link.model.ts @@ -1,5 +1,23 @@ +/** + * A single link in the _links section of a {@link HALResource} + */ export class HALLink { + + /** + * The url of the {@link HALLink}'s target + */ href: string; + + /** + * The name of the {@link HALLink} + */ name?: string; + + /** + * A boolean indicating whether the href contains a template. + * + * e.g. if href is "http://haltalk.herokuapp.com/docs/{rel}" + * {rel} would be the template + */ templated?: boolean } diff --git a/src/app/core/shared/hal-resource.model.ts b/src/app/core/shared/hal-resource.model.ts index d42484febb..b6ef822a23 100644 --- a/src/app/core/shared/hal-resource.model.ts +++ b/src/app/core/shared/hal-resource.model.ts @@ -1,8 +1,23 @@ import { HALLink } from './hal-link.model'; +/** + * Represents HAL resources. + * + * A HAL resource has a _links section with at least a self link. + */ export class HALResource { + /** + * The {@link HALLink}s for this {@link HALResource} + */ _links: { + /** + * The {@link HALLink} that refers to this {@link HALResource} + */ self: HALLink + + /** + * {@link HALLink}s to related {@link HALResource}s + */ [k: string]: HALLink; }; } diff --git a/src/app/core/shared/item-relationships/item-type.model.ts b/src/app/core/shared/item-relationships/item-type.model.ts index 7ff7ba9e74..d41024cdaa 100644 --- a/src/app/core/shared/item-relationships/item-type.model.ts +++ b/src/app/core/shared/item-relationships/item-type.model.ts @@ -39,7 +39,7 @@ export class ItemType implements CacheableObject { uuid: string; /** - * The HALLinks for this ItemType + * The {@link HALLink}s for this ItemType */ @deserialize _links: { diff --git a/src/app/core/shared/item-relationships/relationship-type.model.ts b/src/app/core/shared/item-relationships/relationship-type.model.ts index 437203bd51..fb62f685dd 100644 --- a/src/app/core/shared/item-relationships/relationship-type.model.ts +++ b/src/app/core/shared/item-relationships/relationship-type.model.ts @@ -82,7 +82,7 @@ export class RelationshipType implements CacheableObject { rightMinCardinality: number; /** - * The HALLinks for this RelationshipType + * The {@link HALLink}s for this RelationshipType */ @deserialize _links: { @@ -93,14 +93,14 @@ export class RelationshipType implements CacheableObject { /** * The type of Item found on the left side of this RelationshipType - * Will be undefined unless the leftType HALLink has been resolved. + * Will be undefined unless the leftType {@link HALLink} has been resolved. */ @link(ITEM_TYPE) leftType?: Observable>; /** * The type of Item found on the right side of this RelationshipType - * Will be undefined unless the rightType HALLink has been resolved. + * Will be undefined unless the rightType {@link HALLink} has been resolved. */ @link(ITEM_TYPE) rightType?: Observable>; diff --git a/src/app/core/shared/item-relationships/relationship.model.ts b/src/app/core/shared/item-relationships/relationship.model.ts index 4103208d89..97a5db9e37 100644 --- a/src/app/core/shared/item-relationships/relationship.model.ts +++ b/src/app/core/shared/item-relationships/relationship.model.ts @@ -66,7 +66,7 @@ export class Relationship implements CacheableObject { rightwardValue: string; /** - * The HALLinks for this Relationship + * The {@link HALLink}s for this Relationship */ @deserialize _links: { @@ -78,21 +78,21 @@ export class Relationship implements CacheableObject { /** * The item on the left side of this relationship - * Will be undefined unless the leftItem HALLink has been resolved. + * Will be undefined unless the leftItem {@link HALLink} has been resolved. */ @link(ITEM) leftItem?: Observable>; /** * The item on the right side of this relationship - * Will be undefined unless the rightItem HALLink has been resolved. + * Will be undefined unless the rightItem {@link HALLink} has been resolved. */ @link(ITEM) rightItem?: Observable>; /** * The RelationshipType for this Relationship - * Will be undefined unless the relationshipType HALLink has been resolved. + * Will be undefined unless the relationshipType {@link HALLink} has been resolved. */ @link(RELATIONSHIP_TYPE) relationshipType?: Observable>; diff --git a/src/app/core/shared/item.model.ts b/src/app/core/shared/item.model.ts index 8f5038585d..3fd35280da 100644 --- a/src/app/core/shared/item.model.ts +++ b/src/app/core/shared/item.model.ts @@ -57,7 +57,7 @@ export class Item extends DSpaceObject { isWithdrawn: boolean; /** - * The HALLinks for this Item + * The {@link HALLink}s for this Item */ @deserialize _links: { @@ -71,21 +71,21 @@ export class Item extends DSpaceObject { /** * The owning Collection for this Item - * Will be undefined unless the owningCollection HALLink has been resolved. + * Will be undefined unless the owningCollection {@link HALLink} has been resolved. */ @link(COLLECTION) owningCollection?: Observable>; /** * The list of Bundles inside this Item - * Will be undefined unless the bundles HALLink has been resolved. + * Will be undefined unless the bundles {@link HALLink} has been resolved. */ @link(BUNDLE, true) bundles?: Observable>>; /** * The list of Relationships this Item has with others - * Will be undefined unless the relationships HALLink has been resolved. + * Will be undefined unless the relationships {@link HALLink} has been resolved. */ @link(RELATIONSHIP, true) relationships?: Observable>>; diff --git a/src/app/core/shared/page-info.model.ts b/src/app/core/shared/page-info.model.ts index d05080bfbb..ccb0aae471 100644 --- a/src/app/core/shared/page-info.model.ts +++ b/src/app/core/shared/page-info.model.ts @@ -33,7 +33,7 @@ export class PageInfo implements HALResource { currentPage: number; /** - * The HALLinks for this PageInfo + * The {@link HALLink}s for this PageInfo */ @deserialize _links: { diff --git a/src/app/core/shared/resource-policy.model.ts b/src/app/core/shared/resource-policy.model.ts index 29f901c35b..dd00a16e97 100644 --- a/src/app/core/shared/resource-policy.model.ts +++ b/src/app/core/shared/resource-policy.model.ts @@ -49,7 +49,7 @@ export class ResourcePolicy implements CacheableObject { uuid: string; /** - * The HALLinks for this ResourcePolicy + * The {@link HALLink}s for this ResourcePolicy */ @deserialize _links: { diff --git a/src/app/core/submission/models/submission-object.model.ts b/src/app/core/submission/models/submission-object.model.ts index 3a50484d76..87ea19653d 100644 --- a/src/app/core/submission/models/submission-object.model.ts +++ b/src/app/core/submission/models/submission-object.model.ts @@ -39,7 +39,7 @@ export abstract class SubmissionObject extends DSpaceObject implements Cacheable /** * The collection this submission applies to - * Will be undefined unless the collection HALLink has been resolved. + * Will be undefined unless the collection {@link HALLink} has been resolved. */ @link(COLLECTION) collection?: Observable> | Collection; @@ -57,7 +57,7 @@ export abstract class SubmissionObject extends DSpaceObject implements Cacheable errors: SubmissionObjectError[]; /** - * The HALLinks for this SubmissionObject + * The {@link HALLink}s for this SubmissionObject */ @deserialize _links: { @@ -74,20 +74,20 @@ export abstract class SubmissionObject extends DSpaceObject implements Cacheable /** * The submission item - * Will be undefined unless the item HALLink has been resolved. + * Will be undefined unless the item {@link HALLink} has been resolved. */ @link(ITEM) item?: Observable> | Item; /** * The configuration object that define this submission - * Will be undefined unless the submissionDefinition HALLink has been resolved. + * Will be undefined unless the submissionDefinition {@link HALLink} has been resolved. */ @link(SubmissionDefinitionsModel.type) submissionDefinition?: Observable> | SubmissionDefinitionsModel; /** * The submitter for this SubmissionObject - * Will be undefined unless the submitter HALLink has been resolved. + * Will be undefined unless the submitter {@link HALLink} has been resolved. */ @link(EPERSON) submitter?: Observable> | EPerson; diff --git a/src/app/core/submission/submission-object-data.service.ts b/src/app/core/submission/submission-object-data.service.ts index 0348559eed..0b6d65c758 100644 --- a/src/app/core/submission/submission-object-data.service.ts +++ b/src/app/core/submission/submission-object-data.service.ts @@ -28,7 +28,7 @@ export class SubmissionObjectDataService { * Retrieve a submission object based on its ID. * * @param id The identifier of a submission object - * @param linksToFollow List of {@link FollowLinkConfig} that indicate which HALLinks should be automatically resolved + * @param linksToFollow List of {@link FollowLinkConfig} that indicate which {@link HALLink}s should be automatically resolved */ findById(id: string, ...linksToFollow: Array>): Observable> { switch (this.submissionService.getSubmissionScope()) { diff --git a/src/app/core/submission/submission-response-parsing.service.ts b/src/app/core/submission/submission-response-parsing.service.ts index a37d7c4f49..27a7e43c46 100644 --- a/src/app/core/submission/submission-response-parsing.service.ts +++ b/src/app/core/submission/submission-response-parsing.service.ts @@ -12,8 +12,6 @@ import { BaseResponseParsingService } from '../data/base-response-parsing.servic import { GLOBAL_CONFIG } from '../../../config'; import { GlobalConfig } from '../../../config/global-config.interface'; import { ObjectCacheService } from '../cache/object-cache.service'; -import { Serializer } from '../serializer'; -import { GenericConstructor } from '../shared/generic-constructor'; import { FormFieldMetadataValueObject } from '../../shared/form/builder/models/form-field-metadata-value.model'; import { SubmissionObject } from './models/submission-object.model'; import { WorkflowItem } from './models/workflowitem.model'; @@ -78,6 +76,17 @@ export function normalizeSectionData(obj: any, objIndex?: number) { export class SubmissionResponseParsingService extends BaseResponseParsingService implements ResponseParsingService { protected toCache = false; + + /** + * The submission assumes certain related HALResources will always be embedded. + * It only works if the responseparser finds these embedded resources, and directly + * attaches them to the requested object, instead of putting them in the cache and + * treating them as separate objects. This boolean was added to allow us to disable + * that behavior for the rest of the application, while keeping it for the submission. + * + * It should be removed after the submission has been refactored to treat embeds as + * resources that may need to be retrieved separately. + */ protected shouldDirectlyAttachEmbeds = true; constructor(@Inject(GLOBAL_CONFIG) protected EnvConfig: GlobalConfig, diff --git a/src/app/core/tasks/models/task-object.model.ts b/src/app/core/tasks/models/task-object.model.ts index 2e035f134e..ac659ca9e5 100644 --- a/src/app/core/tasks/models/task-object.model.ts +++ b/src/app/core/tasks/models/task-object.model.ts @@ -40,7 +40,7 @@ export class TaskObject extends DSpaceObject implements CacheableObject { action: string; /** - * The HALLinks for this TaskObject + * The {@link HALLink}s for this TaskObject */ @deserialize _links: { @@ -52,21 +52,21 @@ export class TaskObject extends DSpaceObject implements CacheableObject { /** * The EPerson for this task - * Will be undefined unless the eperson HALLink has been resolved. + * Will be undefined unless the eperson {@link HALLink} has been resolved. */ @link(EPERSON) eperson?: Observable>; /** * The Group for this task - * Will be undefined unless the group HALLink has been resolved. + * Will be undefined unless the group {@link HALLink} has been resolved. */ @link(GROUP) group?: Observable>; /** * The WorkflowItem for this task - * Will be undefined unless the workflowitem HALLink has been resolved. + * Will be undefined unless the workflowitem {@link HALLink} has been resolved. */ @link(WorkflowItem.type) workflowitem?: Observable> | WorkflowItem; diff --git a/src/app/shared/mydspace-actions/workspaceitem/workspaceitem-actions.component.ts b/src/app/shared/mydspace-actions/workspaceitem/workspaceitem-actions.component.ts index 5f2f31c53e..2378c8e251 100644 --- a/src/app/shared/mydspace-actions/workspaceitem/workspaceitem-actions.component.ts +++ b/src/app/shared/mydspace-actions/workspaceitem/workspaceitem-actions.component.ts @@ -54,10 +54,6 @@ export class WorkspaceitemActionsComponent extends MyDSpaceActionsComponent extends ListableObject { hitHighlights: MetadataMap; /** - * The HALLinks for this SearchResult + * The {@link HALLink}s for this SearchResult */ @deserialize _links: { diff --git a/src/app/shared/utils/follow-link-config.model.ts b/src/app/shared/utils/follow-link-config.model.ts index d42ed7bb3f..21df288690 100644 --- a/src/app/shared/utils/follow-link-config.model.ts +++ b/src/app/shared/utils/follow-link-config.model.ts @@ -2,12 +2,12 @@ import { FindListOptions } from '../../core/data/request.models'; import { HALResource } from '../../core/shared/hal-resource.model'; /** - * A class to configure the retrieval of a HALLink + * A class to configure the retrieval of a {@link HALLink} */ export class FollowLinkConfig { /** * The name of the link to fetch. - * Can only be a HALLink of the object you're working with + * Can only be a {@link HALLink} of the object you're working with */ name: keyof R['_links']; @@ -30,7 +30,7 @@ export class FollowLinkConfig { * in order to create them in a less verbose way. * * @param linkName: the name of the link to fetch. - * Can only be a HALLink of the object you're working with + * Can only be a {@link HALLink} of the object you're working with * @param findListOptions: {@link FindListOptions} for the query, * allows you to resolve the link using a certain page, or sorted * in a certain way