parse page info from rest api and add it to remotedata objects

This commit is contained in:
Art Lowel
2017-06-09 17:43:26 +02:00
parent 2c7f646b71
commit bdf6d006e7
6 changed files with 68 additions and 3 deletions

View File

@@ -26,6 +26,7 @@ export class RemoteDataBuildService {
) { ) {
} }
//TODO refactor, nearly identical to buildList, only payload differs
buildSingle<TNormalized extends CacheableObject, TDomain>( buildSingle<TNormalized extends CacheableObject, TDomain>(
href: string, href: string,
normalizedType: GenericConstructor<TNormalized> normalizedType: GenericConstructor<TNormalized>
@@ -50,6 +51,12 @@ export class RemoteDataBuildService {
.map((entry: ResponseCacheEntry) => entry.response.statusCode) .map((entry: ResponseCacheEntry) => entry.response.statusCode)
.distinctUntilChanged(); .distinctUntilChanged();
const pageInfo = responseCacheObs
.filter((entry: ResponseCacheEntry) => hasValue(entry)
&& hasValue(entry.response) && hasValue(entry.response['pageInfo']))
.map((entry: ResponseCacheEntry) => (<SuccessResponse> entry.response).pageInfo)
.distinctUntilChanged();
const payload = const payload =
Observable.race( Observable.race(
this.objectCache.getBySelfLink<TNormalized>(href, normalizedType), this.objectCache.getBySelfLink<TNormalized>(href, normalizedType),
@@ -76,10 +83,12 @@ export class RemoteDataBuildService {
isSuccessFul, isSuccessFul,
errorMessage, errorMessage,
statusCode, statusCode,
pageInfo,
payload payload
); );
} }
//TODO refactor, nearly identical to buildSingle, only payload differs
buildList<TNormalized extends CacheableObject, TDomain>( buildList<TNormalized extends CacheableObject, TDomain>(
href: string, href: string,
normalizedType: GenericConstructor<TNormalized> normalizedType: GenericConstructor<TNormalized>
@@ -104,6 +113,12 @@ export class RemoteDataBuildService {
.map((entry: ResponseCacheEntry) => entry.response.statusCode) .map((entry: ResponseCacheEntry) => entry.response.statusCode)
.distinctUntilChanged(); .distinctUntilChanged();
const pageInfo = responseCacheObs
.filter((entry: ResponseCacheEntry) => hasValue(entry)
&& hasValue(entry.response) && hasValue(entry.response['pageInfo']))
.map((entry: ResponseCacheEntry) => (<SuccessResponse> entry.response).pageInfo)
.distinctUntilChanged();
const payload = responseCacheObs const payload = responseCacheObs
.filter((entry: ResponseCacheEntry) => hasValue(entry) && entry.response.isSuccessful) .filter((entry: ResponseCacheEntry) => hasValue(entry) && entry.response.isSuccessful)
.map((entry: ResponseCacheEntry) => (<SuccessResponse> entry.response).resourceUUIDs) .map((entry: ResponseCacheEntry) => (<SuccessResponse> entry.response).resourceUUIDs)
@@ -124,6 +139,7 @@ export class RemoteDataBuildService {
isSuccessFul, isSuccessFul,
errorMessage, errorMessage,
statusCode, statusCode,
pageInfo,
payload payload
); );
} }
@@ -210,6 +226,8 @@ export class RemoteDataBuildService {
.join(", ") .join(", ")
); );
const pageInfo = Observable.of(undefined);
const payload = <Observable<T[]>> Observable.combineLatest( const payload = <Observable<T[]>> Observable.combineLatest(
...input.map(rd => rd.payload) ...input.map(rd => rd.payload)
); );
@@ -224,6 +242,7 @@ export class RemoteDataBuildService {
isSuccessFul, isSuccessFul,
errorMessage, errorMessage,
statusCode, statusCode,
pageInfo,
payload payload
); );
} }

View File

@@ -1,4 +1,6 @@
import { RequestError } from "../data/request.models"; import { RequestError } from "../data/request.models";
import { PageInfo } from "../shared/page-info.model";
export class Response { export class Response {
constructor( constructor(
public isSuccessful: boolean, public isSuccessful: boolean,
@@ -9,7 +11,8 @@ export class Response {
export class SuccessResponse extends Response { export class SuccessResponse extends Response {
constructor( constructor(
public resourceUUIDs: Array<String>, public resourceUUIDs: Array<String>,
public statusCode: string public statusCode: string,
public pageInfo?: PageInfo
) { ) {
super(true, statusCode); super(true, statusCode);
} }

View File

@@ -1,4 +1,5 @@
import { Observable } from "rxjs"; import { Observable } from "rxjs";
import { PageInfo } from "../shared/page-info.model";
export enum RemoteDataState { export enum RemoteDataState {
RequestPending, RequestPending,
@@ -18,6 +19,7 @@ export class RemoteData<T> {
private isSuccessFul: Observable<boolean>, private isSuccessFul: Observable<boolean>,
public errorMessage: Observable<string>, public errorMessage: Observable<string>,
public statusCode: Observable<string>, public statusCode: Observable<string>,
public pageInfo: Observable<PageInfo>,
public payload: Observable<T> public payload: Observable<T>
) { ) {
} }

View File

@@ -19,6 +19,7 @@ import { RequestService } from "./request.service";
import { NormalizedObjectFactory } from "../cache/models/normalized-object-factory"; import { NormalizedObjectFactory } from "../cache/models/normalized-object-factory";
import { ResourceType } from "../shared/resource-type"; import { ResourceType } from "../shared/resource-type";
import { RequestError } from "./request.models"; import { RequestError } from "./request.models";
import { PageInfo } from "../shared/page-info.model";
function isObjectLevel(halObj: any) { function isObjectLevel(halObj: any) {
return isNotEmpty(halObj._links) && hasValue(halObj._links.self); return isNotEmpty(halObj._links) && hasValue(halObj._links.self);
@@ -48,7 +49,7 @@ export class RequestEffects {
}) })
.flatMap((entry: RequestEntry) => { .flatMap((entry: RequestEntry) => {
return this.restApi.get(entry.request.href) return this.restApi.get(entry.request.href)
.map((data: DSpaceRESTV2Response) => new SuccessResponse(this.process(data.payload), data.statusCode)) .map((data: DSpaceRESTV2Response) => new SuccessResponse(this.process(data.payload), data.statusCode, this.processPageInfo(data.payload.page)))
.do((response: Response) => this.responseCache.add(entry.request.href, response, this.EnvConfig.cache.msToLive)) .do((response: Response) => this.responseCache.add(entry.request.href, response, this.EnvConfig.cache.msToLive))
.map((response: Response) => new RequestCompleteAction(entry.request.href)) .map((response: Response) => new RequestCompleteAction(entry.request.href))
.catch((error: RequestError) => Observable.of(new ErrorResponse(error)) .catch((error: RequestError) => Observable.of(new ErrorResponse(error))
@@ -60,7 +61,6 @@ export class RequestEffects {
if (isNotEmpty(data)) { if (isNotEmpty(data)) {
if (isPaginatedResponse(data)) { if (isPaginatedResponse(data)) {
//TODO parse page object
return this.process(data._embedded); return this.process(data._embedded);
} }
else if (isObjectLevel(data)) { else if (isObjectLevel(data)) {
@@ -138,4 +138,14 @@ export class RequestEffects {
} }
this.objectCache.add(co, this.EnvConfig.cache.msToLive); this.objectCache.add(co, this.EnvConfig.cache.msToLive);
} }
protected processPageInfo(pageObj: any): PageInfo {
if (isNotEmpty(pageObj)) {
return new DSpaceRESTv2Serializer(PageInfo).deserialize(pageObj);
}
else {
return undefined;
}
}
} }

View File

@@ -2,6 +2,7 @@ export interface DSpaceRESTV2Response {
payload: { payload: {
_embedded?: any; _embedded?: any;
_links?: any; _links?: any;
page?: any;
}, },
statusCode: string statusCode: string
} }

View File

@@ -0,0 +1,30 @@
import { autoserialize, autoserializeAs } from "cerialize";
/**
* Represents the state of a paginated response
*/
export class PageInfo {
/**
* The number of elements on a page
*/
@autoserializeAs(Number, 'size')
elementsPerPage: number;
/**
* The total number of elements in the entire set
*/
@autoserialize
totalElements: number;
/**
* The total number of pages
*/
@autoserialize
totalPages: number;
/**
* The number of the current page, zero-based
*/
@autoserializeAs(Number, 'number')
currentPage: number;
}