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 { PageInfo } from '../shared/page-info.model';
|
||||
import { ConfigObject } from '../shared/config/config.model';
|
||||
|
||||
/* tslint:disable:max-classes-per-file */
|
||||
export class RestResponse {
|
||||
@@ -41,4 +42,13 @@ export class ErrorResponse extends RestResponse {
|
||||
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 */
|
||||
|
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 { ServerResponseService } from '../shared/server-response.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 = [
|
||||
CommonModule,
|
||||
@@ -61,6 +65,10 @@ const PROVIDERS = [
|
||||
ResponseCacheService,
|
||||
RootResponseParsingService,
|
||||
ServerResponseService,
|
||||
ConfigResponseParsingService,
|
||||
SubmissionDefinitionsConfigService,
|
||||
SubmissionFormsConfigService,
|
||||
SubmissionSectionsConfigService,
|
||||
{ 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 { ResponseParsingService } from './parsing.service';
|
||||
import { RootResponseParsingService } from './root-response-parsing.service';
|
||||
import { ConfigResponseParsingService } from './config-response-parsing.service';
|
||||
|
||||
/* tslint:disable:max-classes-per-file */
|
||||
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 {
|
||||
statusText: string;
|
||||
}
|
||||
|
@@ -1,5 +1,6 @@
|
||||
export interface DSpaceRESTV2Response {
|
||||
payload: {
|
||||
[name: string]: string;
|
||||
_embedded?: any;
|
||||
_links?: 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