diff --git a/src/app/core/cache/object-cache.reducer.ts b/src/app/core/cache/object-cache.reducer.ts index 3af7209b24..39c623deed 100644 --- a/src/app/core/cache/object-cache.reducer.ts +++ b/src/app/core/cache/object-cache.reducer.ts @@ -5,6 +5,12 @@ import { import { hasValue } from '../../shared/empty.util'; import { CacheEntry } from './cache-entry'; +export enum DirtyType { + Created = 'Created', + Updated = 'Updated', + Deleted = 'Deleted' +} + /** * An interface to represent objects that can be cached * @@ -13,6 +19,11 @@ import { CacheEntry } from './cache-entry'; export interface CacheableObject { uuid?: string; self: string; + // isNew: boolean; + // dirtyType: DirtyType; + // hasDirtyAttributes: boolean; + // changedAttributes: AttributeDiffh; + // save(): void; } /** diff --git a/src/app/core/data/data.service.ts b/src/app/core/data/data.service.ts index e2f41f5962..5751173054 100644 --- a/src/app/core/data/data.service.ts +++ b/src/app/core/data/data.service.ts @@ -6,12 +6,19 @@ import { RemoteDataBuildService } from '../cache/builders/remote-data-build.serv import { CacheableObject } from '../cache/object-cache.reducer'; import { ResponseCacheService } from '../cache/response-cache.service'; import { CoreState } from '../core.reducers'; +import { DSpaceObject } from '../shared/dspace-object.model'; import { GenericConstructor } from '../shared/generic-constructor'; import { HALEndpointService } from '../shared/hal-endpoint.service'; -import { RemoteData } from './remote-data'; -import { FindAllOptions, FindAllRequest, FindByIDRequest, RestRequest } from './request.models'; -import { RequestService } from './request.service'; import { URLCombiner } from '../url-combiner/url-combiner'; +import { RemoteData } from './remote-data'; +import { + FindAllOptions, + FindAllRequest, + FindByIDRequest, + RestRequest, + RestRequestMethod +} from './request.models'; +import { RequestService } from './request.service'; export abstract class DataService extends HALEndpointService { protected abstract responseCache: ResponseCacheService; @@ -102,4 +109,20 @@ export abstract class DataService return this.rdbService.buildSingle(href, this.normalizedResourceType); } + create(dso: DSpaceObject): Observable> { + const postHrefObs = this.getEndpoint(); + + // TODO ID is unknown at this point + const idHrefObs = postHrefObs.map((href: string) => this.getFindByIDHref(href, dso.id)); + + postHrefObs + .filter((href: string) => hasValue(href)) + .take(1) + .subscribe((href: string) => { + const request = new RestRequest(href, RestRequestMethod.Post, dso); + this.requestService.configure(request); + }); + + return this.rdbService.buildSingle(idHrefObs, this.normalizedResourceType); + } } diff --git a/src/app/core/data/request.effects.ts b/src/app/core/data/request.effects.ts index 84f19679b1..f848d7f0d7 100644 --- a/src/app/core/data/request.effects.ts +++ b/src/app/core/data/request.effects.ts @@ -1,18 +1,23 @@ import { Inject, Injectable, Injector } from '@angular/core'; +import { Request } from '@angular/http'; +import { RequestArgs } from '@angular/http/src/interfaces'; import { Actions, Effect } from '@ngrx/effects'; // tslint:disable-next-line:import-blacklist import { Observable } from 'rxjs'; import { GLOBAL_CONFIG, GlobalConfig } from '../../../config'; +import { isNotEmpty } from '../../shared/empty.util'; import { ErrorResponse, RestResponse } from '../cache/response-cache.models'; import { ResponseCacheService } from '../cache/response-cache.service'; import { DSpaceRESTV2Response } from '../dspace-rest-v2/dspace-rest-v2-response.model'; import { DSpaceRESTv2Service } from '../dspace-rest-v2/dspace-rest-v2.service'; import { RequestActionTypes, RequestCompleteAction, RequestExecuteAction } from './request.actions'; -import { RequestError } from './request.models'; +import { RequestError, RestRequest } from './request.models'; import { RequestEntry } from './request.reducer'; import { RequestService } from './request.service'; +import { DSpaceRESTv2Serializer } from '../dspace-rest-v2/dspace-rest-v2.serializer'; +import { NormalizedObjectFactory } from '../cache/models/normalized-object-factory'; @Injectable() export class RequestEffects { @@ -23,15 +28,24 @@ export class RequestEffects { return this.requestService.get(action.payload) .take(1); }) - .flatMap((entry: RequestEntry) => { - return this.restApi.get(entry.request.href) + .map((entry: RequestEntry) => entry.request) + .flatMap((request: RestRequest) => { + const httpRequestConfig: RequestArgs = { + method: request.method, + url: request.href + }; + if (isNotEmpty(request.body)) { + const serializer = new DSpaceRESTv2Serializer(NormalizedObjectFactory.getConstructor(request.body.type)); + httpRequestConfig.body = JSON.stringify(serializer.serialize(request.body)); + } + return this.restApi.request(new Request(httpRequestConfig)) .map((data: DSpaceRESTV2Response) => - this.injector.get(entry.request.getResponseParser()).parse(entry.request, data)) - .do((response: RestResponse) => this.responseCache.add(entry.request.href, response, this.EnvConfig.cache.msToLive)) - .map((response: RestResponse) => new RequestCompleteAction(entry.request.href)) + this.injector.get(request.getResponseParser()).parse(request, data)) + .do((response: RestResponse) => this.responseCache.add(request.href, response, this.EnvConfig.cache.msToLive)) + .map((response: RestResponse) => new RequestCompleteAction(request.href)) .catch((error: RequestError) => Observable.of(new ErrorResponse(error)) - .do((response: RestResponse) => this.responseCache.add(entry.request.href, response, this.EnvConfig.cache.msToLive)) - .map((response: RestResponse) => new RequestCompleteAction(entry.request.href))); + .do((response: RestResponse) => this.responseCache.add(request.href, response, this.EnvConfig.cache.msToLive)) + .map((response: RestResponse) => new RequestCompleteAction(request.href))); }); constructor( diff --git a/src/app/core/data/request.models.ts b/src/app/core/data/request.models.ts index a80eccfaa8..3ab7dc0b8c 100644 --- a/src/app/core/data/request.models.ts +++ b/src/app/core/data/request.models.ts @@ -9,9 +9,21 @@ import { BrowseResponseParsingService } from './browse-response-parsing.service' import { ConfigResponseParsingService } from './config-response-parsing.service'; /* tslint:disable:max-classes-per-file */ +export enum RestRequestMethod { + Get = 'GET', + Post = 'POST', + Put = 'PUT', + Delete = 'DELETE', + Options = 'OPTIONS', + Head = 'HEAD', + Patch = 'PATCH' +} + export class RestRequest { constructor( public href: string, + public method: RestRequestMethod = RestRequestMethod.Get, + public body?: any ) { } getResponseParser(): GenericConstructor { 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 6464268201..bc9d5eddaf 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 @@ -1,11 +1,12 @@ import { Inject, Injectable } from '@angular/core'; -import { Http, RequestOptionsArgs } from '@angular/http'; +import { Http, RequestOptionsArgs, Request } from '@angular/http'; import { Observable } from 'rxjs/Observable'; import { RESTURLCombiner } from '../url-combiner/rest-url-combiner'; import { DSpaceRESTV2Response } from './dspace-rest-v2-response.model'; import { GLOBAL_CONFIG, GlobalConfig } from '../../../config'; +import { RestRequest } from '../data/request.models'; /** * Service to access DSpace's REST API @@ -36,4 +37,26 @@ export class DSpaceRESTv2Service { }); } + /** + * Performs a request to the REST API. + * + * @param httpRequest + * A Request object + * @return {Observable} + * An Observable containing the response from the server + */ + request(httpRequest: Request): Observable { + // const httpRequest = new Request({ + // method: request.method, + // url: request.href, + // body: request.body + // }); + return this.http.request(httpRequest) + .map((res) => ({ payload: res.json(), statusCode: res.statusText })) + .catch((err) => { + console.log('Error: ', err); + return Observable.throw(err); + }); + } + }