From 0677bc38eeb70a0d75ed011937deb42cecb64ba7 Mon Sep 17 00:00:00 2001 From: Art Lowel Date: Wed, 7 Jun 2017 18:25:52 +0200 Subject: [PATCH] switch to live rest-backend, still issue with bitstreams on item page --- config/environment.default.js | 6 +- .../builders/remote-data-build.service.ts | 25 +++++ .../models/normalized-bitstream.model.ts | 77 ++++++++------- .../models/normalized-collection.model.ts | 8 +- .../models/normalized-community.model.ts | 4 + .../models/normalized-dspace-object.model.ts | 5 +- .../cache/models/normalized-item.model.ts | 17 +++- src/app/core/cache/response-cache.models.ts | 17 +++- src/app/core/data/collection-data.service.ts | 2 +- src/app/core/data/community-data.service.ts | 2 +- src/app/core/data/item-data.service.ts | 2 +- src/app/core/data/remote-data.ts | 1 + src/app/core/data/request.effects.ts | 39 ++++---- src/app/core/data/request.models.ts | 4 + .../dspace-rest-v2-response.model.ts | 7 +- .../dspace-rest-v2.serializer.ts | 12 +-- .../dspace-rest-v2/dspace-rest-v2.service.ts | 5 +- src/app/core/shared/bitstream.model.ts | 63 +++++++------ src/app/core/shared/bundle.model.ts | 2 +- src/app/core/shared/collection.model.ts | 2 +- src/app/core/shared/community.model.ts | 2 +- src/app/core/shared/dspace-object.model.ts | 2 +- src/app/core/shared/item.model.ts | 93 +++++++++---------- .../collections/collections.component.ts | 11 ++- .../full-file-section.component.ts | 4 +- .../file-section/file-section.component.html | 2 +- 26 files changed, 247 insertions(+), 167 deletions(-) diff --git a/config/environment.default.js b/config/environment.default.js index cddd204eea..b3f0756378 100644 --- a/config/environment.default.js +++ b/config/environment.default.js @@ -2,10 +2,10 @@ module.exports = { // The REST API server settings. "rest": { "ssl": false, - "address": "localhost", - "port": 3000, + "address": "dspace7.4science.it", + "port": 80, // NOTE: Space is capitalized because 'namespace' is a reserved string in TypeScript - "nameSpace": "/api" + "nameSpace": "/dspace-spring-rest/api" }, // Angular2 UI server settings. "ui": { 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 2096d47459..f197773387 100644 --- a/src/app/core/cache/builders/remote-data-build.service.ts +++ b/src/app/core/cache/builders/remote-data-build.service.ts @@ -45,6 +45,11 @@ export class RemoteDataBuildService { .map((entry: ResponseCacheEntry) => ( entry.response).errorMessage) .distinctUntilChanged(); + const statusCode = responseCacheObs + .filter((entry: ResponseCacheEntry) => hasValue(entry)) + .map((entry: ResponseCacheEntry) => entry.response.statusCode) + .distinctUntilChanged(); + const payload = Observable.race( this.objectCache.getBySelfLink(href, normalizedType), @@ -70,6 +75,7 @@ export class RemoteDataBuildService { responsePending, isSuccessFul, errorMessage, + statusCode, payload ); } @@ -93,6 +99,11 @@ export class RemoteDataBuildService { .map((entry: ResponseCacheEntry) => ( entry.response).errorMessage) .distinctUntilChanged(); + const statusCode = responseCacheObs + .filter((entry: ResponseCacheEntry) => hasValue(entry)) + .map((entry: ResponseCacheEntry) => entry.response.statusCode) + .distinctUntilChanged(); + const payload = responseCacheObs .filter((entry: ResponseCacheEntry) => hasValue(entry) && entry.response.isSuccessful) .map((entry: ResponseCacheEntry) => ( entry.response).resourceUUIDs) @@ -112,6 +123,7 @@ export class RemoteDataBuildService { responsePending, isSuccessFul, errorMessage, + statusCode, payload ); } @@ -186,6 +198,18 @@ export class RemoteDataBuildService { .join(", ") ); + const statusCode = Observable.combineLatest( + ...input.map(rd => rd.statusCode), + ).map((...statusCodes) => statusCodes + .map((code, idx) => { + if (hasValue(code)) { + return `[${idx}]: ${code}`; + } + }) + .filter(c => hasValue(c)) + .join(", ") + ); + const payload = > Observable.combineLatest( ...input.map(rd => rd.payload) ); @@ -199,6 +223,7 @@ export class RemoteDataBuildService { responsePending, isSuccessFul, errorMessage, + statusCode, payload ); } diff --git a/src/app/core/cache/models/normalized-bitstream.model.ts b/src/app/core/cache/models/normalized-bitstream.model.ts index b6df211c2e..e90a5b1a5f 100644 --- a/src/app/core/cache/models/normalized-bitstream.model.ts +++ b/src/app/core/cache/models/normalized-bitstream.model.ts @@ -1,49 +1,60 @@ import { inheritSerialization, autoserialize } from "cerialize"; import { NormalizedDSpaceObject } from "./normalized-dspace-object.model"; import { Bitstream } from "../../shared/bitstream.model"; -import { mapsTo } from "../builders/build-decorators"; +import { mapsTo, relationship } from "../builders/build-decorators"; +import { ResourceType } from "../../shared/resource-type"; @mapsTo(Bitstream) @inheritSerialization(NormalizedDSpaceObject) export class NormalizedBitstream extends NormalizedDSpaceObject { - /** - * The size of this bitstream in bytes(?) - */ - @autoserialize - size: number; + /** + * The size of this bitstream in bytes(?) + */ + @autoserialize + size: number; - /** - * The relative path to this Bitstream's file - */ - url: string; + /** + * The relative path to this Bitstream's file + */ + @autoserialize + url: string; - /** - * The mime type of this Bitstream - */ - @autoserialize - mimetype: string; + /** + * The mime type of this Bitstream + */ + @autoserialize + mimetype: string; - /** - * The format of this Bitstream - */ - format: string; + /** + * The format of this Bitstream + */ + @autoserialize + format: string; - /** - * The description of this Bitstream - */ - description: string; + /** + * The description of this Bitstream + */ + @autoserialize + description: string; - /** - * An array of Bundles that are direct parents of this Bitstream - */ - parents: Array; + /** + * An array of Bundles that are direct parents of this Bitstream + */ + @autoserialize + @relationship(ResourceType.Item) + parents: Array; - /** - * The Bundle that owns this Bitstream - */ - owner: string; + /** + * The Bundle that owns this Bitstream + */ + @autoserialize + @relationship(ResourceType.Item) + owner: string; - @autoserialize - retrieve: string; + /** + * The name of the Bundle this Bitstream is part of + */ + @autoserialize + bundleName: string; } diff --git a/src/app/core/cache/models/normalized-collection.model.ts b/src/app/core/cache/models/normalized-collection.model.ts index e0f96ff805..fe5fbbca15 100644 --- a/src/app/core/cache/models/normalized-collection.model.ts +++ b/src/app/core/cache/models/normalized-collection.model.ts @@ -20,13 +20,17 @@ export class NormalizedCollection extends NormalizedDSpaceObject { logo: string; /** - * An array of Collections that are direct parents of this Collection + * An array of Communities that are direct parents of this Collection */ + @autoserialize + @relationship(ResourceType.Community) parents: Array; /** - * The Collection that owns this Collection + * The Community that owns this Collection */ + @autoserialize + @relationship(ResourceType.Community) owner: string; @autoserialize diff --git a/src/app/core/cache/models/normalized-community.model.ts b/src/app/core/cache/models/normalized-community.model.ts index f6c971b460..07583e0ef3 100644 --- a/src/app/core/cache/models/normalized-community.model.ts +++ b/src/app/core/cache/models/normalized-community.model.ts @@ -22,11 +22,15 @@ export class NormalizedCommunity extends NormalizedDSpaceObject { /** * An array of Communities that are direct parents of this Community */ + @autoserialize + @relationship(ResourceType.Community) parents: Array; /** * The Community that owns this Community */ + @autoserialize + @relationship(ResourceType.Community) owner: string; @autoserialize diff --git a/src/app/core/cache/models/normalized-dspace-object.model.ts b/src/app/core/cache/models/normalized-dspace-object.model.ts index f4b879c01a..e3712b0c2a 100644 --- a/src/app/core/cache/models/normalized-dspace-object.model.ts +++ b/src/app/core/cache/models/normalized-dspace-object.model.ts @@ -13,8 +13,11 @@ export abstract class NormalizedDSpaceObject implements CacheableObject { /** * 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 */ - @autoserialize + @autoserializeAs(String, 'uuid') id: string; /** diff --git a/src/app/core/cache/models/normalized-item.model.ts b/src/app/core/cache/models/normalized-item.model.ts index 15b4822cdf..03cde47bda 100644 --- a/src/app/core/cache/models/normalized-item.model.ts +++ b/src/app/core/cache/models/normalized-item.model.ts @@ -1,4 +1,4 @@ -import { inheritSerialization, autoserialize } from "cerialize"; +import { inheritSerialization, autoserialize, autoserializeAs } from "cerialize"; import { NormalizedDSpaceObject } from "./normalized-dspace-object.model"; import { Item } from "../../shared/item.model"; import { mapsTo, relationship } from "../builders/build-decorators"; @@ -17,16 +17,25 @@ export class NormalizedItem extends NormalizedDSpaceObject { /** * The Date of the last modification of this Item */ + @autoserialize lastModified: Date; /** * A boolean representing if this Item is currently archived or not */ + @autoserializeAs(Boolean, 'inArchive') isArchived: boolean; + /** + * A boolean representing if this Item is currently discoverable or not + */ + @autoserializeAs(Boolean, 'discoverable') + isDiscoverable: boolean; + /** * A boolean representing if this Item is currently withdrawn or not */ + @autoserializeAs(Boolean, 'withdrawn') isWithdrawn: boolean; /** @@ -39,9 +48,11 @@ export class NormalizedItem extends NormalizedDSpaceObject { /** * The Collection that owns this Item */ + @autoserializeAs(String, 'owningCollection') + @relationship(ResourceType.Collection) owner: string; @autoserialize - @relationship(ResourceType.Bundle) - bundles: Array; + @relationship(ResourceType.Bitstream) + bitstreams: Array; } diff --git a/src/app/core/cache/response-cache.models.ts b/src/app/core/cache/response-cache.models.ts index 4208b4cada..3f2b906bc9 100644 --- a/src/app/core/cache/response-cache.models.ts +++ b/src/app/core/cache/response-cache.models.ts @@ -1,18 +1,25 @@ +import { RequestError } from "../data/request.models"; export class Response { - constructor(public isSuccessful: boolean) {} + constructor( + public isSuccessful: boolean, + public statusCode: string + ) {} } export class SuccessResponse extends Response { - constructor(public resourceUUIDs: Array) { - super(true); + constructor( + public resourceUUIDs: Array, + public statusCode: string + ) { + super(true, statusCode); } } export class ErrorResponse extends Response { errorMessage: string; - constructor(error: Error) { - super(false); + constructor(error: RequestError) { + super(false, error.statusText); console.error(error); this.errorMessage = error.message; } diff --git a/src/app/core/data/collection-data.service.ts b/src/app/core/data/collection-data.service.ts index 232345d2be..cf396ec118 100644 --- a/src/app/core/data/collection-data.service.ts +++ b/src/app/core/data/collection-data.service.ts @@ -11,7 +11,7 @@ import { RemoteDataBuildService } from "../cache/builders/remote-data-build.serv @Injectable() export class CollectionDataService extends DataService { - protected endpoint = '/collections'; + protected endpoint = '/core/collections'; constructor( protected objectCache: ObjectCacheService, diff --git a/src/app/core/data/community-data.service.ts b/src/app/core/data/community-data.service.ts index 6e63597407..3da43f09ea 100644 --- a/src/app/core/data/community-data.service.ts +++ b/src/app/core/data/community-data.service.ts @@ -11,7 +11,7 @@ import { RemoteDataBuildService } from "../cache/builders/remote-data-build.serv @Injectable() export class CommunityDataService extends DataService { - protected endpoint = '/communities'; + protected endpoint = '/core/communities'; constructor( protected objectCache: ObjectCacheService, diff --git a/src/app/core/data/item-data.service.ts b/src/app/core/data/item-data.service.ts index fc13999f37..a1a0109ed3 100644 --- a/src/app/core/data/item-data.service.ts +++ b/src/app/core/data/item-data.service.ts @@ -11,7 +11,7 @@ import { RemoteDataBuildService } from "../cache/builders/remote-data-build.serv @Injectable() export class ItemDataService extends DataService { - protected endpoint = '/items'; + protected endpoint = '/core/items'; constructor( protected objectCache: ObjectCacheService, diff --git a/src/app/core/data/remote-data.ts b/src/app/core/data/remote-data.ts index 7fa02bf25c..557d9eddb3 100644 --- a/src/app/core/data/remote-data.ts +++ b/src/app/core/data/remote-data.ts @@ -17,6 +17,7 @@ export class RemoteData { private responsePending: Observable, private isSuccessFul: Observable, public errorMessage: Observable, + public statusCode: Observable, public payload: Observable ) { } diff --git a/src/app/core/data/request.effects.ts b/src/app/core/data/request.effects.ts index 64e7aec1fd..1258003e60 100644 --- a/src/app/core/data/request.effects.ts +++ b/src/app/core/data/request.effects.ts @@ -1,6 +1,5 @@ import { Injectable, Inject } from "@angular/core"; import { Actions, Effect } from "@ngrx/effects"; -import { Store } from "@ngrx/store"; import { DSpaceRESTv2Service } from "../dspace-rest-v2/dspace-rest-v2.service"; import { ObjectCacheService } from "../cache/object-cache.service"; import { DSpaceRESTV2Response } from "../dspace-rest-v2/dspace-rest-v2-response.model"; @@ -10,7 +9,7 @@ import { Observable } from "rxjs"; import { Response, SuccessResponse, ErrorResponse } from "../cache/response-cache.models"; import { hasNoValue, hasValue, isEmpty, isNotEmpty } from "../../shared/empty.util"; import { GlobalConfig, GLOBAL_CONFIG } from "../../../config"; -import { RequestState, RequestEntry } from "./request.reducer"; +import { RequestEntry } from "./request.reducer"; import { RequestActionTypes, RequestExecuteAction, RequestCompleteAction @@ -19,11 +18,16 @@ import { ResponseCacheService } from "../cache/response-cache.service"; import { RequestService } from "./request.service"; import { NormalizedObjectFactory } from "../cache/models/normalized-object-factory"; import { ResourceType } from "../shared/resource-type"; +import { RequestError } from "./request.models"; function isObjectLevel(halObj: any) { return isNotEmpty(halObj._links) && hasValue(halObj._links.self); } +function isPaginatedResponse(halObj: any) { + return isNotEmpty(halObj.page) && hasValue(halObj._embedded); +} + @Injectable() export class RequestEffects { @@ -33,8 +37,7 @@ export class RequestEffects { private restApi: DSpaceRESTv2Service, private objectCache: ObjectCacheService, private responseCache: ResponseCacheService, - protected requestService: RequestService, - private store: Store + protected requestService: RequestService ) { } @Effect() execute = this.actions$ @@ -45,27 +48,31 @@ export class RequestEffects { }) .flatMap((entry: RequestEntry) => { return this.restApi.get(entry.request.href) - .map((data: DSpaceRESTV2Response) => this.processEmbedded(data._embedded)) - .map((ids: Array) => new SuccessResponse(ids)) + .map((data: DSpaceRESTV2Response) => new SuccessResponse(this.process(data.payload), data.statusCode)) .do((response: Response) => this.responseCache.add(entry.request.href, response, this.EnvConfig.cache.msToLive)) .map((response: Response) => new RequestCompleteAction(entry.request.href)) - .catch((error: Error) => Observable.of(new ErrorResponse(error)) + .catch((error: RequestError) => Observable.of(new ErrorResponse(error)) .do((response: Response) => this.responseCache.add(entry.request.href, response, this.EnvConfig.cache.msToLive)) .map((response: Response) => new RequestCompleteAction(entry.request.href))); }); - protected processEmbedded(_embedded: any): Array { + protected process(data: any): Array { - if (isNotEmpty(_embedded)) { - if (isObjectLevel(_embedded)) { - return this.deserializeAndCache(_embedded); + if (isNotEmpty(data)) { + if (isPaginatedResponse(data)) { + //TODO parse page object + return this.process(data._embedded); + } + else if (isObjectLevel(data)) { + return this.deserializeAndCache(data); } else { let uuids = []; - Object.keys(_embedded) - .filter(property => _embedded.hasOwnProperty(property)) + Object.keys(data) + .filter(property => data.hasOwnProperty(property)) + .filter(property => hasValue(data[property])) .forEach(property => { - uuids = [...uuids, ...this.deserializeAndCache(_embedded[property])]; + uuids = [...uuids, ...this.deserializeAndCache(data[property])]; }); return uuids; } @@ -96,7 +103,7 @@ export class RequestEffects { if (isArray) { obj.forEach(o => { if (isNotEmpty(o._embedded)) { - this.processEmbedded(o._embedded); + this.process(o._embedded); } }); const normalizedObjArr = serializer.deserializeArray(obj); @@ -105,7 +112,7 @@ export class RequestEffects { } else { if (isNotEmpty(obj._embedded)) { - this.processEmbedded(obj._embedded); + this.process(obj._embedded); } const normalizedObj = serializer.deserialize(obj); this.addToObjectCache(normalizedObj); diff --git a/src/app/core/data/request.models.ts b/src/app/core/data/request.models.ts index eb74f4b35d..b7a302cc0f 100644 --- a/src/app/core/data/request.models.ts +++ b/src/app/core/data/request.models.ts @@ -27,3 +27,7 @@ export class FindAllRequest extends Request { super(href); } } + +export class RequestError extends Error { + statusText: string; +} diff --git a/src/app/core/dspace-rest-v2/dspace-rest-v2-response.model.ts b/src/app/core/dspace-rest-v2/dspace-rest-v2-response.model.ts index 80567bdf7c..cf0b2dc06b 100644 --- a/src/app/core/dspace-rest-v2/dspace-rest-v2-response.model.ts +++ b/src/app/core/dspace-rest-v2/dspace-rest-v2-response.model.ts @@ -1,4 +1,7 @@ export interface DSpaceRESTV2Response { - _embedded?: any; - _links?: any; + payload: { + _embedded?: any; + _links?: any; + }, + statusCode: string } diff --git a/src/app/core/dspace-rest-v2/dspace-rest-v2.serializer.ts b/src/app/core/dspace-rest-v2/dspace-rest-v2.serializer.ts index b9f1a0be14..0cd1f9edad 100644 --- a/src/app/core/dspace-rest-v2/dspace-rest-v2.serializer.ts +++ b/src/app/core/dspace-rest-v2/dspace-rest-v2.serializer.ts @@ -26,10 +26,8 @@ export class DSpaceRESTv2Serializer implements Serializer { * @param model The model to serialize * @returns An object to send to the backend */ - serialize(model: T): DSpaceRESTV2Response { - return { - "_embedded": Serialize(model, this.modelType) - }; + serialize(model: T): any { + return Serialize(model, this.modelType); } /** @@ -38,10 +36,8 @@ export class DSpaceRESTv2Serializer implements Serializer { * @param models The array of models to serialize * @returns An object to send to the backend */ - serializeArray(models: Array): DSpaceRESTV2Response { - return { - "_embedded": Serialize(models, this.modelType) - }; + serializeArray(models: Array): any { + return Serialize(models, this.modelType); } /** diff --git a/src/app/core/dspace-rest-v2/dspace-rest-v2.service.ts b/src/app/core/dspace-rest-v2/dspace-rest-v2.service.ts index d8a21c6c9d..1920c0a994 100644 --- a/src/app/core/dspace-rest-v2/dspace-rest-v2.service.ts +++ b/src/app/core/dspace-rest-v2/dspace-rest-v2.service.ts @@ -4,6 +4,7 @@ import { Observable } from 'rxjs/Observable'; import { RESTURLCombiner } from "../url-combiner/rest-url-combiner"; import { GLOBAL_CONFIG, GlobalConfig } from '../../../config'; +import { DSpaceRESTV2Response } from "./dspace-rest-v2-response.model"; /** * Service to access DSpace's REST API @@ -24,9 +25,9 @@ export class DSpaceRESTv2Service { * @return {Observable} * An Observablse containing the response from the server */ - get(relativeURL: string, options?: RequestOptionsArgs): Observable { + get(relativeURL: string, options?: RequestOptionsArgs): Observable { return this.http.get(new RESTURLCombiner(this.EnvConfig, relativeURL).toString(), options) - .map(res => res.json()) + .map(res => ({ payload: res.json(), statusCode: res.statusText })) .catch(err => { console.log('Error: ', err); return Observable.throw(err); diff --git a/src/app/core/shared/bitstream.model.ts b/src/app/core/shared/bitstream.model.ts index 06bdf41f30..3dd134478f 100644 --- a/src/app/core/shared/bitstream.model.ts +++ b/src/app/core/shared/bitstream.model.ts @@ -1,42 +1,47 @@ import { DSpaceObject } from "./dspace-object.model"; -import { Bundle } from "./bundle.model"; import { RemoteData } from "../data/remote-data"; +import { Item } from "./item.model"; export class Bitstream extends DSpaceObject { - /** - * The size of this bitstream in bytes(?) - */ - size: number; + /** + * The size of this bitstream in bytes(?) + */ + size: number; - /** - * The relative path to this Bitstream's file - */ - url: string; + /** + * The relative path to this Bitstream's file + */ + url: string; - /** - * The mime type of this Bitstream - */ - mimetype: string; + /** + * The mime type of this Bitstream + */ + mimetype: string; - /** - * The description of this Bitstream - */ - description: string; + /** + * The description of this Bitstream + */ + description: string; - /** - * An array of Bundles that are direct parents of this Bitstream - */ - parents: RemoteData; + /** + * The name of the Bundle this Bitstream is part of + */ + bundleName: string; - /** - * The Bundle that owns this Bitstream - */ - owner: Bundle; + /** + * An array of Items that are direct parents of this Bitstream + */ + parents: RemoteData; - /** - * The Bundle that owns this Bitstream - */ - retrieve: string; + /** + * The Bundle that owns this Bitstream + */ + owner: RemoteData; + + /** + * The Bundle that owns this Bitstream + */ + retrieve: string; } diff --git a/src/app/core/shared/bundle.model.ts b/src/app/core/shared/bundle.model.ts index 8f3a284fb6..9d8e3855b8 100644 --- a/src/app/core/shared/bundle.model.ts +++ b/src/app/core/shared/bundle.model.ts @@ -17,7 +17,7 @@ export class Bundle extends DSpaceObject { /** * The Item that owns this Bundle */ - owner: Item; + owner: RemoteData; bitstreams: RemoteData diff --git a/src/app/core/shared/collection.model.ts b/src/app/core/shared/collection.model.ts index 30814726b8..43d5ff523c 100644 --- a/src/app/core/shared/collection.model.ts +++ b/src/app/core/shared/collection.model.ts @@ -63,7 +63,7 @@ export class Collection extends DSpaceObject { /** * The Collection that owns this Collection */ - owner: Collection; + owner: RemoteData; items: RemoteData; diff --git a/src/app/core/shared/community.model.ts b/src/app/core/shared/community.model.ts index 67c8211fd2..bd82c2e05f 100644 --- a/src/app/core/shared/community.model.ts +++ b/src/app/core/shared/community.model.ts @@ -55,7 +55,7 @@ export class Community extends DSpaceObject { /** * The Community that owns this Community */ - owner: Community; + owner: RemoteData; collections: RemoteData; diff --git a/src/app/core/shared/dspace-object.model.ts b/src/app/core/shared/dspace-object.model.ts index ca7c67207a..d3c698ac2f 100644 --- a/src/app/core/shared/dspace-object.model.ts +++ b/src/app/core/shared/dspace-object.model.ts @@ -44,7 +44,7 @@ export abstract class DSpaceObject implements CacheableObject { /** * The DSpaceObject that owns this DSpaceObject */ - owner: DSpaceObject; + owner: RemoteData; /** * Find a metadata field by key and language diff --git a/src/app/core/shared/item.model.ts b/src/app/core/shared/item.model.ts index a3e098eed9..cb488ab0a8 100644 --- a/src/app/core/shared/item.model.ts +++ b/src/app/core/shared/item.model.ts @@ -1,10 +1,9 @@ import { DSpaceObject } from "./dspace-object.model"; import { Collection } from "./collection.model"; import { RemoteData } from "../data/remote-data"; -import { Bundle } from "./bundle.model"; import { Bitstream } from "./bitstream.model"; import { Observable } from "rxjs"; -import { hasValue } from "../../shared/empty.util"; +import { isNotEmpty } from "../../shared/empty.util"; export class Item extends DSpaceObject { @@ -23,6 +22,11 @@ export class Item extends DSpaceObject { */ isArchived: boolean; + /** + * A boolean representing if this Item is currently discoverable or not + */ + isDiscoverable: boolean; + /** * A boolean representing if this Item is currently withdrawn or not */ @@ -36,9 +40,9 @@ export class Item extends DSpaceObject { /** * The Collection that owns this Item */ - owner: Collection; + owner: RemoteData; - bundles: RemoteData; + bitstreams: RemoteData; /** @@ -46,57 +50,44 @@ export class Item extends DSpaceObject { * @returns {Observable} the primaryBitstream of the "THUMBNAIL" bundle */ getThumbnail(): Observable { - const bundle: Observable = this.getBundle("THUMBNAIL"); - return bundle - .filter(bundle => hasValue(bundle)) - .flatMap(bundle => bundle.primaryBitstream.payload) - .startWith(undefined); + //TODO currently this just picks the first thumbnail + //should be adjusted when we have a way to determine + //the primary thumbnail from rest + return this.getBitstreamsByBundleName("THUMBNAIL") + .filter(thumbnails => isNotEmpty(thumbnails)) + .map(thumbnails => thumbnails[0]) } - /** - * Retrieves the thumbnail for the given original of this item - * @returns {Observable} the primaryBitstream of the "THUMBNAIL" bundle - */ - getThumbnailForOriginal(original: Bitstream): Observable { - const bundle: Observable = this.getBundle("THUMBNAIL"); - return bundle - .filter(bundle => hasValue(bundle)) - .flatMap(bundle => bundle - .bitstreams.payload.map(files => files - .find(thumbnail => thumbnail - .name.startsWith(original.name) - ) - ) - ) - .startWith(undefined);; + /** + * Retrieves the thumbnail for the given original of this item + * @returns {Observable} the primaryBitstream of the "THUMBNAIL" bundle + */ + getThumbnailForOriginal(original: Bitstream): Observable { + return this.getBitstreamsByBundleName("THUMBNAIL").map(files => files + .find(thumbnail => thumbnail + .name.startsWith(original.name) + ) + ).startWith(undefined); + } + + /** + * Retrieves all files that should be displayed on the item page of this item + * @returns {Observable>>} an array of all Bitstreams in the "ORIGINAL" bundle + */ + getFiles(): Observable { + return this.getBitstreamsByBundleName("ORIGINAL"); } - /** - * Retrieves all files that should be displayed on the item page of this item - * @returns {Observable>>} an array of all Bitstreams in the "ORIGINAL" bundle - */ - getFiles(name: String = "ORIGINAL"): Observable { - const bundle: Observable = this.getBundle(name); - return bundle - .filter(bundle => hasValue(bundle)) - .flatMap(bundle => bundle.bitstreams.payload) - .startWith([]); - } - - /** - * Retrieves the bundle of this item by its name - * @param name The name of the Bundle that should be returned - * @returns {Observable} the Bundle that belongs to this item with the given name - */ - getBundle(name: String): Observable { - return this.bundles.payload - .filter(bundles => hasValue(bundles)) - .map(bundles => { - return bundles.find((bundle: Bundle) => { - return bundle.name === name - }); - }) - .startWith(undefined); + /** + * Retrieves bitstreams by bundle name + * @param bundleName The name of the Bundle that should be returned + * @returns {Observable} the bitstreams with the given bundleName + */ + getBitstreamsByBundleName(bundleName: string): Observable { + return this.bitstreams.payload.startWith([]) + .map(bitstreams => bitstreams + .filter(bitstream => bitstream.bundleName === bundleName) + ); } } diff --git a/src/app/item-page/field-components/collections/collections.component.ts b/src/app/item-page/field-components/collections/collections.component.ts index 199fb2b773..0ff774b1ea 100644 --- a/src/app/item-page/field-components/collections/collections.component.ts +++ b/src/app/item-page/field-components/collections/collections.component.ts @@ -2,6 +2,7 @@ import { Component, Input, OnInit } from '@angular/core'; import { Collection } from "../../../core/shared/collection.model"; import { Observable } from "rxjs"; import { Item } from "../../../core/shared/item.model"; +import { RemoteDataBuildService } from "../../../core/cache/builders/remote-data-build.service"; /** * This component renders the parent collections section of the item @@ -22,7 +23,9 @@ export class CollectionsComponent implements OnInit { collections: Observable; - constructor() { + constructor( + private rdbs: RemoteDataBuildService + ) { this.universalInit(); } @@ -31,7 +34,11 @@ export class CollectionsComponent implements OnInit { } ngOnInit(): void { - this.collections = this.item.parents.payload; + // this.collections = this.item.parents.payload; + //TODO this should use parents, but the collections + // for an Item aren't returned by the REST API yet, + // only the owning collection + this.collections = this.rdbs.aggregate([this.item.owner]).payload } diff --git a/src/app/item-page/full/field-components/file-section/full-file-section.component.ts b/src/app/item-page/full/field-components/file-section/full-file-section.component.ts index 3723bc5450..17208e8b20 100644 --- a/src/app/item-page/full/field-components/file-section/full-file-section.component.ts +++ b/src/app/item-page/full/field-components/file-section/full-file-section.component.ts @@ -35,8 +35,8 @@ export class FullFileSectionComponent extends FileSectionComponent implements On } initialize(): void { - const originals = this.item.getFiles("ORIGINAL"); - const licenses = this.item.getFiles("LICENSE"); + const originals = this.item.getFiles(); + const licenses = this.item.getBitstreamsByBundleName("LICENSE"); this.files = Observable.combineLatest(originals, licenses, (originals, licenses) => [...originals, ...licenses]); this.files.subscribe( files => diff --git a/src/app/item-page/simple/field-components/file-section/file-section.component.html b/src/app/item-page/simple/field-components/file-section/file-section.component.html index 149a1b2017..1eba7d9f7f 100644 --- a/src/app/item-page/simple/field-components/file-section/file-section.component.html +++ b/src/app/item-page/simple/field-components/file-section/file-section.component.html @@ -1,6 +1,6 @@