mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-17 15:03:07 +00:00
Merge pull request #271 from atmire/embedded-objects-fixes
Embedded objects fixes
This commit is contained in:
@@ -2,7 +2,7 @@
|
|||||||
<div *ngIf="subCollectionsRD?.hasSucceeded" @fadeIn>
|
<div *ngIf="subCollectionsRD?.hasSucceeded" @fadeIn>
|
||||||
<h2>{{'community.sub-collection-list.head' | translate}}</h2>
|
<h2>{{'community.sub-collection-list.head' | translate}}</h2>
|
||||||
<ul>
|
<ul>
|
||||||
<li *ngFor="let collection of subCollectionsRD?.payload">
|
<li *ngFor="let collection of subCollectionsRD?.payload.page">
|
||||||
<p>
|
<p>
|
||||||
<span class="lead"><a [routerLink]="['/collections', collection.id]">{{collection.name}}</a></span><br>
|
<span class="lead"><a [routerLink]="['/collections', collection.id]">{{collection.name}}</a></span><br>
|
||||||
<span class="text-muted">{{collection.shortDescription}}</span>
|
<span class="text-muted">{{collection.shortDescription}}</span>
|
||||||
|
@@ -6,6 +6,7 @@ import { Collection } from '../../core/shared/collection.model';
|
|||||||
import { Community } from '../../core/shared/community.model';
|
import { Community } from '../../core/shared/community.model';
|
||||||
|
|
||||||
import { fadeIn } from '../../shared/animations/fade';
|
import { fadeIn } from '../../shared/animations/fade';
|
||||||
|
import { PaginatedList } from '../../core/data/paginated-list';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ds-community-page-sub-collection-list',
|
selector: 'ds-community-page-sub-collection-list',
|
||||||
@@ -15,7 +16,7 @@ import { fadeIn } from '../../shared/animations/fade';
|
|||||||
})
|
})
|
||||||
export class CommunityPageSubCollectionListComponent implements OnInit {
|
export class CommunityPageSubCollectionListComponent implements OnInit {
|
||||||
@Input() community: Community;
|
@Input() community: Community;
|
||||||
subCollectionsRDObs: Observable<RemoteData<Collection[]>>;
|
subCollectionsRDObs: Observable<RemoteData<PaginatedList<Collection>>>;
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.subCollectionsRDObs = this.community.collections;
|
this.subCollectionsRDObs = this.community.collections;
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
<ds-metadata-field-wrapper [label]="label | translate">
|
<ds-metadata-field-wrapper *ngIf="hasSucceeded() | async" [label]="label | translate">
|
||||||
<div class="collections">
|
<div class="collections">
|
||||||
<a *ngFor="let collection of (collections | async); let last=last;" [routerLink]="['/collections', collection.id]">
|
<a *ngFor="let collection of (collections | async); let last=last;" [routerLink]="['/collections', collection.id]">
|
||||||
<span>{{collection?.name}}</span><span *ngIf="!last" [innerHTML]="separator"></span>
|
<span>{{collection?.name}}</span><span *ngIf="!last" [innerHTML]="separator"></span>
|
||||||
|
@@ -0,0 +1,74 @@
|
|||||||
|
import { CollectionsComponent } from './collections.component';
|
||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core';
|
||||||
|
import { By } from '@angular/platform-browser';
|
||||||
|
import { Collection } from '../../../core/shared/collection.model';
|
||||||
|
import { RemoteDataBuildService } from '../../../core/cache/builders/remote-data-build.service';
|
||||||
|
import { getMockRemoteDataBuildService } from '../../../shared/mocks/mock-remote-data-build.service';
|
||||||
|
import { Item } from '../../../core/shared/item.model';
|
||||||
|
import { Observable } from 'rxjs/Observable';
|
||||||
|
import { RemoteData } from '../../../core/data/remote-data';
|
||||||
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
|
|
||||||
|
let collectionsComponent: CollectionsComponent;
|
||||||
|
let fixture: ComponentFixture<CollectionsComponent>;
|
||||||
|
|
||||||
|
const mockCollection1: Collection = Object.assign(new Collection(), {
|
||||||
|
metadata: [
|
||||||
|
{
|
||||||
|
key: 'dc.description.abstract',
|
||||||
|
language: 'en_US',
|
||||||
|
value: 'Short description'
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
|
||||||
|
const succeededMockItem: Item = Object.assign(new Item(), {owningCollection: Observable.of(new RemoteData(false, false, true, null, mockCollection1))});
|
||||||
|
const failedMockItem: Item = Object.assign(new Item(), {owningCollection: Observable.of(new RemoteData(false, false, false, null, mockCollection1))});
|
||||||
|
|
||||||
|
describe('CollectionsComponent', () => {
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
imports: [TranslateModule.forRoot()],
|
||||||
|
declarations: [ CollectionsComponent ],
|
||||||
|
providers: [
|
||||||
|
{ provide: RemoteDataBuildService, useValue: getMockRemoteDataBuildService()}
|
||||||
|
],
|
||||||
|
|
||||||
|
schemas: [ NO_ERRORS_SCHEMA ]
|
||||||
|
}).overrideComponent(CollectionsComponent, {
|
||||||
|
set: { changeDetection: ChangeDetectionStrategy.Default }
|
||||||
|
}).compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
fixture = TestBed.createComponent(CollectionsComponent);
|
||||||
|
collectionsComponent = fixture.componentInstance;
|
||||||
|
collectionsComponent.label = 'test.test';
|
||||||
|
collectionsComponent.separator = '<br/>';
|
||||||
|
|
||||||
|
}));
|
||||||
|
|
||||||
|
describe('When the requested item request has succeeded', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
collectionsComponent.item = succeededMockItem;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should show the collection', () => {
|
||||||
|
const collectionField = fixture.debugElement.query(By.css('ds-metadata-field-wrapper div.collections'));
|
||||||
|
expect(collectionField).not.toBeNull();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('When the requested item request has failed', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
collectionsComponent.item = failedMockItem;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not show the collection', () => {
|
||||||
|
const collectionField = fixture.debugElement.query(By.css('ds-metadata-field-wrapper div.collections'));
|
||||||
|
expect(collectionField).toBeNull();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@@ -38,4 +38,8 @@ export class CollectionsComponent implements OnInit {
|
|||||||
this.collections = this.item.owner.map((rd: RemoteData<Collection>) => [rd.payload]);
|
this.collections = this.item.owner.map((rd: RemoteData<Collection>) => [rd.payload]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hasSucceeded() {
|
||||||
|
return this.item.owner.map((rd: RemoteData<Collection>) => rd.hasSucceeded);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -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,12 +8,14 @@ import { RemoteDataError } from '../../data/remote-data-error';
|
|||||||
import { GetRequest } 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 { NormalizedObject } from '../models/normalized-object.model';
|
import { NormalizedObject } from '../models/normalized-object.model';
|
||||||
import { ObjectCacheService } from '../object-cache.service';
|
import { ObjectCacheService } from '../object-cache.service';
|
||||||
import { DSOSuccessResponse, ErrorResponse } 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 { PageInfo } from '../../shared/page-info.model';
|
||||||
import {
|
import {
|
||||||
getRequestFromSelflink,
|
getRequestFromSelflink,
|
||||||
getResourceLinksFromResponse,
|
getResourceLinksFromResponse,
|
||||||
@@ -96,7 +98,6 @@ export class RemoteDataBuildService {
|
|||||||
error = new RemoteDataError(resEntry.response.statusCode, errorMessage);
|
error = new RemoteDataError(resEntry.response.statusCode, errorMessage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return new RemoteData(
|
return new RemoteData(
|
||||||
requestPending,
|
requestPending,
|
||||||
responsePending,
|
responsePending,
|
||||||
@@ -107,7 +108,7 @@ export class RemoteDataBuildService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
buildList<TNormalized extends NormalizedObject, TDomain>(href$: string | Observable<string>): Observable<RemoteData<TDomain[] | PaginatedList<TDomain>>> {
|
buildList<TNormalized extends NormalizedObject, TDomain>(href$: string | Observable<string>): Observable<RemoteData<PaginatedList<TDomain>>> {
|
||||||
if (typeof href$ === 'string') {
|
if (typeof href$ === 'string') {
|
||||||
href$ = Observable.of(href$);
|
href$ = Observable.of(href$);
|
||||||
}
|
}
|
||||||
@@ -144,11 +145,7 @@ export class RemoteDataBuildService {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const payload$ = Observable.combineLatest(tDomainList$, pageInfo$, (tDomainList, pageInfo) => {
|
const payload$ = Observable.combineLatest(tDomainList$, pageInfo$, (tDomainList, pageInfo) => {
|
||||||
if (hasValue(pageInfo)) {
|
return new PaginatedList(pageInfo, tDomainList);
|
||||||
return new PaginatedList(pageInfo, tDomainList);
|
|
||||||
} else {
|
|
||||||
return tDomainList;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return this.toRemoteDataObservable(requestEntry$, responseCache$, payload$);
|
return this.toRemoteDataObservable(requestEntry$, responseCache$, payload$);
|
||||||
@@ -160,35 +157,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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -249,4 +254,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)}));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
34
src/app/core/cache/id-to-uuid-serializer.spec.ts
vendored
Normal file
34
src/app/core/cache/id-to-uuid-serializer.spec.ts
vendored
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
import { IDToUUIDSerializer } from './id-to-uuid-serializer';
|
||||||
|
|
||||||
|
describe('IDToUUIDSerializer', () => {
|
||||||
|
let serializer: IDToUUIDSerializer;
|
||||||
|
const prefix = 'test-prefix';
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
serializer = new IDToUUIDSerializer(prefix);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Serialize', () => {
|
||||||
|
it('should return undefined', () => {
|
||||||
|
expect(serializer.Serialize('some-uuid')).toBeUndefined()
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Deserialize', () => {
|
||||||
|
describe('when ID is defined', () => {
|
||||||
|
it('should prepend the prefix to the ID', () => {
|
||||||
|
const id = 'some-id';
|
||||||
|
expect(serializer.Deserialize(id)).toBe(`${prefix}-${id}`);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when ID is null or undefined', () => {
|
||||||
|
it('should return null or undefined', () => {
|
||||||
|
expect(serializer.Deserialize(null)).toBeNull();
|
||||||
|
expect(serializer.Deserialize(undefined)).toBeUndefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
35
src/app/core/cache/id-to-uuid-serializer.ts
vendored
Normal file
35
src/app/core/cache/id-to-uuid-serializer.ts
vendored
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
import { hasValue } from '../../shared/empty.util';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serializer to create unique fake UUID's from id's that might otherwise be the same across multiple object types
|
||||||
|
*/
|
||||||
|
export class IDToUUIDSerializer {
|
||||||
|
/**
|
||||||
|
* @param {string} prefix To prepend the original ID with
|
||||||
|
*/
|
||||||
|
constructor(private prefix: string) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method to serialize a UUID
|
||||||
|
* @param {string} uuid
|
||||||
|
* @returns {any} undefined Fake UUID's should not be sent back to the server, but only be used in the UI
|
||||||
|
*/
|
||||||
|
Serialize(uuid: string): any {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method to deserialize a UUID
|
||||||
|
* @param {string} id Identifier to transform in to a UUID
|
||||||
|
* @returns {string} UUID based on the prefix and the given id
|
||||||
|
*/
|
||||||
|
Deserialize(id: string): string {
|
||||||
|
if (hasValue(id)) {
|
||||||
|
return `${this.prefix}-${id}`;
|
||||||
|
} else {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
64
src/app/core/cache/models/action-type.model.ts
vendored
Normal file
64
src/app/core/cache/models/action-type.model.ts
vendored
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
/**
|
||||||
|
* Enum representing the Action Type of a Resource Policy
|
||||||
|
*/
|
||||||
|
export enum ActionType {
|
||||||
|
/**
|
||||||
|
* Action of reading, viewing or downloading something
|
||||||
|
*/
|
||||||
|
READ = 0,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Action of modifying something
|
||||||
|
*/
|
||||||
|
WRITE = 1,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Action of deleting something
|
||||||
|
*/
|
||||||
|
DELETE = 2,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Action of adding something to a container
|
||||||
|
*/
|
||||||
|
ADD = 3,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Action of removing something from a container
|
||||||
|
*/
|
||||||
|
REMOVE = 4,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Action of performing workflow step 1
|
||||||
|
*/
|
||||||
|
WORKFLOW_STEP_1 = 5,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Action of performing workflow step 2
|
||||||
|
*/
|
||||||
|
WORKFLOW_STEP_2 = 6,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Action of performing workflow step 3
|
||||||
|
*/
|
||||||
|
WORKFLOW_STEP_3 = 7,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Action of performing a workflow abort
|
||||||
|
*/
|
||||||
|
WORKFLOW_ABORT = 8,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default Read policies for Bitstreams submitted to container
|
||||||
|
*/
|
||||||
|
DEFAULT_BITSTREAM_READ = 9,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default Read policies for Items submitted to container
|
||||||
|
*/
|
||||||
|
DEFAULT_ITEM_READ = 10,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Administrative actions
|
||||||
|
*/
|
||||||
|
ADMIN = 11,
|
||||||
|
}
|
66
src/app/core/cache/models/normalized-bitstream-format.model.ts
vendored
Normal file
66
src/app/core/cache/models/normalized-bitstream-format.model.ts
vendored
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
import { autoserialize, autoserializeAs, inheritSerialization } from 'cerialize';
|
||||||
|
import { BitstreamFormat } from '../../shared/bitstream-format.model';
|
||||||
|
|
||||||
|
import { mapsTo } from '../builders/build-decorators';
|
||||||
|
import { IDToUUIDSerializer } from '../id-to-uuid-serializer';
|
||||||
|
import { NormalizedObject } from './normalized-object.model';
|
||||||
|
import { SupportLevel } from './support-level.model';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Normalized model class for a Bitstream Format
|
||||||
|
*/
|
||||||
|
@mapsTo(BitstreamFormat)
|
||||||
|
@inheritSerialization(NormalizedObject)
|
||||||
|
export class NormalizedBitstreamFormat extends NormalizedObject {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Short description of this Bitstream Format
|
||||||
|
*/
|
||||||
|
@autoserialize
|
||||||
|
shortDescription: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Description of this Bitstream Format
|
||||||
|
*/
|
||||||
|
@autoserialize
|
||||||
|
description: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* String representing the MIME type of this Bitstream Format
|
||||||
|
*/
|
||||||
|
@autoserialize
|
||||||
|
mimetype: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The level of support the system offers for this Bitstream Format
|
||||||
|
*/
|
||||||
|
@autoserialize
|
||||||
|
supportLevel: SupportLevel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* True if the Bitstream Format is used to store system information, rather than the content of items in the system
|
||||||
|
*/
|
||||||
|
@autoserialize
|
||||||
|
internal: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* String representing this Bitstream Format's file extension
|
||||||
|
*/
|
||||||
|
@autoserialize
|
||||||
|
extensions: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Identifier for this Bitstream Format
|
||||||
|
* Note that this ID is unique for bitstream formats,
|
||||||
|
* but might not be unique across different object types
|
||||||
|
*/
|
||||||
|
@autoserialize
|
||||||
|
id: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Universally unique identifier for this Bitstream Format
|
||||||
|
* Consist of a prefix and the id field to ensure the identifier is unique across all object types
|
||||||
|
*/
|
||||||
|
@autoserializeAs(new IDToUUIDSerializer('bitstream-format'), 'id')
|
||||||
|
uuid: string;
|
||||||
|
}
|
@@ -5,6 +5,9 @@ import { Bitstream } from '../../shared/bitstream.model';
|
|||||||
import { mapsTo, relationship } from '../builders/build-decorators';
|
import { mapsTo, relationship } from '../builders/build-decorators';
|
||||||
import { ResourceType } from '../../shared/resource-type';
|
import { ResourceType } from '../../shared/resource-type';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Normalized model class for a DSpace Bitstream
|
||||||
|
*/
|
||||||
@mapsTo(Bitstream)
|
@mapsTo(Bitstream)
|
||||||
@inheritSerialization(NormalizedDSpaceObject)
|
@inheritSerialization(NormalizedDSpaceObject)
|
||||||
export class NormalizedBitstream extends NormalizedDSpaceObject {
|
export class NormalizedBitstream extends NormalizedDSpaceObject {
|
||||||
|
@@ -5,6 +5,9 @@ import { Bundle } from '../../shared/bundle.model';
|
|||||||
import { mapsTo, relationship } from '../builders/build-decorators';
|
import { mapsTo, relationship } from '../builders/build-decorators';
|
||||||
import { ResourceType } from '../../shared/resource-type';
|
import { ResourceType } from '../../shared/resource-type';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Normalized model class for a DSpace Bundle
|
||||||
|
*/
|
||||||
@mapsTo(Bundle)
|
@mapsTo(Bundle)
|
||||||
@inheritSerialization(NormalizedDSpaceObject)
|
@inheritSerialization(NormalizedDSpaceObject)
|
||||||
export class NormalizedBundle extends NormalizedDSpaceObject {
|
export class NormalizedBundle extends NormalizedDSpaceObject {
|
||||||
@@ -25,6 +28,9 @@ export class NormalizedBundle extends NormalizedDSpaceObject {
|
|||||||
*/
|
*/
|
||||||
owner: string;
|
owner: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of Bitstreams that are part of this Bundle
|
||||||
|
*/
|
||||||
@autoserialize
|
@autoserialize
|
||||||
@relationship(ResourceType.Bitstream, true)
|
@relationship(ResourceType.Bitstream, true)
|
||||||
bitstreams: string[];
|
bitstreams: string[];
|
||||||
|
@@ -1,10 +1,13 @@
|
|||||||
import { autoserialize, inheritSerialization, autoserializeAs } from 'cerialize';
|
import { autoserialize, inheritSerialization } from 'cerialize';
|
||||||
|
|
||||||
import { NormalizedDSpaceObject } from './normalized-dspace-object.model';
|
import { NormalizedDSpaceObject } from './normalized-dspace-object.model';
|
||||||
import { Collection } from '../../shared/collection.model';
|
import { Collection } from '../../shared/collection.model';
|
||||||
import { mapsTo, relationship } from '../builders/build-decorators';
|
import { mapsTo, relationship } from '../builders/build-decorators';
|
||||||
import { ResourceType } from '../../shared/resource-type';
|
import { ResourceType } from '../../shared/resource-type';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Normalized model class for a DSpace Collection
|
||||||
|
*/
|
||||||
@mapsTo(Collection)
|
@mapsTo(Collection)
|
||||||
@inheritSerialization(NormalizedDSpaceObject)
|
@inheritSerialization(NormalizedDSpaceObject)
|
||||||
export class NormalizedCollection extends NormalizedDSpaceObject {
|
export class NormalizedCollection extends NormalizedDSpaceObject {
|
||||||
@@ -36,6 +39,9 @@ export class NormalizedCollection extends NormalizedDSpaceObject {
|
|||||||
@relationship(ResourceType.Community, false)
|
@relationship(ResourceType.Community, false)
|
||||||
owner: string;
|
owner: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of Items that are part of (not necessarily owned by) this Collection
|
||||||
|
*/
|
||||||
@autoserialize
|
@autoserialize
|
||||||
@relationship(ResourceType.Item, true)
|
@relationship(ResourceType.Item, true)
|
||||||
items: string[];
|
items: string[];
|
||||||
|
@@ -1,10 +1,13 @@
|
|||||||
import { autoserialize, inheritSerialization, autoserializeAs } from 'cerialize';
|
import { autoserialize, inheritSerialization } from 'cerialize';
|
||||||
|
|
||||||
import { NormalizedDSpaceObject } from './normalized-dspace-object.model';
|
import { NormalizedDSpaceObject } from './normalized-dspace-object.model';
|
||||||
import { Community } from '../../shared/community.model';
|
import { Community } from '../../shared/community.model';
|
||||||
import { mapsTo, relationship } from '../builders/build-decorators';
|
import { mapsTo, relationship } from '../builders/build-decorators';
|
||||||
import { ResourceType } from '../../shared/resource-type';
|
import { ResourceType } from '../../shared/resource-type';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Normalized model class for a DSpace Community
|
||||||
|
*/
|
||||||
@mapsTo(Community)
|
@mapsTo(Community)
|
||||||
@inheritSerialization(NormalizedDSpaceObject)
|
@inheritSerialization(NormalizedDSpaceObject)
|
||||||
export class NormalizedCommunity extends NormalizedDSpaceObject {
|
export class NormalizedCommunity extends NormalizedDSpaceObject {
|
||||||
@@ -36,6 +39,9 @@ export class NormalizedCommunity extends NormalizedDSpaceObject {
|
|||||||
@relationship(ResourceType.Community, false)
|
@relationship(ResourceType.Community, false)
|
||||||
owner: string;
|
owner: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of Collections that are owned by this Community
|
||||||
|
*/
|
||||||
@autoserialize
|
@autoserialize
|
||||||
@relationship(ResourceType.Collection, true)
|
@relationship(ResourceType.Collection, true)
|
||||||
collections: string[];
|
collections: string[];
|
||||||
|
@@ -5,6 +5,9 @@ import { Item } from '../../shared/item.model';
|
|||||||
import { mapsTo, relationship } from '../builders/build-decorators';
|
import { mapsTo, relationship } from '../builders/build-decorators';
|
||||||
import { ResourceType } from '../../shared/resource-type';
|
import { ResourceType } from '../../shared/resource-type';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Normalized model class for a DSpace Item
|
||||||
|
*/
|
||||||
@mapsTo(Item)
|
@mapsTo(Item)
|
||||||
@inheritSerialization(NormalizedDSpaceObject)
|
@inheritSerialization(NormalizedDSpaceObject)
|
||||||
export class NormalizedItem extends NormalizedDSpaceObject {
|
export class NormalizedItem extends NormalizedDSpaceObject {
|
||||||
@@ -49,9 +52,13 @@ export class NormalizedItem extends NormalizedDSpaceObject {
|
|||||||
/**
|
/**
|
||||||
* The Collection that owns this Item
|
* The Collection that owns this Item
|
||||||
*/
|
*/
|
||||||
|
@autoserialize
|
||||||
@relationship(ResourceType.Collection, false)
|
@relationship(ResourceType.Collection, false)
|
||||||
owningCollection: string;
|
owningCollection: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of Bitstreams that are owned by this Item
|
||||||
|
*/
|
||||||
@autoserialize
|
@autoserialize
|
||||||
@relationship(ResourceType.Bitstream, true)
|
@relationship(ResourceType.Bitstream, true)
|
||||||
bitstreams: string[];
|
bitstreams: string[];
|
||||||
|
@@ -6,6 +6,8 @@ import { GenericConstructor } from '../../shared/generic-constructor';
|
|||||||
import { NormalizedCommunity } from './normalized-community.model';
|
import { NormalizedCommunity } from './normalized-community.model';
|
||||||
import { ResourceType } from '../../shared/resource-type';
|
import { ResourceType } from '../../shared/resource-type';
|
||||||
import { NormalizedObject } from './normalized-object.model';
|
import { NormalizedObject } from './normalized-object.model';
|
||||||
|
import { NormalizedBitstreamFormat } from './normalized-bitstream-format.model';
|
||||||
|
import { NormalizedResourcePolicy } from './normalized-resource-policy.model';
|
||||||
|
|
||||||
export class NormalizedObjectFactory {
|
export class NormalizedObjectFactory {
|
||||||
public static getConstructor(type: ResourceType): GenericConstructor<NormalizedObject> {
|
public static getConstructor(type: ResourceType): GenericConstructor<NormalizedObject> {
|
||||||
@@ -25,6 +27,12 @@ export class NormalizedObjectFactory {
|
|||||||
case ResourceType.Community: {
|
case ResourceType.Community: {
|
||||||
return NormalizedCommunity
|
return NormalizedCommunity
|
||||||
}
|
}
|
||||||
|
case ResourceType.BitstreamFormat: {
|
||||||
|
return NormalizedBitstreamFormat
|
||||||
|
}
|
||||||
|
case ResourceType.ResourcePolicy: {
|
||||||
|
return NormalizedResourcePolicy
|
||||||
|
}
|
||||||
default: {
|
default: {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
49
src/app/core/cache/models/normalized-resource-policy.model.ts
vendored
Normal file
49
src/app/core/cache/models/normalized-resource-policy.model.ts
vendored
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
import { autoserialize, autoserializeAs, inheritSerialization } from 'cerialize';
|
||||||
|
import { ResourcePolicy } from '../../shared/resource-policy.model';
|
||||||
|
|
||||||
|
import { mapsTo, relationship } from '../builders/build-decorators';
|
||||||
|
import { NormalizedObject } from './normalized-object.model';
|
||||||
|
import { IDToUUIDSerializer } from '../id-to-uuid-serializer';
|
||||||
|
import { ResourceType } from '../../shared/resource-type';
|
||||||
|
import { ActionType } from './action-type.model';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Normalized model class for a Resource Policy
|
||||||
|
*/
|
||||||
|
@mapsTo(ResourcePolicy)
|
||||||
|
@inheritSerialization(NormalizedObject)
|
||||||
|
export class NormalizedResourcePolicy extends NormalizedObject {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The action that is allowed by this Resource Policy
|
||||||
|
*/
|
||||||
|
action: ActionType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name for this Resource Policy
|
||||||
|
*/
|
||||||
|
@autoserialize
|
||||||
|
name: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The uuid of the Group this Resource Policy applies to
|
||||||
|
*/
|
||||||
|
@relationship(ResourceType.Group, false)
|
||||||
|
@autoserializeAs(String, 'groupUUID')
|
||||||
|
group: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Identifier for this Resource Policy
|
||||||
|
* Note that this ID is unique for resource policies,
|
||||||
|
* but might not be unique across different object types
|
||||||
|
*/
|
||||||
|
@autoserialize
|
||||||
|
id: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The universally unique identifier for this Resource Policy
|
||||||
|
* Consist of a prefix and the id field to ensure the identifier is unique across all object types
|
||||||
|
*/
|
||||||
|
@autoserializeAs(new IDToUUIDSerializer('resource-policy'), 'id')
|
||||||
|
uuid: string;
|
||||||
|
}
|
19
src/app/core/cache/models/support-level.model.ts
vendored
Normal file
19
src/app/core/cache/models/support-level.model.ts
vendored
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
/**
|
||||||
|
* Enum representing the Support Level of a Bitstream Format
|
||||||
|
*/
|
||||||
|
export enum SupportLevel {
|
||||||
|
/**
|
||||||
|
* Unknown for Bitstream Formats that are unknown to the system
|
||||||
|
*/
|
||||||
|
Unknown = 0,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unknown for Bitstream Formats that are known to the system, but not fully supported
|
||||||
|
*/
|
||||||
|
Known = 1,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Supported for Bitstream Formats that are known to the system and fully supported
|
||||||
|
*/
|
||||||
|
Supported = 2,
|
||||||
|
}
|
@@ -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]);
|
||||||
|
@@ -4,8 +4,9 @@ import { CacheableObject } from '../cache/object-cache.reducer';
|
|||||||
import { PageInfo } from '../shared/page-info.model';
|
import { PageInfo } from '../shared/page-info.model';
|
||||||
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';
|
||||||
import { NormalizedObject } from '../cache/models/normalized-object.model';
|
|
||||||
import { GenericConstructor } from '../shared/generic-constructor';
|
import { GenericConstructor } from '../shared/generic-constructor';
|
||||||
|
import { PaginatedList } from './paginated-list';
|
||||||
|
import { NormalizedObject } from '../cache/models/normalized-object.model';
|
||||||
|
|
||||||
function isObjectLevel(halObj: any) {
|
function isObjectLevel(halObj: any) {
|
||||||
return isNotEmpty(halObj._links) && hasValue(halObj._links.self);
|
return isNotEmpty(halObj._links) && hasValue(halObj._links.self);
|
||||||
@@ -17,96 +18,103 @@ function isPaginatedResponse(halObj: any) {
|
|||||||
|
|
||||||
/* tslint:disable:max-classes-per-file */
|
/* tslint:disable:max-classes-per-file */
|
||||||
|
|
||||||
class ProcessRequestDTO<ObjectDomain> {
|
|
||||||
[key: string]: ObjectDomain[]
|
|
||||||
}
|
|
||||||
|
|
||||||
export abstract class BaseResponseParsingService {
|
export abstract class BaseResponseParsingService {
|
||||||
protected abstract EnvConfig: GlobalConfig;
|
protected abstract EnvConfig: GlobalConfig;
|
||||||
protected abstract objectCache: ObjectCacheService;
|
protected abstract objectCache: ObjectCacheService;
|
||||||
protected abstract objectFactory: any;
|
protected abstract objectFactory: any;
|
||||||
protected abstract toCache: boolean;
|
protected abstract toCache: boolean;
|
||||||
|
|
||||||
protected process<ObjectDomain,ObjectType>(data: any, requestHref: string): ProcessRequestDTO<ObjectDomain> {
|
protected process<ObjectDomain, ObjectType>(data: any, requestHref: string): any {
|
||||||
|
|
||||||
if (isNotEmpty(data)) {
|
if (isNotEmpty(data)) {
|
||||||
if (isPaginatedResponse(data)) {
|
if (hasNoValue(data) || (typeof data !== 'object')) {
|
||||||
return this.process(data._embedded, requestHref);
|
return data;
|
||||||
|
} else if (isPaginatedResponse(data)) {
|
||||||
|
return this.processPaginatedList(data, requestHref);
|
||||||
|
} else if (Array.isArray(data)) {
|
||||||
|
return this.processArray(data, requestHref);
|
||||||
} else if (isObjectLevel(data)) {
|
} else if (isObjectLevel(data)) {
|
||||||
return { topLevel: this.deserializeAndCache(data, requestHref) };
|
const object = this.deserialize(data);
|
||||||
} else {
|
if (isNotEmpty(data._embedded)) {
|
||||||
const result = new ProcessRequestDTO<ObjectDomain>();
|
Object
|
||||||
if (Array.isArray(data)) {
|
.keys(data._embedded)
|
||||||
result.topLevel = [];
|
.filter((property) => data._embedded.hasOwnProperty(property))
|
||||||
data.forEach((datum) => {
|
|
||||||
if (isPaginatedResponse(datum)) {
|
|
||||||
const obj = this.process(datum, requestHref);
|
|
||||||
result.topLevel = [...result.topLevel, ...this.flattenSingleKeyObject(obj)];
|
|
||||||
} else {
|
|
||||||
result.topLevel = [...result.topLevel, ...this.deserializeAndCache<ObjectDomain,ObjectType>(datum, requestHref)];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
Object.keys(data)
|
|
||||||
.filter((property) => data.hasOwnProperty(property))
|
|
||||||
.filter((property) => hasValue(data[property]))
|
|
||||||
.forEach((property) => {
|
.forEach((property) => {
|
||||||
if (isPaginatedResponse(data[property])) {
|
const parsedObj = this.process<ObjectDomain, ObjectType>(data._embedded[property], requestHref);
|
||||||
const obj = this.process(data[property], requestHref);
|
if (isNotEmpty(parsedObj)) {
|
||||||
result[property] = this.flattenSingleKeyObject(obj);
|
if (isPaginatedResponse(data._embedded[property])) {
|
||||||
} else {
|
object[property] = parsedObj;
|
||||||
result[property] = this.deserializeAndCache(data[property], requestHref);
|
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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return result;
|
this.cache(object, requestHref);
|
||||||
|
return object;
|
||||||
}
|
}
|
||||||
|
const result = {};
|
||||||
|
Object.keys(data)
|
||||||
|
.filter((property) => data.hasOwnProperty(property))
|
||||||
|
.filter((property) => hasValue(data[property]))
|
||||||
|
.forEach((property) => {
|
||||||
|
const obj = this.process(data[property], requestHref);
|
||||||
|
result[property] = obj;
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected deserializeAndCache<ObjectDomain,ObjectType>(obj, requestHref: string): ObjectDomain[] {
|
protected processPaginatedList<ObjectDomain, ObjectType>(data: any, requestHref: string): PaginatedList<ObjectDomain> {
|
||||||
if (Array.isArray(obj)) {
|
const pageInfo: PageInfo = this.processPageInfo(data);
|
||||||
let result = [];
|
let list = data._embedded;
|
||||||
obj.forEach((o) => result = [...result, ...this.deserializeAndCache<ObjectDomain,ObjectType>(o, requestHref)]);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// Workaround for inconsistency in rest response. Issue: https://github.com/DSpace/dspace-angular/issues/238
|
||||||
|
if (!Array.isArray(list)) {
|
||||||
|
list = this.flattenSingleKeyObject(list);
|
||||||
|
}
|
||||||
|
const page: ObjectDomain[] = this.processArray(list, requestHref);
|
||||||
|
return new PaginatedList<ObjectDomain>(pageInfo, page);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected processArray<ObjectDomain, ObjectType>(data: any, requestHref: string): ObjectDomain[] {
|
||||||
|
let array: ObjectDomain[] = [];
|
||||||
|
data.forEach((datum) => {
|
||||||
|
array = [...array, this.process(datum, requestHref)];
|
||||||
|
}
|
||||||
|
);
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
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>;
|
||||||
|
|
||||||
if (hasValue(normObjConstructor)) {
|
if (hasValue(normObjConstructor)) {
|
||||||
const serializer = new DSpaceRESTv2Serializer(normObjConstructor);
|
const serializer = new DSpaceRESTv2Serializer(normObjConstructor);
|
||||||
|
const res = serializer.deserialize(obj);
|
||||||
let processed;
|
return res;
|
||||||
if (isNotEmpty(obj._embedded)) {
|
|
||||||
processed = this.process<ObjectDomain,ObjectType>(obj._embedded, requestHref);
|
|
||||||
}
|
|
||||||
const normalizedObj: any = serializer.deserialize(obj);
|
|
||||||
|
|
||||||
if (isNotEmpty(processed)) {
|
|
||||||
const processedList = {};
|
|
||||||
Object.keys(processed).forEach((key) => {
|
|
||||||
processedList[key] = processed[key].map((no: NormalizedObject) => (this.toCache) ? no.self : no);
|
|
||||||
});
|
|
||||||
Object.assign(normalizedObj, processedList);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.toCache) {
|
|
||||||
this.addToObjectCache(normalizedObj, requestHref);
|
|
||||||
}
|
|
||||||
return [normalizedObj] as any;
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// TODO: move check to Validator?
|
// TODO: move check to Validator?
|
||||||
// throw new Error(`The server returned an object with an unknown a known type: ${type}`);
|
// throw new Error(`The server returned an object with an unknown a known type: ${type}`);
|
||||||
return [];
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// TODO: move check to Validator
|
// TODO: move check to Validator
|
||||||
// throw new Error(`The server returned an object without a type: ${JSON.stringify(obj)}`);
|
// throw new Error(`The server returned an object without a type: ${JSON.stringify(obj)}`);
|
||||||
return [];
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected cache<ObjectDomain, ObjectType>(obj, requestHref) {
|
||||||
|
if (this.toCache) {
|
||||||
|
this.addToObjectCache(obj, requestHref);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -119,7 +127,7 @@ export abstract class BaseResponseParsingService {
|
|||||||
|
|
||||||
processPageInfo(payload: any): PageInfo {
|
processPageInfo(payload: any): PageInfo {
|
||||||
if (isNotEmpty(payload.page)) {
|
if (isNotEmpty(payload.page)) {
|
||||||
const pageObj = Object.assign({}, payload.page, {_links: payload._links});
|
const pageObj = Object.assign({}, payload.page, { _links: payload._links });
|
||||||
const pageInfoObject = new DSpaceRESTv2Serializer(PageInfo).deserialize(pageObj);
|
const pageInfoObject = new DSpaceRESTv2Serializer(PageInfo).deserialize(pageObj);
|
||||||
if (pageInfoObject.currentPage >= 0) {
|
if (pageInfoObject.currentPage >= 0) {
|
||||||
Object.assign(pageInfoObject, { currentPage: pageInfoObject.currentPage + 1 });
|
Object.assign(pageInfoObject, { currentPage: pageInfoObject.currentPage + 1 });
|
||||||
|
@@ -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,141 +16,143 @@ 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 = {
|
||||||
|
payload: {
|
||||||
|
id: 'traditional',
|
||||||
|
name: 'traditional',
|
||||||
|
type: 'submissiondefinition',
|
||||||
|
isDefault: true,
|
||||||
|
_links: {
|
||||||
|
sections: {
|
||||||
|
href: 'https://rest.api/config/submissiondefinitions/traditional/sections'
|
||||||
|
},
|
||||||
|
self: {
|
||||||
|
href: 'https://rest.api/config/submissiondefinitions/traditional'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_embedded: {
|
||||||
|
sections: {
|
||||||
|
page: {
|
||||||
|
number: 0,
|
||||||
|
size: 4,
|
||||||
|
totalPages: 1, totalElements: 4
|
||||||
|
},
|
||||||
|
_embedded: [
|
||||||
|
{
|
||||||
|
id: 'traditionalpageone', header: 'submit.progressbar.describe.stepone',
|
||||||
|
mandatory: true,
|
||||||
|
sectionType: 'submission-form',
|
||||||
|
visibility: {
|
||||||
|
main: null,
|
||||||
|
other: 'READONLY'
|
||||||
|
},
|
||||||
|
type: 'submissionsection',
|
||||||
|
_links: {
|
||||||
|
self: {
|
||||||
|
href: 'https://rest.api/config/submissionsections/traditionalpageone'
|
||||||
|
},
|
||||||
|
config: {
|
||||||
|
href: 'https://rest.api/config/submissionforms/traditionalpageone'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
id: 'traditionalpagetwo',
|
||||||
|
header: 'submit.progressbar.describe.steptwo',
|
||||||
|
mandatory: true,
|
||||||
|
sectionType: 'submission-form',
|
||||||
|
visibility: {
|
||||||
|
main: null,
|
||||||
|
other: 'READONLY'
|
||||||
|
},
|
||||||
|
type: 'submissionsection',
|
||||||
|
_links: {
|
||||||
|
self: {
|
||||||
|
href: 'https://rest.api/config/submissionsections/traditionalpagetwo'
|
||||||
|
},
|
||||||
|
config: {
|
||||||
|
href: 'https://rest.api/config/submissionforms/traditionalpagetwo'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
id: 'upload',
|
||||||
|
header: 'submit.progressbar.upload',
|
||||||
|
mandatory: false,
|
||||||
|
sectionType: 'upload',
|
||||||
|
visibility: {
|
||||||
|
main: null,
|
||||||
|
other: 'READONLY'
|
||||||
|
},
|
||||||
|
type: 'submissionsection',
|
||||||
|
_links: {
|
||||||
|
self: {
|
||||||
|
href: 'https://rest.api/config/submissionsections/upload'
|
||||||
|
},
|
||||||
|
config: {
|
||||||
|
href: 'https://rest.api/config/submissionuploads/upload'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
id: 'license',
|
||||||
|
header: 'submit.progressbar.license',
|
||||||
|
mandatory: true,
|
||||||
|
sectionType: 'license',
|
||||||
|
visibility: {
|
||||||
|
main: null,
|
||||||
|
other: 'READONLY'
|
||||||
|
},
|
||||||
|
type: 'submissionsection',
|
||||||
|
_links: {
|
||||||
|
self: {
|
||||||
|
href: 'https://rest.api/config/submissionsections/license'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
_links: {
|
||||||
|
self: {
|
||||||
|
href: 'https://rest.api/config/submissiondefinitions/traditional/sections'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
statusCode: '200'
|
||||||
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('parse', () => {
|
describe('parse', () => {
|
||||||
const validRequest = new ConfigRequest('69f375b5-19f4-4453-8c7a-7dc5c55aafbb', 'https://rest.api/config/submissiondefinitions/traditional');
|
const validRequest = new ConfigRequest('69f375b5-19f4-4453-8c7a-7dc5c55aafbb', 'https://rest.api/config/submissiondefinitions/traditional');
|
||||||
|
|
||||||
const validResponse = {
|
|
||||||
payload: {
|
|
||||||
id:'traditional',
|
|
||||||
name:'traditional',
|
|
||||||
type:'submissiondefinition',
|
|
||||||
isDefault:true,
|
|
||||||
_links:{
|
|
||||||
sections:{
|
|
||||||
href:'https://rest.api/config/submissiondefinitions/traditional/sections'
|
|
||||||
},self:{
|
|
||||||
href:'https://rest.api/config/submissiondefinitions/traditional'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
_embedded:{
|
|
||||||
sections:{
|
|
||||||
page:{
|
|
||||||
number:0,
|
|
||||||
size:4,
|
|
||||||
totalPages:1,totalElements:4
|
|
||||||
},
|
|
||||||
_embedded:[
|
|
||||||
{
|
|
||||||
id:'traditionalpageone',header:'submit.progressbar.describe.stepone',
|
|
||||||
mandatory:true,
|
|
||||||
sectionType:'submission-form',
|
|
||||||
visibility:{
|
|
||||||
main:null,
|
|
||||||
other:'READONLY'
|
|
||||||
},
|
|
||||||
type:'submissionsection',
|
|
||||||
_links:{
|
|
||||||
self:{
|
|
||||||
href:'https://rest.api/config/submissionsections/traditionalpageone'
|
|
||||||
},
|
|
||||||
config:{
|
|
||||||
href:'https://rest.api/config/submissionforms/traditionalpageone'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
id:'traditionalpagetwo',
|
|
||||||
header:'submit.progressbar.describe.steptwo',
|
|
||||||
mandatory:true,
|
|
||||||
sectionType:'submission-form',
|
|
||||||
visibility:{
|
|
||||||
main:null,
|
|
||||||
other:'READONLY'
|
|
||||||
},
|
|
||||||
type:'submissionsection',
|
|
||||||
_links:{
|
|
||||||
self:{
|
|
||||||
href:'https://rest.api/config/submissionsections/traditionalpagetwo'
|
|
||||||
},
|
|
||||||
config:{
|
|
||||||
href:'https://rest.api/config/submissionforms/traditionalpagetwo'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
id:'upload',
|
|
||||||
header:'submit.progressbar.upload',
|
|
||||||
mandatory:false,
|
|
||||||
sectionType:'upload',
|
|
||||||
visibility:{
|
|
||||||
main:null,
|
|
||||||
other:'READONLY'
|
|
||||||
},
|
|
||||||
type:'submissionsection',
|
|
||||||
_links:{
|
|
||||||
self:{
|
|
||||||
href:'https://rest.api/config/submissionsections/upload'
|
|
||||||
},
|
|
||||||
config: {
|
|
||||||
href:'https://rest.api/config/submissionuploads/upload'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
id:'license',
|
|
||||||
header:'submit.progressbar.license',
|
|
||||||
mandatory:true,
|
|
||||||
sectionType:'license',
|
|
||||||
visibility:{
|
|
||||||
main:null,
|
|
||||||
other:'READONLY'
|
|
||||||
},
|
|
||||||
type:'submissionsection',
|
|
||||||
_links:{
|
|
||||||
self:{
|
|
||||||
href:'https://rest.api/config/submissionsections/license'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
_links:{
|
|
||||||
self:'https://rest.api/config/submissiondefinitions/traditional/sections'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
statusCode:'200'
|
|
||||||
};
|
|
||||||
|
|
||||||
const invalidResponse1 = {
|
const invalidResponse1 = {
|
||||||
payload: {},
|
payload: {},
|
||||||
statusCode:'200'
|
statusCode: '200'
|
||||||
};
|
};
|
||||||
|
|
||||||
const invalidResponse2 = {
|
const invalidResponse2 = {
|
||||||
payload: {
|
payload: {
|
||||||
id:'traditional',
|
id: 'traditional',
|
||||||
name:'traditional',
|
name: 'traditional',
|
||||||
type:'submissiondefinition',
|
type: 'submissiondefinition',
|
||||||
isDefault:true,
|
isDefault: true,
|
||||||
_links:{},
|
_links: {},
|
||||||
_embedded:{
|
_embedded: {
|
||||||
sections:{
|
sections: {
|
||||||
page:{
|
page: {
|
||||||
number:0,
|
number: 0,
|
||||||
size:4,
|
size: 4,
|
||||||
totalPages:1,totalElements:4
|
totalPages: 1, totalElements: 4
|
||||||
},
|
},
|
||||||
_embedded:[{},{}],
|
_embedded: [{}, {}],
|
||||||
_links:{
|
_links: {
|
||||||
self:'https://rest.api/config/submissiondefinitions/traditional/sections'
|
self: 'https://rest.api/config/submissiondefinitions/traditional/sections'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
statusCode:'200'
|
statusCode: '200'
|
||||||
};
|
};
|
||||||
|
|
||||||
const invalidResponse3 = {
|
const invalidResponse3 = {
|
||||||
@@ -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,
|
self: 'https://rest.api/config/submissiondefinitions/traditional',
|
||||||
sectionType: 'submission-form',
|
sections: new PaginatedList(pageinfo, [
|
||||||
visibility:{
|
'https://rest.api/config/submissionsections/traditionalpageone',
|
||||||
main:null,
|
'https://rest.api/config/submissionsections/traditionalpagetwo',
|
||||||
other:'READONLY'
|
'https://rest.api/config/submissionsections/upload',
|
||||||
},
|
'https://rest.api/config/submissionsections/license'
|
||||||
type: 'submissionsection',
|
])
|
||||||
_links: {}
|
});
|
||||||
}),
|
|
||||||
Object.assign(new SubmissionSectionModel(), {
|
|
||||||
header: 'submit.progressbar.describe.steptwo',
|
|
||||||
mandatory: true,
|
|
||||||
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);
|
||||||
|
@@ -29,7 +29,7 @@ export class ConfigResponseParsingService extends BaseResponseParsingService imp
|
|||||||
parse(request: RestRequest, data: DSpaceRESTV2Response): RestResponse {
|
parse(request: RestRequest, data: DSpaceRESTV2Response): RestResponse {
|
||||||
if (isNotEmpty(data.payload) && isNotEmpty(data.payload._links) && (data.statusCode === '201' || data.statusCode === '200' || data.statusCode === 'OK')) {
|
if (isNotEmpty(data.payload) && isNotEmpty(data.payload._links) && (data.statusCode === '201' || data.statusCode === '200' || data.statusCode === 'OK')) {
|
||||||
const configDefinition = this.process<ConfigObject,ConfigType>(data.payload, request.href);
|
const configDefinition = this.process<ConfigObject,ConfigType>(data.payload, request.href);
|
||||||
return new ConfigSuccessResponse(configDefinition[Object.keys(configDefinition)[0]], data.statusCode, this.processPageInfo(data.payload));
|
return new ConfigSuccessResponse(configDefinition, data.statusCode, this.processPageInfo(data.payload));
|
||||||
} else {
|
} else {
|
||||||
return new ErrorResponse(
|
return new ErrorResponse(
|
||||||
Object.assign(
|
Object.assign(
|
||||||
|
@@ -12,6 +12,7 @@ import { RestRequest } from './request.models';
|
|||||||
|
|
||||||
import { ResponseParsingService } from './parsing.service';
|
import { ResponseParsingService } from './parsing.service';
|
||||||
import { BaseResponseParsingService } from './base-response-parsing.service';
|
import { BaseResponseParsingService } from './base-response-parsing.service';
|
||||||
|
import { hasNoValue, hasValue } from '../../shared/empty.util';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class DSOResponseParsingService extends BaseResponseParsingService implements ResponseParsingService {
|
export class DSOResponseParsingService extends BaseResponseParsingService implements ResponseParsingService {
|
||||||
@@ -27,7 +28,16 @@ export class DSOResponseParsingService extends BaseResponseParsingService implem
|
|||||||
|
|
||||||
parse(request: RestRequest, data: DSpaceRESTV2Response): RestResponse {
|
parse(request: RestRequest, data: DSpaceRESTV2Response): RestResponse {
|
||||||
const processRequestDTO = this.process<NormalizedObject,ResourceType>(data.payload, request.href);
|
const processRequestDTO = this.process<NormalizedObject,ResourceType>(data.payload, request.href);
|
||||||
const selfLinks = this.flattenSingleKeyObject(processRequestDTO).map((no) => no.self);
|
let objectList = processRequestDTO;
|
||||||
|
if (hasNoValue(processRequestDTO)) {
|
||||||
|
return new DSOSuccessResponse([], data.statusCode, undefined)
|
||||||
|
}
|
||||||
|
if (hasValue(processRequestDTO.page)) {
|
||||||
|
objectList = processRequestDTO.page;
|
||||||
|
} else if (!Array.isArray(processRequestDTO)) {
|
||||||
|
objectList = [processRequestDTO];
|
||||||
|
}
|
||||||
|
const selfLinks = objectList.map((no) => no.self);
|
||||||
return new DSOSuccessResponse(selfLinks, data.statusCode, this.processPageInfo(data.payload))
|
return new DSOSuccessResponse(selfLinks, data.statusCode, this.processPageInfo(data.payload))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -8,6 +8,8 @@ import { CoreState } from '../core.reducers';
|
|||||||
import { IntegrationResponseParsingService } from './integration-response-parsing.service';
|
import { IntegrationResponseParsingService } from './integration-response-parsing.service';
|
||||||
import { IntegrationRequest } from '../data/request.models';
|
import { IntegrationRequest } from '../data/request.models';
|
||||||
import { AuthorityValueModel } from './models/authority-value.model';
|
import { AuthorityValueModel } from './models/authority-value.model';
|
||||||
|
import { PageInfo } from '../shared/page-info.model';
|
||||||
|
import { PaginatedList } from '../data/paginated-list';
|
||||||
|
|
||||||
describe('IntegrationResponseParsingService', () => {
|
describe('IntegrationResponseParsingService', () => {
|
||||||
let service: IntegrationResponseParsingService;
|
let service: IntegrationResponseParsingService;
|
||||||
@@ -78,7 +80,7 @@ describe('IntegrationResponseParsingService', () => {
|
|||||||
|
|
||||||
},
|
},
|
||||||
_links: {
|
_links: {
|
||||||
self: 'https://rest.api/integration/authorities/type/entries'
|
self: { href: 'https://rest.api/integration/authorities/type/entries' }
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
statusCode: '200'
|
statusCode: '200'
|
||||||
@@ -141,39 +143,44 @@ describe('IntegrationResponseParsingService', () => {
|
|||||||
},
|
},
|
||||||
statusCode: '200'
|
statusCode: '200'
|
||||||
};
|
};
|
||||||
|
const pageinfo = Object.assign(new PageInfo(), { elementsPerPage: 5, totalElements: 5, totalPages: 1, currentPage: 1 });
|
||||||
const definitions = [
|
const definitions = new PaginatedList(pageinfo,[
|
||||||
Object.assign(new AuthorityValueModel(), {
|
Object.assign({}, new AuthorityValueModel(), {
|
||||||
|
type: 'authority',
|
||||||
display: 'One',
|
display: 'One',
|
||||||
id: 'One',
|
id: 'One',
|
||||||
otherInformation: {},
|
otherInformation: undefined,
|
||||||
value: 'One'
|
value: 'One'
|
||||||
}),
|
}),
|
||||||
Object.assign(new AuthorityValueModel(), {
|
Object.assign({}, new AuthorityValueModel(), {
|
||||||
|
type: 'authority',
|
||||||
display: 'Two',
|
display: 'Two',
|
||||||
id: 'Two',
|
id: 'Two',
|
||||||
otherInformation: {},
|
otherInformation: undefined,
|
||||||
value: 'Two'
|
value: 'Two'
|
||||||
}),
|
}),
|
||||||
Object.assign(new AuthorityValueModel(), {
|
Object.assign({}, new AuthorityValueModel(), {
|
||||||
|
type: 'authority',
|
||||||
display: 'Three',
|
display: 'Three',
|
||||||
id: 'Three',
|
id: 'Three',
|
||||||
otherInformation: {},
|
otherInformation: undefined,
|
||||||
value: 'Three'
|
value: 'Three'
|
||||||
}),
|
}),
|
||||||
Object.assign(new AuthorityValueModel(), {
|
Object.assign({}, new AuthorityValueModel(), {
|
||||||
|
type: 'authority',
|
||||||
display: 'Four',
|
display: 'Four',
|
||||||
id: 'Four',
|
id: 'Four',
|
||||||
otherInformation: {},
|
otherInformation: undefined,
|
||||||
value: 'Four'
|
value: 'Four'
|
||||||
}),
|
}),
|
||||||
Object.assign(new AuthorityValueModel(), {
|
Object.assign({}, new AuthorityValueModel(), {
|
||||||
|
type: 'authority',
|
||||||
display: 'Five',
|
display: 'Five',
|
||||||
id: 'Five',
|
id: 'Five',
|
||||||
otherInformation: {},
|
otherInformation: undefined,
|
||||||
value: 'Five'
|
value: 'Five'
|
||||||
})
|
})
|
||||||
];
|
]);
|
||||||
|
|
||||||
it('should return a IntegrationSuccessResponse if data contains a valid endpoint response', () => {
|
it('should return a IntegrationSuccessResponse if data contains a valid endpoint response', () => {
|
||||||
const response = service.parse(validRequest, validResponse);
|
const response = service.parse(validRequest, validResponse);
|
||||||
|
@@ -33,7 +33,7 @@ export class IntegrationResponseParsingService extends BaseResponseParsingServic
|
|||||||
parse(request: RestRequest, data: DSpaceRESTV2Response): RestResponse {
|
parse(request: RestRequest, data: DSpaceRESTV2Response): RestResponse {
|
||||||
if (isNotEmpty(data.payload) && isNotEmpty(data.payload._links)) {
|
if (isNotEmpty(data.payload) && isNotEmpty(data.payload._links)) {
|
||||||
const dataDefinition = this.process<IntegrationModel,IntegrationType>(data.payload, request.href);
|
const dataDefinition = this.process<IntegrationModel,IntegrationType>(data.payload, request.href);
|
||||||
return new IntegrationSuccessResponse(dataDefinition[Object.keys(dataDefinition)[0]], data.statusCode, this.processPageInfo(data.payload.page));
|
return new IntegrationSuccessResponse(dataDefinition, data.statusCode, this.processPageInfo(data.payload.page));
|
||||||
} else {
|
} else {
|
||||||
return new ErrorResponse(
|
return new ErrorResponse(
|
||||||
Object.assign(
|
Object.assign(
|
||||||
|
@@ -1,24 +1,55 @@
|
|||||||
|
|
||||||
import { autoserialize } from 'cerialize';
|
import { CacheableObject } from '../cache/object-cache.reducer';
|
||||||
|
import { ResourceType } from './resource-type';
|
||||||
|
|
||||||
export class BitstreamFormat {
|
/**
|
||||||
|
* Model class for a Bitstream Format
|
||||||
|
*/
|
||||||
|
export class BitstreamFormat implements CacheableObject {
|
||||||
|
|
||||||
@autoserialize
|
/**
|
||||||
|
* Short description of this Bitstream Format
|
||||||
|
*/
|
||||||
shortDescription: string;
|
shortDescription: string;
|
||||||
|
|
||||||
@autoserialize
|
/**
|
||||||
|
* Description of this Bitstream Format
|
||||||
|
*/
|
||||||
description: string;
|
description: string;
|
||||||
|
|
||||||
@autoserialize
|
/**
|
||||||
|
* String representing the MIME type of this Bitstream Format
|
||||||
|
*/
|
||||||
mimetype: string;
|
mimetype: string;
|
||||||
|
|
||||||
@autoserialize
|
/**
|
||||||
|
* The level of support the system offers for this Bitstream Format
|
||||||
|
*/
|
||||||
supportLevel: number;
|
supportLevel: number;
|
||||||
|
|
||||||
@autoserialize
|
/**
|
||||||
|
* True if the Bitstream Format is used to store system information, rather than the content of items in the system
|
||||||
|
*/
|
||||||
internal: boolean;
|
internal: boolean;
|
||||||
|
|
||||||
@autoserialize
|
/**
|
||||||
|
* String representing this Bitstream Format's file extension
|
||||||
|
*/
|
||||||
extensions: string;
|
extensions: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The link to the rest endpoint where this Bitstream Format can be found
|
||||||
|
*/
|
||||||
|
self: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A ResourceType representing the kind of Object of this BitstreamFormat
|
||||||
|
*/
|
||||||
|
type: ResourceType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Universally unique identifier for this Bitstream Format
|
||||||
|
*/
|
||||||
|
uuid: string;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -3,6 +3,7 @@ import { Bitstream } from './bitstream.model';
|
|||||||
import { Collection } from './collection.model';
|
import { Collection } from './collection.model';
|
||||||
import { RemoteData } from '../data/remote-data';
|
import { RemoteData } from '../data/remote-data';
|
||||||
import { Observable } from 'rxjs/Observable';
|
import { Observable } from 'rxjs/Observable';
|
||||||
|
import { PaginatedList } from '../data/paginated-list';
|
||||||
|
|
||||||
export class Community extends DSpaceObject {
|
export class Community extends DSpaceObject {
|
||||||
|
|
||||||
@@ -58,6 +59,6 @@ export class Community extends DSpaceObject {
|
|||||||
*/
|
*/
|
||||||
owner: Observable<RemoteData<Community>>;
|
owner: Observable<RemoteData<Community>>;
|
||||||
|
|
||||||
collections: Observable<RemoteData<Collection[]>>;
|
collections: Observable<RemoteData<PaginatedList<Collection>>>;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
import { autoserialize, autoserializeAs, inheritSerialization } from 'cerialize';
|
import { autoserialize, autoserializeAs, inheritSerialization } from 'cerialize';
|
||||||
import { ConfigObject } from './config.model';
|
import { ConfigObject } from './config.model';
|
||||||
import { SubmissionSectionModel } from './config-submission-section.model';
|
import { SubmissionSectionModel } from './config-submission-section.model';
|
||||||
|
import { PaginatedList } from '../../data/paginated-list';
|
||||||
|
|
||||||
@inheritSerialization(ConfigObject)
|
@inheritSerialization(ConfigObject)
|
||||||
export class SubmissionDefinitionsModel extends ConfigObject {
|
export class SubmissionDefinitionsModel extends ConfigObject {
|
||||||
@@ -9,6 +10,6 @@ export class SubmissionDefinitionsModel extends ConfigObject {
|
|||||||
isDefault: boolean;
|
isDefault: boolean;
|
||||||
|
|
||||||
@autoserializeAs(SubmissionSectionModel)
|
@autoserializeAs(SubmissionSectionModel)
|
||||||
sections: SubmissionSectionModel[];
|
sections: PaginatedList<SubmissionSectionModel>;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -5,6 +5,7 @@ import { Collection } from './collection.model';
|
|||||||
import { RemoteData } from '../data/remote-data';
|
import { RemoteData } from '../data/remote-data';
|
||||||
import { Bitstream } from './bitstream.model';
|
import { Bitstream } from './bitstream.model';
|
||||||
import { hasValue, isNotEmpty } from '../../shared/empty.util';
|
import { hasValue, isNotEmpty } from '../../shared/empty.util';
|
||||||
|
import { PaginatedList } from '../data/paginated-list';
|
||||||
|
|
||||||
export class Item extends DSpaceObject {
|
export class Item extends DSpaceObject {
|
||||||
|
|
||||||
@@ -47,7 +48,7 @@ export class Item extends DSpaceObject {
|
|||||||
return this.owningCollection;
|
return this.owningCollection;
|
||||||
}
|
}
|
||||||
|
|
||||||
bitstreams: Observable<RemoteData<Bitstream[]>>;
|
bitstreams: Observable<RemoteData<PaginatedList<Bitstream>>>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the thumbnail of this item
|
* Retrieves the thumbnail of this item
|
||||||
@@ -88,7 +89,7 @@ export class Item extends DSpaceObject {
|
|||||||
*/
|
*/
|
||||||
getBitstreamsByBundleName(bundleName: string): Observable<Bitstream[]> {
|
getBitstreamsByBundleName(bundleName: string): Observable<Bitstream[]> {
|
||||||
return this.bitstreams
|
return this.bitstreams
|
||||||
.map((rd: RemoteData<Bitstream[]>) => rd.payload)
|
.map((rd: RemoteData<PaginatedList<Bitstream>>) => rd.payload.page)
|
||||||
.filter((bitstreams: Bitstream[]) => hasValue(bitstreams))
|
.filter((bitstreams: Bitstream[]) => hasValue(bitstreams))
|
||||||
.startWith([])
|
.startWith([])
|
||||||
.map((bitstreams) => {
|
.map((bitstreams) => {
|
||||||
|
40
src/app/core/shared/resource-policy.model.ts
Normal file
40
src/app/core/shared/resource-policy.model.ts
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
import { CacheableObject } from '../cache/object-cache.reducer';
|
||||||
|
import { ResourceType } from './resource-type';
|
||||||
|
import { Group } from '../eperson/models/group.model';
|
||||||
|
import { ActionType } from '../cache/models/action-type.model';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Model class for a Resource Policy
|
||||||
|
*/
|
||||||
|
export class ResourcePolicy implements CacheableObject {
|
||||||
|
/**
|
||||||
|
* The action that is allowed by this Resource Policy
|
||||||
|
*/
|
||||||
|
action: ActionType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name for this Resource Policy
|
||||||
|
*/
|
||||||
|
name: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Group this Resource Policy applies to
|
||||||
|
*/
|
||||||
|
group: Group;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The link to the rest endpoint where this Resource Policy can be found
|
||||||
|
*/
|
||||||
|
self: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A ResourceType representing the kind of Object of this ResourcePolicy
|
||||||
|
*/
|
||||||
|
type: ResourceType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The universally unique identifier for this Resource Policy
|
||||||
|
*/
|
||||||
|
uuid: string;
|
||||||
|
|
||||||
|
}
|
@@ -8,4 +8,5 @@ export enum ResourceType {
|
|||||||
Community = 'community',
|
Community = 'community',
|
||||||
Eperson = 'eperson',
|
Eperson = 'eperson',
|
||||||
Group = 'group',
|
Group = 'group',
|
||||||
|
ResourcePolicy = 'resourcePolicy'
|
||||||
}
|
}
|
||||||
|
@@ -17,78 +17,86 @@ export const MockItem: Item = Object.assign(new Item(), {
|
|||||||
errorMessage: '',
|
errorMessage: '',
|
||||||
statusCode: '202',
|
statusCode: '202',
|
||||||
pageInfo: {},
|
pageInfo: {},
|
||||||
payload: [
|
payload: {
|
||||||
{
|
pageInfo: {
|
||||||
sizeBytes: 10201,
|
elementsPerPage: 20,
|
||||||
content: 'https://dspace7.4science.it/dspace-spring-rest/api/core/bitstreams/cf9b0c8e-a1eb-4b65-afd0-567366448713/content',
|
totalElements: 3,
|
||||||
format: Observable.of({
|
totalPages: 1,
|
||||||
self: 'https://dspace7.4science.it/dspace-spring-rest/api/core/bitstreamformats/10',
|
currentPage: 2
|
||||||
requestPending: false,
|
|
||||||
responsePending: false,
|
|
||||||
isSuccessful: true,
|
|
||||||
errorMessage: '',
|
|
||||||
statusCode: '202',
|
|
||||||
pageInfo: {},
|
|
||||||
payload: {
|
|
||||||
shortDescription: 'Microsoft Word XML',
|
|
||||||
description: 'Microsoft Word XML',
|
|
||||||
mimetype: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
|
||||||
supportLevel: 0,
|
|
||||||
internal: false,
|
|
||||||
extensions: null,
|
|
||||||
self: 'https://dspace7.4science.it/dspace-spring-rest/api/core/bitstreamformats/10'
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
bundleName: 'ORIGINAL',
|
|
||||||
self: 'https://dspace7.4science.it/dspace-spring-rest/api/core/bitstreams/cf9b0c8e-a1eb-4b65-afd0-567366448713',
|
|
||||||
id: 'cf9b0c8e-a1eb-4b65-afd0-567366448713',
|
|
||||||
uuid: 'cf9b0c8e-a1eb-4b65-afd0-567366448713',
|
|
||||||
type: 'bitstream',
|
|
||||||
name: 'test_word.docx',
|
|
||||||
metadata: [
|
|
||||||
{
|
|
||||||
key: 'dc.title',
|
|
||||||
language: null,
|
|
||||||
value: 'test_word.docx'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
{
|
page: [
|
||||||
sizeBytes: 31302,
|
{
|
||||||
content: 'https://dspace7.4science.it/dspace-spring-rest/api/core/bitstreams/99b00f3c-1cc6-4689-8158-91965bee6b28/content',
|
sizeBytes: 10201,
|
||||||
format: Observable.of({
|
content: 'https://dspace7.4science.it/dspace-spring-rest/api/core/bitstreams/cf9b0c8e-a1eb-4b65-afd0-567366448713/content',
|
||||||
self: 'https://dspace7.4science.it/dspace-spring-rest/api/core/bitstreamformats/4',
|
format: Observable.of({
|
||||||
requestPending: false,
|
self: 'https://dspace7.4science.it/dspace-spring-rest/api/core/bitstreamformats/10',
|
||||||
responsePending: false,
|
requestPending: false,
|
||||||
isSuccessful: true,
|
responsePending: false,
|
||||||
errorMessage: '',
|
isSuccessful: true,
|
||||||
statusCode: '202',
|
errorMessage: '',
|
||||||
pageInfo: {},
|
statusCode: '202',
|
||||||
payload: {
|
pageInfo: {},
|
||||||
shortDescription: 'Adobe PDF',
|
payload: {
|
||||||
description: 'Adobe Portable Document Format',
|
shortDescription: 'Microsoft Word XML',
|
||||||
mimetype: 'application/pdf',
|
description: 'Microsoft Word XML',
|
||||||
supportLevel: 0,
|
mimetype: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
||||||
internal: false,
|
supportLevel: 0,
|
||||||
extensions: null,
|
internal: false,
|
||||||
self: 'https://dspace7.4science.it/dspace-spring-rest/api/core/bitstreamformats/4'
|
extensions: null,
|
||||||
}
|
self: 'https://dspace7.4science.it/dspace-spring-rest/api/core/bitstreamformats/10'
|
||||||
}),
|
}
|
||||||
bundleName: 'ORIGINAL',
|
}),
|
||||||
self: 'https://dspace7.4science.it/dspace-spring-rest/api/core/bitstreams/99b00f3c-1cc6-4689-8158-91965bee6b28',
|
bundleName: 'ORIGINAL',
|
||||||
id: '99b00f3c-1cc6-4689-8158-91965bee6b28',
|
self: 'https://dspace7.4science.it/dspace-spring-rest/api/core/bitstreams/cf9b0c8e-a1eb-4b65-afd0-567366448713',
|
||||||
uuid: '99b00f3c-1cc6-4689-8158-91965bee6b28',
|
id: 'cf9b0c8e-a1eb-4b65-afd0-567366448713',
|
||||||
type: 'bitstream',
|
uuid: 'cf9b0c8e-a1eb-4b65-afd0-567366448713',
|
||||||
name: 'test_pdf.pdf',
|
type: 'bitstream',
|
||||||
metadata: [
|
name: 'test_word.docx',
|
||||||
{
|
metadata: [
|
||||||
key: 'dc.title',
|
{
|
||||||
language: null,
|
key: 'dc.title',
|
||||||
value: 'test_pdf.pdf'
|
language: null,
|
||||||
}
|
value: 'test_word.docx'
|
||||||
]
|
}
|
||||||
}
|
]
|
||||||
]
|
},
|
||||||
|
{
|
||||||
|
sizeBytes: 31302,
|
||||||
|
content: 'https://dspace7.4science.it/dspace-spring-rest/api/core/bitstreams/99b00f3c-1cc6-4689-8158-91965bee6b28/content',
|
||||||
|
format: Observable.of({
|
||||||
|
self: 'https://dspace7.4science.it/dspace-spring-rest/api/core/bitstreamformats/4',
|
||||||
|
requestPending: false,
|
||||||
|
responsePending: false,
|
||||||
|
isSuccessful: true,
|
||||||
|
errorMessage: '',
|
||||||
|
statusCode: '202',
|
||||||
|
pageInfo: {},
|
||||||
|
payload: {
|
||||||
|
shortDescription: 'Adobe PDF',
|
||||||
|
description: 'Adobe Portable Document Format',
|
||||||
|
mimetype: 'application/pdf',
|
||||||
|
supportLevel: 0,
|
||||||
|
internal: false,
|
||||||
|
extensions: null,
|
||||||
|
self: 'https://dspace7.4science.it/dspace-spring-rest/api/core/bitstreamformats/4'
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
bundleName: 'ORIGINAL',
|
||||||
|
self: 'https://dspace7.4science.it/dspace-spring-rest/api/core/bitstreams/99b00f3c-1cc6-4689-8158-91965bee6b28',
|
||||||
|
id: '99b00f3c-1cc6-4689-8158-91965bee6b28',
|
||||||
|
uuid: '99b00f3c-1cc6-4689-8158-91965bee6b28',
|
||||||
|
type: 'bitstream',
|
||||||
|
name: 'test_pdf.pdf',
|
||||||
|
metadata: [
|
||||||
|
{
|
||||||
|
key: 'dc.title',
|
||||||
|
language: null,
|
||||||
|
value: 'test_pdf.pdf'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
}),
|
}),
|
||||||
self: 'https://dspace7.4science.it/dspace-spring-rest/api/core/items/0ec7ff22-f211-40ab-a69e-c819b0b1f357',
|
self: 'https://dspace7.4science.it/dspace-spring-rest/api/core/items/0ec7ff22-f211-40ab-a69e-c819b0b1f357',
|
||||||
id: '0ec7ff22-f211-40ab-a69e-c819b0b1f357',
|
id: '0ec7ff22-f211-40ab-a69e-c819b0b1f357',
|
||||||
|
Reference in New Issue
Block a user