mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-18 15:33:04 +00:00
finished embedded object fixes
This commit is contained in:
@@ -1,7 +1,6 @@
|
|||||||
import { SortOptions } from '../core/cache/models/sort-options.model';
|
import { SortOptions } from '../core/cache/models/sort-options.model';
|
||||||
import { PaginationComponentOptions } from '../shared/pagination/pagination-component-options.model';
|
import { PaginationComponentOptions } from '../shared/pagination/pagination-component-options.model';
|
||||||
import { isNotEmpty } from '../shared/empty.util';
|
import { isNotEmpty } from '../shared/empty.util';
|
||||||
import { URLCombiner } from '../core/url-combiner/url-combiner';
|
|
||||||
import { SearchOptions } from './search-options.model';
|
import { SearchOptions } from './search-options.model';
|
||||||
|
|
||||||
export class PaginatedSearchOptions extends SearchOptions {
|
export class PaginatedSearchOptions extends SearchOptions {
|
||||||
|
@@ -8,21 +8,17 @@ import { hasValue, isEmpty, isNotEmpty } from '../../../shared/empty.util';
|
|||||||
import { PaginatedList } from '../../data/paginated-list';
|
import { PaginatedList } from '../../data/paginated-list';
|
||||||
import { RemoteData } from '../../data/remote-data';
|
import { RemoteData } from '../../data/remote-data';
|
||||||
import { RemoteDataError } from '../../data/remote-data-error';
|
import { RemoteDataError } from '../../data/remote-data-error';
|
||||||
import { GetRequest, RestRequest } from '../../data/request.models';
|
import { GetRequest } from '../../data/request.models';
|
||||||
import { RequestEntry } from '../../data/request.reducer';
|
import { RequestEntry } from '../../data/request.reducer';
|
||||||
import { RequestService } from '../../data/request.service';
|
import { RequestService } from '../../data/request.service';
|
||||||
import { DSpaceObject } from '../../shared/dspace-object.model';
|
|
||||||
import { GenericConstructor } from '../../shared/generic-constructor';
|
|
||||||
import { NormalizedDSpaceObject } from '../models/normalized-dspace-object.model';
|
|
||||||
import { NormalizedObjectFactory } from '../models/normalized-object-factory';
|
|
||||||
|
|
||||||
import { CacheableObject } from '../object-cache.reducer';
|
|
||||||
import { ObjectCacheService } from '../object-cache.service';
|
import { ObjectCacheService } from '../object-cache.service';
|
||||||
import { DSOSuccessResponse, ErrorResponse, SearchSuccessResponse } from '../response-cache.models';
|
import { DSOSuccessResponse, ErrorResponse } from '../response-cache.models';
|
||||||
import { ResponseCacheEntry } from '../response-cache.reducer';
|
import { ResponseCacheEntry } from '../response-cache.reducer';
|
||||||
import { ResponseCacheService } from '../response-cache.service';
|
import { ResponseCacheService } from '../response-cache.service';
|
||||||
import { getMapsTo, getRelationMetadata, getRelationships } from './build-decorators';
|
import { getMapsTo, getRelationMetadata, getRelationships } from './build-decorators';
|
||||||
import { NormalizedObject } from '../models/normalized-object.model';
|
import { NormalizedObject } from '../models/normalized-object.model';
|
||||||
|
import { PageInfo } from '../../shared/page-info.model';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class RemoteDataBuildService {
|
export class RemoteDataBuildService {
|
||||||
@@ -159,35 +155,43 @@ export class RemoteDataBuildService {
|
|||||||
const relationships = getRelationships(normalized.constructor) || [];
|
const relationships = getRelationships(normalized.constructor) || [];
|
||||||
|
|
||||||
relationships.forEach((relationship: string) => {
|
relationships.forEach((relationship: string) => {
|
||||||
|
let result;
|
||||||
if (hasValue(normalized[relationship])) {
|
if (hasValue(normalized[relationship])) {
|
||||||
const { resourceType, isList } = getRelationMetadata(normalized, relationship);
|
const { resourceType, isList } = getRelationMetadata(normalized, relationship);
|
||||||
if (Array.isArray(normalized[relationship])) {
|
const objectList = normalized[relationship].page || normalized[relationship];
|
||||||
normalized[relationship].forEach((href: string) => {
|
if (typeof objectList !== 'string') {
|
||||||
|
objectList.forEach((href: string) => {
|
||||||
this.requestService.configure(new GetRequest(this.requestService.generateRequestId(), href))
|
this.requestService.configure(new GetRequest(this.requestService.generateRequestId(), href))
|
||||||
});
|
});
|
||||||
|
|
||||||
const rdArr = [];
|
const rdArr = [];
|
||||||
normalized[relationship].forEach((href: string) => {
|
objectList.forEach((href: string) => {
|
||||||
rdArr.push(this.buildSingle(href));
|
rdArr.push(this.buildSingle(href));
|
||||||
});
|
});
|
||||||
|
|
||||||
if (isList) {
|
if (isList) {
|
||||||
links[relationship] = this.aggregate(rdArr);
|
result = this.aggregate(rdArr);
|
||||||
} else if (rdArr.length === 1) {
|
} else if (rdArr.length === 1) {
|
||||||
links[relationship] = rdArr[0];
|
result = rdArr[0];
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this.requestService.configure(new GetRequest(this.requestService.generateRequestId(), normalized[relationship]));
|
this.requestService.configure(new GetRequest(this.requestService.generateRequestId(), objectList));
|
||||||
|
|
||||||
// The rest API can return a single URL to represent a list of resources (e.g. /items/:id/bitstreams)
|
// The rest API can return a single URL to represent a list of resources (e.g. /items/:id/bitstreams)
|
||||||
// in that case only 1 href will be stored in the normalized obj (so the isArray above fails),
|
// in that case only 1 href will be stored in the normalized obj (so the isArray above fails),
|
||||||
// but it should still be built as a list
|
// but it should still be built as a list
|
||||||
if (isList) {
|
if (isList) {
|
||||||
links[relationship] = this.buildList(normalized[relationship]);
|
result = this.buildList(objectList);
|
||||||
} else {
|
} else {
|
||||||
links[relationship] = this.buildSingle(normalized[relationship]);
|
result = this.buildSingle(objectList);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (hasValue(normalized[relationship].page)) {
|
||||||
|
links[relationship] = this.aggregatePaginatedList(result, normalized[relationship].pageInfo);
|
||||||
|
} else {
|
||||||
|
links[relationship] = result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -248,4 +252,8 @@ export class RemoteDataBuildService {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
aggregatePaginatedList<T>(input: Observable<RemoteData<T[]>>, pageInfo: PageInfo): Observable<RemoteData<PaginatedList<T>>> {
|
||||||
|
return input.map((rd) => Object.assign(rd, {payload: new PaginatedList(pageInfo, rd.payload)}));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -46,7 +46,6 @@ describe('ResponseCacheService', () => {
|
|||||||
|
|
||||||
let testObj: ResponseCacheEntry;
|
let testObj: ResponseCacheEntry;
|
||||||
service.get(keys[1]).first().subscribe((entry) => {
|
service.get(keys[1]).first().subscribe((entry) => {
|
||||||
console.log(entry);
|
|
||||||
testObj = entry;
|
testObj = entry;
|
||||||
});
|
});
|
||||||
expect(testObj.key).toEqual(keys[1]);
|
expect(testObj.key).toEqual(keys[1]);
|
||||||
|
@@ -34,19 +34,26 @@ export abstract class BaseResponseParsingService {
|
|||||||
} else if (Array.isArray(data)) {
|
} else if (Array.isArray(data)) {
|
||||||
return this.processArray(data, requestHref);
|
return this.processArray(data, requestHref);
|
||||||
} else if (isObjectLevel(data)) {
|
} else if (isObjectLevel(data)) {
|
||||||
let object = this.deserialize(data, requestHref);
|
const object = this.deserialize(data);
|
||||||
this.cache(object, requestHref);
|
|
||||||
if (isNotEmpty(data._embedded)) {
|
if (isNotEmpty(data._embedded)) {
|
||||||
const list = {};
|
|
||||||
Object
|
Object
|
||||||
.keys(data._embedded)
|
.keys(data._embedded)
|
||||||
.filter((property) => data._embedded.hasOwnProperty(property))
|
.filter((property) => data._embedded.hasOwnProperty(property))
|
||||||
.forEach((property) => {
|
.forEach((property) => {
|
||||||
const parsedObj = this.process<ObjectDomain, ObjectType>(data._embedded[property], requestHref);
|
const parsedObj = this.process<ObjectDomain, ObjectType>(data._embedded[property], requestHref);
|
||||||
list[property] = parsedObj;
|
if (isNotEmpty(parsedObj)) {
|
||||||
});
|
if (isPaginatedResponse(data._embedded[property])) {
|
||||||
object = Object.assign({}, object, list);
|
object[property] = parsedObj;
|
||||||
|
object[property].page = parsedObj.page.map((obj) => obj.self);
|
||||||
|
} else if (isObjectLevel(data._embedded[property])) {
|
||||||
|
object[property] = parsedObj.self;
|
||||||
|
} else if (Array.isArray(parsedObj)) {
|
||||||
|
object[property] = parsedObj.map((obj) => obj.self)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
this.cache(object, requestHref);
|
||||||
return object;
|
return object;
|
||||||
}
|
}
|
||||||
const result = {};
|
const result = {};
|
||||||
@@ -83,7 +90,7 @@ export abstract class BaseResponseParsingService {
|
|||||||
return array;
|
return array;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected deserialize<ObjectDomain, ObjectType>(obj, requestHref) {
|
protected deserialize<ObjectDomain, ObjectType>(obj): any {
|
||||||
const type: ObjectType = obj.type;
|
const type: ObjectType = obj.type;
|
||||||
if (hasValue(type)) {
|
if (hasValue(type)) {
|
||||||
const normObjConstructor = this.objectFactory.getConstructor(type) as GenericConstructor<ObjectDomain>;
|
const normObjConstructor = this.objectFactory.getConstructor(type) as GenericConstructor<ObjectDomain>;
|
||||||
|
@@ -1,5 +1,4 @@
|
|||||||
import { ConfigSuccessResponse, ErrorResponse } from '../cache/response-cache.models';
|
import { ConfigSuccessResponse, ErrorResponse } from '../cache/response-cache.models';
|
||||||
import { DSpaceRESTV2Response } from '../dspace-rest-v2/dspace-rest-v2-response.model';
|
|
||||||
import { ConfigResponseParsingService } from './config-response-parsing.service';
|
import { ConfigResponseParsingService } from './config-response-parsing.service';
|
||||||
import { ObjectCacheService } from '../cache/object-cache.service';
|
import { ObjectCacheService } from '../cache/object-cache.service';
|
||||||
import { GlobalConfig } from '../../../config/global-config.interface';
|
import { GlobalConfig } from '../../../config/global-config.interface';
|
||||||
@@ -8,7 +7,8 @@ import { ConfigRequest } from './request.models';
|
|||||||
import { Store } from '@ngrx/store';
|
import { Store } from '@ngrx/store';
|
||||||
import { CoreState } from '../core.reducers';
|
import { CoreState } from '../core.reducers';
|
||||||
import { SubmissionDefinitionsModel } from '../shared/config/config-submission-definitions.model';
|
import { SubmissionDefinitionsModel } from '../shared/config/config-submission-definitions.model';
|
||||||
import { SubmissionSectionModel } from '../shared/config/config-submission-section.model';
|
import { PaginatedList } from './paginated-list';
|
||||||
|
import { PageInfo } from '../shared/page-info.model';
|
||||||
|
|
||||||
describe('ConfigResponseParsingService', () => {
|
describe('ConfigResponseParsingService', () => {
|
||||||
let service: ConfigResponseParsingService;
|
let service: ConfigResponseParsingService;
|
||||||
@@ -16,15 +16,10 @@ describe('ConfigResponseParsingService', () => {
|
|||||||
const EnvConfig = {} as GlobalConfig;
|
const EnvConfig = {} as GlobalConfig;
|
||||||
const store = {} as Store<CoreState>;
|
const store = {} as Store<CoreState>;
|
||||||
const objectCacheService = new ObjectCacheService(store);
|
const objectCacheService = new ObjectCacheService(store);
|
||||||
|
let validResponse;
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
service = new ConfigResponseParsingService(EnvConfig, objectCacheService);
|
service = new ConfigResponseParsingService(EnvConfig, objectCacheService);
|
||||||
});
|
validResponse = {
|
||||||
|
|
||||||
describe('parse', () => {
|
|
||||||
const validRequest = new ConfigRequest('69f375b5-19f4-4453-8c7a-7dc5c55aafbb', 'https://rest.api/config/submissiondefinitions/traditional');
|
|
||||||
|
|
||||||
const validResponse = {
|
|
||||||
payload: {
|
payload: {
|
||||||
id: 'traditional',
|
id: 'traditional',
|
||||||
name: 'traditional',
|
name: 'traditional',
|
||||||
@@ -33,7 +28,8 @@ describe('ConfigResponseParsingService', () => {
|
|||||||
_links: {
|
_links: {
|
||||||
sections: {
|
sections: {
|
||||||
href: 'https://rest.api/config/submissiondefinitions/traditional/sections'
|
href: 'https://rest.api/config/submissiondefinitions/traditional/sections'
|
||||||
},self:{
|
},
|
||||||
|
self: {
|
||||||
href: 'https://rest.api/config/submissiondefinitions/traditional'
|
href: 'https://rest.api/config/submissiondefinitions/traditional'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -116,13 +112,19 @@ describe('ConfigResponseParsingService', () => {
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
_links: {
|
_links: {
|
||||||
self:'https://rest.api/config/submissiondefinitions/traditional/sections'
|
self: {
|
||||||
|
href: 'https://rest.api/config/submissiondefinitions/traditional/sections'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
statusCode: '200'
|
statusCode: '200'
|
||||||
};
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('parse', () => {
|
||||||
|
const validRequest = new ConfigRequest('69f375b5-19f4-4453-8c7a-7dc5c55aafbb', 'https://rest.api/config/submissiondefinitions/traditional');
|
||||||
|
|
||||||
const invalidResponse1 = {
|
const invalidResponse1 = {
|
||||||
payload: {},
|
payload: {},
|
||||||
@@ -159,61 +161,24 @@ describe('ConfigResponseParsingService', () => {
|
|||||||
page: { size: 20, totalElements: 2, totalPages: 1, number: 0 }
|
page: { size: 20, totalElements: 2, totalPages: 1, number: 0 }
|
||||||
}, statusCode: '500'
|
}, statusCode: '500'
|
||||||
};
|
};
|
||||||
|
const pageinfo = Object.assign(new PageInfo(), { elementsPerPage: 4, totalElements: 4, totalPages: 1, currentPage: 1 });
|
||||||
const definitions = [
|
const definitions =
|
||||||
Object.assign(new SubmissionDefinitionsModel(), {
|
Object.assign(new SubmissionDefinitionsModel(), {
|
||||||
isDefault: true,
|
isDefault: true,
|
||||||
name: 'traditional',
|
name: 'traditional',
|
||||||
type: 'submissiondefinition',
|
type: 'submissiondefinition',
|
||||||
_links: {},
|
_links: {
|
||||||
sections: [
|
sections: 'https://rest.api/config/submissiondefinitions/traditional/sections',
|
||||||
Object.assign(new SubmissionSectionModel(), {
|
self: 'https://rest.api/config/submissiondefinitions/traditional'
|
||||||
header: 'submit.progressbar.describe.stepone',
|
|
||||||
mandatory: true,
|
|
||||||
sectionType: 'submission-form',
|
|
||||||
visibility:{
|
|
||||||
main:null,
|
|
||||||
other:'READONLY'
|
|
||||||
},
|
},
|
||||||
type: 'submissionsection',
|
self: 'https://rest.api/config/submissiondefinitions/traditional',
|
||||||
_links: {}
|
sections: new PaginatedList(pageinfo, [
|
||||||
}),
|
'https://rest.api/config/submissionsections/traditionalpageone',
|
||||||
Object.assign(new SubmissionSectionModel(), {
|
'https://rest.api/config/submissionsections/traditionalpagetwo',
|
||||||
header: 'submit.progressbar.describe.steptwo',
|
'https://rest.api/config/submissionsections/upload',
|
||||||
mandatory: true,
|
'https://rest.api/config/submissionsections/license'
|
||||||
sectionType: 'submission-form',
|
])
|
||||||
visibility:{
|
});
|
||||||
main:null,
|
|
||||||
other:'READONLY'
|
|
||||||
},
|
|
||||||
type: 'submissionsection',
|
|
||||||
_links: {}
|
|
||||||
}),
|
|
||||||
Object.assign(new SubmissionSectionModel(), {
|
|
||||||
header: 'submit.progressbar.upload',
|
|
||||||
mandatory: false,
|
|
||||||
sectionType: 'upload',
|
|
||||||
visibility:{
|
|
||||||
main:null,
|
|
||||||
other:'READONLY'
|
|
||||||
},
|
|
||||||
type: 'submissionsection',
|
|
||||||
_links: {}
|
|
||||||
}),
|
|
||||||
Object.assign(new SubmissionSectionModel(), {
|
|
||||||
header: 'submit.progressbar.license',
|
|
||||||
mandatory: true,
|
|
||||||
sectionType: 'license',
|
|
||||||
visibility:{
|
|
||||||
main:null,
|
|
||||||
other:'READONLY'
|
|
||||||
},
|
|
||||||
type: 'submissionsection',
|
|
||||||
_links: {}
|
|
||||||
})
|
|
||||||
]
|
|
||||||
})
|
|
||||||
];
|
|
||||||
|
|
||||||
it('should return a ConfigSuccessResponse if data contains a valid config endpoint response', () => {
|
it('should return a ConfigSuccessResponse if data contains a valid config endpoint response', () => {
|
||||||
const response = service.parse(validRequest, validResponse);
|
const response = service.parse(validRequest, validResponse);
|
||||||
@@ -232,11 +197,8 @@ describe('ConfigResponseParsingService', () => {
|
|||||||
expect(response.constructor).toBe(ErrorResponse);
|
expect(response.constructor).toBe(ErrorResponse);
|
||||||
});
|
});
|
||||||
|
|
||||||
fit('should return a ConfigSuccessResponse with the ConfigDefinitions in data', () => {
|
it('should return a ConfigSuccessResponse with the ConfigDefinitions in data', () => {
|
||||||
const response = service.parse(validRequest, validResponse);
|
const response = service.parse(validRequest, validResponse);
|
||||||
debugger;
|
|
||||||
console.log(definitions);
|
|
||||||
console.log((response as any).configDefinition);
|
|
||||||
expect((response as any).configDefinition).toEqual(definitions);
|
expect((response as any).configDefinition).toEqual(definitions);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@@ -27,7 +27,6 @@ export class ConfigResponseParsingService extends BaseResponseParsingService imp
|
|||||||
}
|
}
|
||||||
|
|
||||||
parse(request: RestRequest, data: DSpaceRESTV2Response): RestResponse {
|
parse(request: RestRequest, data: DSpaceRESTV2Response): RestResponse {
|
||||||
console.log(data);
|
|
||||||
if (isNotEmpty(data.payload) && isNotEmpty(data.payload._links) && data.statusCode === '200') {
|
if (isNotEmpty(data.payload) && isNotEmpty(data.payload._links) && data.statusCode === '200') {
|
||||||
const configDefinition = this.process<ConfigObject,ConfigType>(data.payload, request.href);
|
const configDefinition = this.process<ConfigObject,ConfigType>(data.payload, request.href);
|
||||||
return new ConfigSuccessResponse(configDefinition, data.statusCode, this.processPageInfo(data.payload));
|
return new ConfigSuccessResponse(configDefinition, data.statusCode, this.processPageInfo(data.payload));
|
||||||
|
Reference in New Issue
Block a user