mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-13 04:53:06 +00:00
made use of embedded resources for relationships in the response that contain a single link for a set of resources rather than enumerate the self link of each resource
This commit is contained in:
@@ -185,8 +185,13 @@ export class RemoteDataBuildService {
|
||||
rdArr.push(this.buildSingle(href, resourceConstructor));
|
||||
});
|
||||
|
||||
if (rdArr.length === 1) {
|
||||
links[relationship] = rdArr[0];
|
||||
}
|
||||
else {
|
||||
links[relationship] = this.aggregate(rdArr);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// without the setTimeout, the actions inside requestService.configure
|
||||
// are dispatched, but sometimes don't arrive. I'm unsure why atm.
|
||||
|
@@ -48,9 +48,8 @@ export class NormalizedItem extends NormalizedDSpaceObject {
|
||||
/**
|
||||
* The Collection that owns this Item
|
||||
*/
|
||||
@autoserializeAs(String, 'owningCollection')
|
||||
@relationship(ResourceType.Collection, false)
|
||||
owner: string;
|
||||
owningCollection: string;
|
||||
|
||||
@autoserialize
|
||||
@relationship(ResourceType.Bitstream, true)
|
||||
|
@@ -2,10 +2,10 @@ import { Observable } from "rxjs";
|
||||
import { PageInfo } from "../shared/page-info.model";
|
||||
|
||||
export enum RemoteDataState {
|
||||
RequestPending,
|
||||
ResponsePending,
|
||||
Failed,
|
||||
Success
|
||||
RequestPending = <any> "RequestPending",
|
||||
ResponsePending = <any> "ResponsePending",
|
||||
Failed = <any> "Failed",
|
||||
Success = <any> "Success"
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -20,6 +20,7 @@ import { NormalizedObjectFactory } from "../cache/models/normalized-object-facto
|
||||
import { ResourceType } from "../shared/resource-type";
|
||||
import { RequestError } from "./request.models";
|
||||
import { PageInfo } from "../shared/page-info.model";
|
||||
import { NormalizedObject } from "../cache/models/normalized-object.model";
|
||||
|
||||
function isObjectLevel(halObj: any) {
|
||||
return isNotEmpty(halObj._links) && hasValue(halObj._links.self);
|
||||
@@ -29,6 +30,19 @@ function isPaginatedResponse(halObj: any) {
|
||||
return isNotEmpty(halObj.page) && hasValue(halObj._embedded);
|
||||
}
|
||||
|
||||
function flattenSingleKeyObject(obj: any): any {
|
||||
const keys = Object.keys(obj);
|
||||
if (keys.length !== 1) {
|
||||
throw new Error(`Expected an object with a single key, got: ${JSON.stringify(obj)}`);
|
||||
}
|
||||
return obj[keys[0]];
|
||||
}
|
||||
|
||||
class ProcessRequestDTO {
|
||||
[key: string]: NormalizedObject[]
|
||||
}
|
||||
|
||||
|
||||
@Injectable()
|
||||
export class RequestEffects {
|
||||
|
||||
@@ -49,84 +63,89 @@ export class RequestEffects {
|
||||
})
|
||||
.flatMap((entry: RequestEntry) => {
|
||||
return this.restApi.get(entry.request.href)
|
||||
.map((data: DSpaceRESTV2Response) => new SuccessResponse(this.process(data.payload, entry.request.href), data.statusCode, this.processPageInfo(data.payload.page)))
|
||||
.do((response: Response) => this.responseCache.add(entry.request.href, response, this.EnvConfig.cache.msToLive))
|
||||
.map((data: DSpaceRESTV2Response) => {
|
||||
const processRequestDTO = this.process(data.payload, entry.request.href);
|
||||
const uuids = flattenSingleKeyObject(processRequestDTO).map(no => no.uuid);
|
||||
return new SuccessResponse(uuids, data.statusCode, this.processPageInfo(data.payload.page))
|
||||
}).do((response: Response) => this.responseCache.add(entry.request.href, response, this.EnvConfig.cache.msToLive))
|
||||
.map((response: Response) => new RequestCompleteAction(entry.request.href))
|
||||
.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 process(data: any, requestHref: string): Array<string> {
|
||||
protected process(data: any, requestHref: string): ProcessRequestDTO {
|
||||
|
||||
if (isNotEmpty(data)) {
|
||||
if (isPaginatedResponse(data)) {
|
||||
return this.process(data._embedded, requestHref);
|
||||
}
|
||||
else if (isObjectLevel(data)) {
|
||||
return this.deserializeAndCache(data, requestHref);
|
||||
return { "topLevel": this.deserializeAndCache(data, requestHref) };
|
||||
}
|
||||
else {
|
||||
let result = new ProcessRequestDTO();
|
||||
if (Array.isArray(data)) {
|
||||
result['topLevel'] = [];
|
||||
data.forEach(datum => {
|
||||
if (isPaginatedResponse(datum)) {
|
||||
const obj = this.process(datum, requestHref);
|
||||
result['topLevel'] = [...result['topLevel'], ...flattenSingleKeyObject(obj)];
|
||||
}
|
||||
else {
|
||||
result['topLevel'] = [...result['topLevel'], ...this.deserializeAndCache(datum, requestHref)];
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
let uuids = [];
|
||||
Object.keys(data)
|
||||
.filter(property => data.hasOwnProperty(property))
|
||||
.filter(property => hasValue(data[property]))
|
||||
.forEach(property => {
|
||||
let propertyUUIDs;
|
||||
|
||||
if (isPaginatedResponse(data[property])) {
|
||||
propertyUUIDs = this.process(data[property], requestHref);
|
||||
const obj = this.process(data[property], requestHref);
|
||||
result[property] = flattenSingleKeyObject(obj);
|
||||
}
|
||||
else {
|
||||
propertyUUIDs = this.deserializeAndCache(data[property], requestHref);
|
||||
result[property] = this.deserializeAndCache(data[property], requestHref);
|
||||
}
|
||||
|
||||
uuids = [...uuids, ...propertyUUIDs];
|
||||
});
|
||||
return uuids;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected deserializeAndCache(obj, requestHref: string): Array<string> {
|
||||
let type: ResourceType;
|
||||
const isArray = Array.isArray(obj);
|
||||
|
||||
if (isArray && isEmpty(obj)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
if (isArray) {
|
||||
type = obj[0]["type"];
|
||||
}
|
||||
else {
|
||||
type = obj["type"];
|
||||
protected deserializeAndCache(obj, requestHref: string): NormalizedObject[] {
|
||||
if(Array.isArray(obj)) {
|
||||
let result = [];
|
||||
obj.forEach(o => result = [...result, ...this.deserializeAndCache(o, requestHref)])
|
||||
return result;
|
||||
}
|
||||
|
||||
let type: ResourceType = obj["type"];
|
||||
if (hasValue(type)) {
|
||||
const normObjConstructor = NormalizedObjectFactory.getConstructor(type);
|
||||
|
||||
if (hasValue(normObjConstructor)) {
|
||||
const serializer = new DSpaceRESTv2Serializer(normObjConstructor);
|
||||
|
||||
if (isArray) {
|
||||
obj.forEach(o => {
|
||||
if (isNotEmpty(o._embedded)) {
|
||||
this.process(o._embedded, requestHref);
|
||||
}
|
||||
});
|
||||
const normalizedObjArr = serializer.deserializeArray(obj);
|
||||
normalizedObjArr.forEach(t => this.addToObjectCache(t, requestHref));
|
||||
return normalizedObjArr.map(t => t.uuid);
|
||||
}
|
||||
else {
|
||||
let processed;
|
||||
if (isNotEmpty(obj._embedded)) {
|
||||
this.process(obj._embedded, requestHref);
|
||||
processed = this.process(obj._embedded, requestHref);
|
||||
}
|
||||
const normalizedObj = serializer.deserialize(obj);
|
||||
let normalizedObj = serializer.deserialize(obj);
|
||||
|
||||
if (isNotEmpty(processed)) {
|
||||
let linksOnly = {};
|
||||
Object.keys(processed).forEach(key => {
|
||||
linksOnly[key] = processed[key].map((no: NormalizedObject) => no.self);
|
||||
});
|
||||
Object.assign(normalizedObj, linksOnly);
|
||||
}
|
||||
|
||||
this.addToObjectCache(normalizedObj, requestHref);
|
||||
return [normalizedObj.uuid];
|
||||
}
|
||||
return [normalizedObj];
|
||||
|
||||
}
|
||||
else {
|
||||
|
@@ -23,7 +23,7 @@ export class DSpaceRESTv2Service {
|
||||
* @param options
|
||||
* A RequestOptionsArgs object, with options for the http call.
|
||||
* @return {Observable<string>}
|
||||
* An Observablse<string> containing the response from the server
|
||||
* An Observable<string> containing the response from the server
|
||||
*/
|
||||
get(absoluteURL: string, options?: RequestOptionsArgs): Observable<DSpaceRESTV2Response> {
|
||||
return this.http.get(absoluteURL, options)
|
||||
|
@@ -40,7 +40,11 @@ export class Item extends DSpaceObject {
|
||||
/**
|
||||
* The Collection that owns this Item
|
||||
*/
|
||||
owner: RemoteData<Collection>;
|
||||
owningCollection: RemoteData<Collection>;
|
||||
|
||||
get owner(): RemoteData<Collection> {
|
||||
return this.owningCollection;
|
||||
}
|
||||
|
||||
bitstreams: RemoteData<Bitstream[]>;
|
||||
|
||||
|
Reference in New Issue
Block a user