forked from hazza/dspace-angular
Add config endpoint service
This commit is contained in:
10
src/app/core/cache/response-cache.models.ts
vendored
10
src/app/core/cache/response-cache.models.ts
vendored
@@ -1,5 +1,6 @@
|
|||||||
import { RequestError } from '../data/request.models';
|
import { RequestError } from '../data/request.models';
|
||||||
import { PageInfo } from '../shared/page-info.model';
|
import { PageInfo } from '../shared/page-info.model';
|
||||||
|
import { ConfigObject } from '../shared/config/config.model';
|
||||||
|
|
||||||
/* tslint:disable:max-classes-per-file */
|
/* tslint:disable:max-classes-per-file */
|
||||||
export class RestResponse {
|
export class RestResponse {
|
||||||
@@ -41,4 +42,13 @@ export class ErrorResponse extends RestResponse {
|
|||||||
this.errorMessage = error.message;
|
this.errorMessage = error.message;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class ConfigSuccessResponse extends RestResponse {
|
||||||
|
constructor(
|
||||||
|
public configDefinition: ConfigObject[],
|
||||||
|
public statusCode: string
|
||||||
|
) {
|
||||||
|
super(true, statusCode);
|
||||||
|
}
|
||||||
|
}
|
||||||
/* tslint:enable:max-classes-per-file */
|
/* tslint:enable:max-classes-per-file */
|
||||||
|
137
src/app/core/config/config.service.ts
Normal file
137
src/app/core/config/config.service.ts
Normal file
@@ -0,0 +1,137 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { Observable } from 'rxjs/Observable';
|
||||||
|
|
||||||
|
import { RequestService } from '../data/request.service';
|
||||||
|
import { ResponseCacheService } from '../cache/response-cache.service';
|
||||||
|
import { GlobalConfig } from '../../../config/global-config.interface';
|
||||||
|
import { ConfigSuccessResponse, EndpointMap, RootSuccessResponse } from '../cache/response-cache.models';
|
||||||
|
import { ConfigRequest, FindAllOptions, RestRequest, RootEndpointRequest } from '../data/request.models';
|
||||||
|
import { ResponseCacheEntry } from '../cache/response-cache.reducer';
|
||||||
|
import { hasValue, isNotEmpty } from '../../shared/empty.util';
|
||||||
|
import { ConfigObject } from '../shared/config/config.model';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export abstract class ConfigService {
|
||||||
|
protected request: ConfigRequest;
|
||||||
|
protected abstract responseCache: ResponseCacheService;
|
||||||
|
protected abstract requestService: RequestService;
|
||||||
|
protected abstract linkName: string;
|
||||||
|
protected abstract EnvConfig: GlobalConfig;
|
||||||
|
protected abstract browseEndpoint: string;
|
||||||
|
|
||||||
|
protected getConfig(request: RestRequest): Observable<ConfigObject[]> {
|
||||||
|
return this.responseCache.get(request.href)
|
||||||
|
.map((entry: ResponseCacheEntry) => entry.response)
|
||||||
|
.filter((response: ConfigSuccessResponse) => isNotEmpty(response) && isNotEmpty(response.configDefinition))
|
||||||
|
.map((response: ConfigSuccessResponse) => response.configDefinition)
|
||||||
|
.distinctUntilChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected getConfigByIDHref(endpoint, resourceID): string {
|
||||||
|
return `${endpoint}/${resourceID}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected getConfigSearchHref(endpoint, options: FindAllOptions = {}): string {
|
||||||
|
let result;
|
||||||
|
const args = [];
|
||||||
|
|
||||||
|
if (hasValue(options.scopeID)) {
|
||||||
|
result = `${endpoint}/${this.browseEndpoint}`
|
||||||
|
args.push(`uuid=${options.scopeID}`);
|
||||||
|
} else {
|
||||||
|
result = endpoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasValue(options.currentPage) && typeof options.currentPage === 'number') {
|
||||||
|
/* TODO: this is a temporary fix for the pagination start index (0 or 1) discrepancy between the rest and the frontend respectively */
|
||||||
|
args.push(`page=${options.currentPage - 1}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasValue(options.elementsPerPage)) {
|
||||||
|
args.push(`size=${options.elementsPerPage}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasValue(options.sort)) {
|
||||||
|
let direction = 'asc';
|
||||||
|
if (options.sort.direction === 1) {
|
||||||
|
direction = 'desc';
|
||||||
|
}
|
||||||
|
args.push(`sort=${options.sort.field},${direction}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isNotEmpty(args)) {
|
||||||
|
result = `${result}?${args.join('&')}`;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected getEndpointMap(): Observable<EndpointMap> {
|
||||||
|
const request = new RootEndpointRequest(this.EnvConfig);
|
||||||
|
setTimeout(() => {
|
||||||
|
this.requestService.configure(request);
|
||||||
|
}, 0);
|
||||||
|
return this.responseCache.get(request.href)
|
||||||
|
.map((entry: ResponseCacheEntry) => entry.response)
|
||||||
|
.filter((response: RootSuccessResponse) => isNotEmpty(response) && isNotEmpty(response.endpointMap))
|
||||||
|
.map((response: RootSuccessResponse) => response.endpointMap)
|
||||||
|
.distinctUntilChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
public getConfigAll(): Observable<ConfigObject[]> {
|
||||||
|
return this.getEndpoint()
|
||||||
|
.filter((href: string) => isNotEmpty(href))
|
||||||
|
.distinctUntilChanged()
|
||||||
|
.map((endpointURL: string) => new ConfigRequest(endpointURL))
|
||||||
|
.do((request: RestRequest) => {
|
||||||
|
setTimeout(() => {
|
||||||
|
this.requestService.configure(request);
|
||||||
|
}, 0);
|
||||||
|
})
|
||||||
|
.flatMap((request: RestRequest) => this.getConfig(request))
|
||||||
|
.distinctUntilChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
public getConfigByHref(href: string): Observable<ConfigObject[]> {
|
||||||
|
const request = new ConfigRequest(href);
|
||||||
|
this.requestService.configure(request);
|
||||||
|
|
||||||
|
return this.getConfig(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
public getConfigById(id: string): Observable<ConfigObject[]> {
|
||||||
|
return this.getEndpoint()
|
||||||
|
.map((endpoint: string) => this.getConfigByIDHref(endpoint, id))
|
||||||
|
.filter((href: string) => isNotEmpty(href))
|
||||||
|
.distinctUntilChanged()
|
||||||
|
.map((endpointURL: string) => new ConfigRequest(endpointURL))
|
||||||
|
.do((request: RestRequest) => {
|
||||||
|
setTimeout(() => {
|
||||||
|
this.requestService.configure(request);
|
||||||
|
}, 0);
|
||||||
|
})
|
||||||
|
.flatMap((request: RestRequest) => this.getConfig(request))
|
||||||
|
.distinctUntilChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
public getConfigBySearch(options: FindAllOptions = {}): Observable<ConfigObject[]> {
|
||||||
|
return this.getEndpoint()
|
||||||
|
.map((endpoint: string) => this.getConfigSearchHref(endpoint, options))
|
||||||
|
.filter((href: string) => isNotEmpty(href))
|
||||||
|
.distinctUntilChanged()
|
||||||
|
.map((endpointURL: string) => new ConfigRequest(endpointURL))
|
||||||
|
.do((request: RestRequest) => {
|
||||||
|
setTimeout(() => {
|
||||||
|
this.requestService.configure(request);
|
||||||
|
}, 0);
|
||||||
|
})
|
||||||
|
.flatMap((request: RestRequest) => this.getConfig(request))
|
||||||
|
.distinctUntilChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
public getEndpoint(): Observable<string> {
|
||||||
|
return this.getEndpointMap()
|
||||||
|
.map((map: EndpointMap) => map[this.linkName])
|
||||||
|
.distinctUntilChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
21
src/app/core/config/submission-definitions-config.service.ts
Normal file
21
src/app/core/config/submission-definitions-config.service.ts
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
import { Inject, Injectable } from '@angular/core';
|
||||||
|
|
||||||
|
import { ConfigService } from './config.service';
|
||||||
|
import { ResponseCacheService } from '../cache/response-cache.service';
|
||||||
|
import { RequestService } from '../data/request.service';
|
||||||
|
import { GLOBAL_CONFIG } from '../../../config';
|
||||||
|
import { GlobalConfig } from '../../../config/global-config.interface';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class SubmissionDefinitionsConfigService extends ConfigService {
|
||||||
|
protected linkName = 'submissiondefinitions';
|
||||||
|
protected browseEndpoint = 'search/findByCollection';
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
protected responseCache: ResponseCacheService,
|
||||||
|
protected requestService: RequestService,
|
||||||
|
@Inject(GLOBAL_CONFIG) protected EnvConfig: GlobalConfig) {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
21
src/app/core/config/submission-forms-config.service.ts
Normal file
21
src/app/core/config/submission-forms-config.service.ts
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
import { Inject, Injectable } from '@angular/core';
|
||||||
|
|
||||||
|
import { ConfigService } from './config.service';
|
||||||
|
import { ResponseCacheService } from '../cache/response-cache.service';
|
||||||
|
import { RequestService } from '../data/request.service';
|
||||||
|
import { GLOBAL_CONFIG } from '../../../config';
|
||||||
|
import { GlobalConfig } from '../../../config/global-config.interface';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class SubmissionFormsConfigService extends ConfigService {
|
||||||
|
protected linkName = 'submissionforms';
|
||||||
|
protected browseEndpoint = '';
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
protected responseCache: ResponseCacheService,
|
||||||
|
protected requestService: RequestService,
|
||||||
|
@Inject(GLOBAL_CONFIG) protected EnvConfig: GlobalConfig) {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
21
src/app/core/config/submission-sections-config.service.ts
Normal file
21
src/app/core/config/submission-sections-config.service.ts
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
import { Inject, Injectable } from '@angular/core';
|
||||||
|
|
||||||
|
import { ConfigService } from './config.service';
|
||||||
|
import { ResponseCacheService } from '../cache/response-cache.service';
|
||||||
|
import { RequestService } from '../data/request.service';
|
||||||
|
import { GLOBAL_CONFIG } from '../../../config';
|
||||||
|
import { GlobalConfig } from '../../../config/global-config.interface';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class SubmissionSectionsConfigService extends ConfigService {
|
||||||
|
protected linkName = 'submissionsections';
|
||||||
|
protected browseEndpoint = '';
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
protected responseCache: ResponseCacheService,
|
||||||
|
protected requestService: RequestService,
|
||||||
|
@Inject(GLOBAL_CONFIG) protected EnvConfig: GlobalConfig) {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -30,6 +30,10 @@ import { ResponseCacheService } from './cache/response-cache.service';
|
|||||||
import { RootResponseParsingService } from './data/root-response-parsing.service';
|
import { RootResponseParsingService } from './data/root-response-parsing.service';
|
||||||
import { ServerResponseService } from '../shared/server-response.service';
|
import { ServerResponseService } from '../shared/server-response.service';
|
||||||
import { NativeWindowFactory, NativeWindowService } from '../shared/window.service';
|
import { NativeWindowFactory, NativeWindowService } from '../shared/window.service';
|
||||||
|
import { SubmissionDefinitionsConfigService } from './config/submission-definitions-config.service';
|
||||||
|
import { ConfigResponseParsingService } from './data/config-response-parsing.service';
|
||||||
|
import { SubmissionFormsConfigService } from './config/submission-forms-config.service';
|
||||||
|
import { SubmissionSectionsConfigService } from './config/submission-sections-config.service';
|
||||||
|
|
||||||
const IMPORTS = [
|
const IMPORTS = [
|
||||||
CommonModule,
|
CommonModule,
|
||||||
@@ -61,6 +65,10 @@ const PROVIDERS = [
|
|||||||
ResponseCacheService,
|
ResponseCacheService,
|
||||||
RootResponseParsingService,
|
RootResponseParsingService,
|
||||||
ServerResponseService,
|
ServerResponseService,
|
||||||
|
ConfigResponseParsingService,
|
||||||
|
SubmissionDefinitionsConfigService,
|
||||||
|
SubmissionFormsConfigService,
|
||||||
|
SubmissionSectionsConfigService,
|
||||||
{ provide: NativeWindowService, useFactory: NativeWindowFactory }
|
{ provide: NativeWindowService, useFactory: NativeWindowFactory }
|
||||||
];
|
];
|
||||||
|
|
||||||
|
36
src/app/core/data/config-response-parsing.service.ts
Normal file
36
src/app/core/data/config-response-parsing.service.ts
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
|
||||||
|
import { ResponseParsingService } from './parsing.service';
|
||||||
|
import { RestRequest } from './request.models';
|
||||||
|
import { DSpaceRESTV2Response } from '../dspace-rest-v2/dspace-rest-v2-response.model';
|
||||||
|
import { ConfigSuccessResponse, ErrorResponse, RestResponse } from '../cache/response-cache.models';
|
||||||
|
import { isNotEmpty } from '../../shared/empty.util';
|
||||||
|
import { DSpaceRESTv2Serializer } from '../dspace-rest-v2/dspace-rest-v2.serializer';
|
||||||
|
import { ConfigObjectFactory } from '../shared/config/config-object-factory';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class ConfigResponseParsingService implements ResponseParsingService {
|
||||||
|
|
||||||
|
parse(request: RestRequest, data: DSpaceRESTV2Response): RestResponse {
|
||||||
|
if (isNotEmpty(data.payload) && isNotEmpty(data.payload._links)) {
|
||||||
|
let configDefinition;
|
||||||
|
if (isNotEmpty(data.payload._embedded) && Array.isArray(data.payload._embedded[Object.keys(data.payload._embedded)[0]])) {
|
||||||
|
const type = Object.keys(data.payload._embedded)[0];
|
||||||
|
const serializer = new DSpaceRESTv2Serializer(ConfigObjectFactory.getConstructor(type));
|
||||||
|
configDefinition = serializer.deserializeArray(data.payload._embedded[Object.keys(data.payload._embedded)[0]]);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
const serializer = new DSpaceRESTv2Serializer(ConfigObjectFactory.getConstructor(data.payload.type));
|
||||||
|
configDefinition = serializer.deserialize(data.payload);
|
||||||
|
}
|
||||||
|
return new ConfigSuccessResponse(configDefinition, data.statusCode);
|
||||||
|
} else {
|
||||||
|
return new ErrorResponse(
|
||||||
|
Object.assign(
|
||||||
|
new Error('Unexpected response from config endpoint'),
|
||||||
|
{statusText: data.statusCode}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -5,6 +5,7 @@ import { RESTURLCombiner } from '../url-combiner/rest-url-combiner';
|
|||||||
import { DSOResponseParsingService } from './dso-response-parsing.service';
|
import { DSOResponseParsingService } from './dso-response-parsing.service';
|
||||||
import { ResponseParsingService } from './parsing.service';
|
import { ResponseParsingService } from './parsing.service';
|
||||||
import { RootResponseParsingService } from './root-response-parsing.service';
|
import { RootResponseParsingService } from './root-response-parsing.service';
|
||||||
|
import { ConfigResponseParsingService } from './config-response-parsing.service';
|
||||||
|
|
||||||
/* tslint:disable:max-classes-per-file */
|
/* tslint:disable:max-classes-per-file */
|
||||||
export class RestRequest {
|
export class RestRequest {
|
||||||
@@ -53,6 +54,16 @@ export class RootEndpointRequest extends RestRequest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class ConfigRequest extends RestRequest {
|
||||||
|
constructor(href: string) {
|
||||||
|
super(href);
|
||||||
|
}
|
||||||
|
|
||||||
|
getResponseParser(): GenericConstructor<ResponseParsingService> {
|
||||||
|
return ConfigResponseParsingService;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export class RequestError extends Error {
|
export class RequestError extends Error {
|
||||||
statusText: string;
|
statusText: string;
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
export interface DSpaceRESTV2Response {
|
export interface DSpaceRESTV2Response {
|
||||||
payload: {
|
payload: {
|
||||||
|
[name: string]: string;
|
||||||
_embedded?: any;
|
_embedded?: any;
|
||||||
_links?: any;
|
_links?: any;
|
||||||
page?: any;
|
page?: any;
|
||||||
|
30
src/app/core/shared/config/config-object-factory.ts
Normal file
30
src/app/core/shared/config/config-object-factory.ts
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
|
||||||
|
import { GenericConstructor } from '../../shared/generic-constructor';
|
||||||
|
|
||||||
|
import { SubmissionSectionModel } from './config-submission-section.model';
|
||||||
|
import { SubmissionFormsModel } from './config-submission-forms.model';
|
||||||
|
import { SubmissionDefinitionsModel } from './config-submission-definitions.model';
|
||||||
|
import { ConfigType } from './config-type';
|
||||||
|
import { ConfigObject } from './config.model';
|
||||||
|
|
||||||
|
export class ConfigObjectFactory {
|
||||||
|
public static getConstructor(type): GenericConstructor<ConfigObject> {
|
||||||
|
switch (type) {
|
||||||
|
case ConfigType.SubmissionDefinition:
|
||||||
|
case ConfigType.SubmissionDefinitions: {
|
||||||
|
return SubmissionDefinitionsModel
|
||||||
|
}
|
||||||
|
case ConfigType.SubmissionForm:
|
||||||
|
case ConfigType.SubmissionForms: {
|
||||||
|
return SubmissionFormsModel
|
||||||
|
}
|
||||||
|
case ConfigType.SubmissionSection:
|
||||||
|
case ConfigType.SubmissionSections: {
|
||||||
|
return SubmissionSectionModel
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,15 @@
|
|||||||
|
import { autoserialize, inheritSerialization } from 'cerialize';
|
||||||
|
import { ConfigObject } from './config.model';
|
||||||
|
import { SubmissionSectionModel } from './config-submission-section.model';
|
||||||
|
import { RemoteData } from '../../data/remote-data';
|
||||||
|
|
||||||
|
@inheritSerialization(ConfigObject)
|
||||||
|
export class SubmissionDefinitionsModel extends ConfigObject {
|
||||||
|
|
||||||
|
@autoserialize
|
||||||
|
isDefault: boolean;
|
||||||
|
|
||||||
|
@autoserialize
|
||||||
|
sections: RemoteData<SubmissionSectionModel[]>;
|
||||||
|
|
||||||
|
}
|
10
src/app/core/shared/config/config-submission-forms.model.ts
Normal file
10
src/app/core/shared/config/config-submission-forms.model.ts
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
import { autoserialize, autoserializeAs, inheritSerialization } from 'cerialize';
|
||||||
|
import { ConfigObject } from './config.model';
|
||||||
|
|
||||||
|
@inheritSerialization(ConfigObject)
|
||||||
|
export class SubmissionFormsModel extends ConfigObject {
|
||||||
|
|
||||||
|
@autoserialize
|
||||||
|
fields: any[];
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,16 @@
|
|||||||
|
import { autoserialize, autoserializeAs, inheritSerialization } from 'cerialize';
|
||||||
|
import { ConfigObject } from './config.model';
|
||||||
|
|
||||||
|
@inheritSerialization(ConfigObject)
|
||||||
|
export class SubmissionSectionModel extends ConfigObject {
|
||||||
|
|
||||||
|
@autoserialize
|
||||||
|
header: string;
|
||||||
|
|
||||||
|
@autoserialize
|
||||||
|
mandatory: boolean;
|
||||||
|
|
||||||
|
@autoserialize
|
||||||
|
sectionType: string;
|
||||||
|
|
||||||
|
}
|
12
src/app/core/shared/config/config-type.ts
Normal file
12
src/app/core/shared/config/config-type.ts
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
/**
|
||||||
|
* TODO replace with actual string enum after upgrade to TypeScript 2.4:
|
||||||
|
* https://github.com/Microsoft/TypeScript/pull/15486
|
||||||
|
*/
|
||||||
|
export enum ConfigType {
|
||||||
|
SubmissionDefinitions = 'submissiondefinitions',
|
||||||
|
SubmissionDefinition = 'submissiondefinition',
|
||||||
|
SubmissionForm = 'submissionform',
|
||||||
|
SubmissionForms = 'submissionforms',
|
||||||
|
SubmissionSections = 'submissionsections',
|
||||||
|
SubmissionSection = 'submissionsection'
|
||||||
|
}
|
15
src/app/core/shared/config/config.model.ts
Normal file
15
src/app/core/shared/config/config.model.ts
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
import { autoserialize, autoserializeAs } from 'cerialize';
|
||||||
|
|
||||||
|
export abstract class ConfigObject {
|
||||||
|
|
||||||
|
@autoserialize
|
||||||
|
public name: string;
|
||||||
|
|
||||||
|
@autoserialize
|
||||||
|
public type: string;
|
||||||
|
|
||||||
|
@autoserialize
|
||||||
|
public _links: {
|
||||||
|
[name: string]: string
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user