Skip to content
Snippets Groups Projects
Commit 01f26bd8 authored by Giuseppe Digilio's avatar Giuseppe Digilio
Browse files

Add config endpoint service

parent 311fef21
Branches
Tags
No related merge requests found
Showing
with 364 additions and 0 deletions
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 */
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();
}
}
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();
}
}
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();
}
}
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 }
];
......
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;
}
......
export interface DSpaceRESTV2Response {
payload: {
[name: string]: string;
_embedded?: any;
_links?: any;
page?: any;
......
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;
}
}
}
}
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[]>;
}
import { autoserialize, autoserializeAs, inheritSerialization } from 'cerialize';
import { ConfigObject } from './config.model';
@inheritSerialization(ConfigObject)
export class SubmissionFormsModel extends ConfigObject {
@autoserialize
fields: any[];
}
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;
}
/**
* 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'
}
import { autoserialize, autoserializeAs } from 'cerialize';
export abstract class ConfigObject {
@autoserialize
public name: string;
@autoserialize
public type: string;
@autoserialize
public _links: {
[name: string]: string
}
}
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment