mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-15 14:03:06 +00:00
93803: Make data services composable
Data services should extend BaseDataService (or IdentifiableDataService) for low-level functionality and optionally wrap "data service feature" classes for - create - findAll - patch / update - put - delete
This commit is contained in:
107
src/app/core/data/base/create-data.ts
Normal file
107
src/app/core/data/base/create-data.ts
Normal file
@@ -0,0 +1,107 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
import { CacheableObject } from '../../cache/cacheable-object.model';
|
||||
import { BaseDataService } from './base-data.service';
|
||||
import { RequestParam } from '../../cache/models/request-param.model';
|
||||
import { Observable } from 'rxjs';
|
||||
import { RemoteData } from '../remote-data';
|
||||
import { hasValue, isNotEmptyOperator } from '../../../shared/empty.util';
|
||||
import { distinctUntilChanged, map, take, takeWhile } from 'rxjs/operators';
|
||||
import { DSpaceSerializer } from '../../dspace-rest/dspace.serializer';
|
||||
import { getClassForType } from '../../cache/builders/build-decorators';
|
||||
import { CreateRequest } from '../request.models';
|
||||
import { NotificationOptions } from '../../../shared/notifications/models/notification-options.model';
|
||||
import { RequestService } from '../request.service';
|
||||
import { RemoteDataBuildService } from '../../cache/builders/remote-data-build.service';
|
||||
import { HALEndpointService } from '../../shared/hal-endpoint.service';
|
||||
import { NotificationsService } from '../../../shared/notifications/notifications.service';
|
||||
import { ObjectCacheService } from '../../cache/object-cache.service';
|
||||
|
||||
/**
|
||||
* Interface for a data service that can create objects.
|
||||
*/
|
||||
export interface CreateData<T extends CacheableObject> {
|
||||
/**
|
||||
* Create a new DSpaceObject on the server, and store the response
|
||||
* in the object cache
|
||||
*
|
||||
* @param object The object to create
|
||||
* @param params Array with additional params to combine with query string
|
||||
*/
|
||||
create(object: T, ...params: RequestParam[]): Observable<RemoteData<T>>;
|
||||
}
|
||||
|
||||
/**
|
||||
* A DataService feature to create objects.
|
||||
*
|
||||
* Concrete data services can use this feature by implementing {@link CreateData}
|
||||
* and delegating its method to an inner instance of this class.
|
||||
*/
|
||||
export class CreateDataImpl<T extends CacheableObject> extends BaseDataService<T> implements CreateData<T> {
|
||||
constructor(
|
||||
protected linkPath: string,
|
||||
protected requestService: RequestService,
|
||||
protected rdbService: RemoteDataBuildService,
|
||||
protected objectCache: ObjectCacheService,
|
||||
protected halService: HALEndpointService,
|
||||
protected notificationsService: NotificationsService,
|
||||
protected responseMsToLive: number,
|
||||
) {
|
||||
super(linkPath, requestService, rdbService, objectCache, halService, responseMsToLive);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new object on the server, and store the response in the object cache
|
||||
*
|
||||
* @param object The object to create
|
||||
* @param params Array with additional params to combine with query string
|
||||
*/
|
||||
create(object: T, ...params: RequestParam[]): Observable<RemoteData<T>> {
|
||||
const endpoint$ = this.getEndpoint().pipe(
|
||||
isNotEmptyOperator(),
|
||||
distinctUntilChanged(),
|
||||
map((endpoint: string) => this.buildHrefWithParams(endpoint, params)),
|
||||
);
|
||||
return this.createOnEndpoint(object, endpoint$);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a POST request to create a new resource to a specific endpoint.
|
||||
* Use this method if the endpoint needs to be adjusted. In most cases {@link create} should be sufficient.
|
||||
* @param object the object to create
|
||||
* @param endpoint$ the endpoint to send the POST request to
|
||||
*/
|
||||
createOnEndpoint(object: T, endpoint$: Observable<string>): Observable<RemoteData<T>> {
|
||||
const requestId = this.requestService.generateRequestId();
|
||||
const serializedObject = new DSpaceSerializer(getClassForType(object.type)).serialize(object);
|
||||
|
||||
endpoint$.pipe(
|
||||
take(1),
|
||||
).subscribe((endpoint: string) => {
|
||||
const request = new CreateRequest(requestId, endpoint, JSON.stringify(serializedObject));
|
||||
if (hasValue(this.responseMsToLive)) {
|
||||
request.responseMsToLive = this.responseMsToLive;
|
||||
}
|
||||
this.requestService.send(request);
|
||||
});
|
||||
|
||||
const result$ = this.rdbService.buildFromRequestUUID<T>(requestId);
|
||||
|
||||
// TODO a dataservice is not the best place to show a notification,
|
||||
// this should move up to the components that use this method
|
||||
result$.pipe(
|
||||
takeWhile((rd: RemoteData<T>) => rd.isLoading, true)
|
||||
).subscribe((rd: RemoteData<T>) => {
|
||||
if (rd.hasFailed) {
|
||||
this.notificationsService.error('Server Error:', rd.errorMessage, new NotificationOptions(-1));
|
||||
}
|
||||
});
|
||||
|
||||
return result$;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user