Merge branch 'master' into improve-i18n-files

This commit is contained in:
Art Lowel
2019-08-08 13:50:10 +02:00
251 changed files with 2509 additions and 1792 deletions

View File

@@ -11,7 +11,7 @@ language: node_js
node_js:
- "8"
- "9"
- "10"
cache:
yarn: true

View File

@@ -14,7 +14,7 @@ If you're looking for the 2016 Angular 2 DSpace UI prototype, you can find it [h
Quick start
-----------
**Ensure you're running [Node](https://nodejs.org) >= `v8.0.x`, [npm](https://www.npmjs.com/) >= `v5.x` and [yarn](https://yarnpkg.com) >= `v1.x`**
**Ensure you're running [Node](https://nodejs.org) `v8.0.x` or `v10.0.x`, [npm](https://www.npmjs.com/) >= `v5.x` and [yarn](https://yarnpkg.com) >= `v1.x`**
```bash
# clone the repo
@@ -65,7 +65,7 @@ Requirements
------------
- [Node.js](https://nodejs.org), [npm](https://www.npmjs.com/), and [yarn](https://yarnpkg.com)
- Ensure you're running node >= `v8.x`, npm >= `v5.x` and yarn >= `v1.x`
- Ensure you're running node `v8.x` or `v10.x`, npm >= `v5.x` and yarn >= `v1.x`
If you have [`nvm`](https://github.com/creationix/nvm#install-script) or [`nvm-windows`](https://github.com/coreybutler/nvm-windows) installed, which is highly recommended, you can run `nvm install --lts && nvm use` to install and start using the latest Node LTS.

View File

@@ -13,7 +13,7 @@ module.exports = {
host: 'dspace7.4science.cloud',
port: 443,
// NOTE: Space is capitalized because 'namespace' is a reserved string in TypeScript
nameSpace: '/dspace-spring-rest/api'
nameSpace: '/server/api'
},
// Caching settings
cache: {

View File

@@ -8,7 +8,7 @@
},
"license": "BSD-2-Clause",
"engines": {
"node": ">=8.0.0"
"node": "8.* || >= 10.*"
},
"scripts": {
"global": "npm install -g @angular/cli marked node-gyp nodemon node-nightly npm-check-updates npm-run-all rimraf typescript ts-node typedoc webpack webpack-bundle-analyzer pm2 rollup",
@@ -62,7 +62,9 @@
"webdriver:update": "node node_modules/protractor/bin/webdriver-manager update --standalone --gecko false",
"lint": "tslint \"src/**/*.ts\" && tslint \"e2e/**/*.ts\"",
"docs": "typedoc --options typedoc.json ./src/",
"coverage": "http-server -c-1 -o -p 9875 ./coverage"
"coverage": "http-server -c-1 -o -p 9875 ./coverage",
"postinstall": "yarn run patch-protractor",
"patch-protractor": "ncp node_modules/webdriver-manager node_modules/protractor/node_modules/webdriver-manager"
},
"dependencies": {
"@angular/animations": "^6.1.4",
@@ -121,7 +123,7 @@
"ngx-moment": "^3.1.0",
"ngx-pagination": "3.0.3",
"nouislider": "^11.0.0",
"pem": "1.12.3",
"pem": "1.13.2",
"reflect-metadata": "0.1.12",
"rxjs": "6.2.2",
"rxjs-spy": "^7.5.1",
@@ -169,7 +171,7 @@
"codelyzer": "^4.4.4",
"compression-webpack-plugin": "^1.1.6",
"copy-webpack-plugin": "^4.4.1",
"copyfiles": "^2.1.0",
"copyfiles": "^2.1.1",
"coveralls": "3.0.0",
"css-loader": "1.0.0",
"cssnano": "^4.1.10",
@@ -192,8 +194,9 @@
"karma-remap-coverage": "^0.1.5",
"karma-remap-istanbul": "0.6.0",
"karma-sourcemap-loader": "0.3.7",
"karma-webdriver-launcher": "1.0.5",
"karma-webdriver-launcher": "^1.0.7",
"karma-webpack": "3.0.0",
"ncp": "^2.0.0",
"ngrx-store-freeze": "^0.2.4",
"node-sass": "^4.11.0",
"nodemon": "^1.15.0",
@@ -206,7 +209,7 @@
"postcss-loader": "^3.0.0",
"postcss-responsive-type": "1.0.0",
"postcss-smart-import": "0.7.6",
"protractor": "^5.3.0",
"protractor": "^5.4.2",
"protractor-istanbul-plugin": "2.0.0",
"raw-loader": "0.5.1",
"resolve-url-loader": "^2.3.0",
@@ -227,10 +230,11 @@
"tslint": "5.11.0",
"typedoc": "^0.9.0",
"typescript": "^2.9.1",
"webdriver-manager": "^12.1.6",
"webpack": "^4.17.1",
"webpack-bundle-analyzer": "^3.3.2",
"webpack-dev-middleware": "3.2.0",
"webpack-dev-server": "^3.1.5",
"webpack-dev-server": "^3.1.11",
"webpack-import-glob-loader": "^1.6.3",
"webpack-merge": "4.1.4",
"webpack-node-externals": "1.7.2"

View File

@@ -5,7 +5,7 @@
var SpecReporter = require('jasmine-spec-reporter').SpecReporter;
exports.config = {
allScriptsTimeout: 11000,
allScriptsTimeout: 600000,
// -----------------------------------------------------------------
// Uncomment to run tests using a remote Selenium server
//seleniumAddress: 'http://selenium.address:4444/wd/hub',
@@ -73,7 +73,7 @@ exports.config = {
framework: 'jasmine',
jasmineNodeOpts: {
showColors: true,
defaultTimeoutInterval: 30000,
defaultTimeoutInterval: 600000,
print: function () {}
},
useAllAngular2AppRoots: true,

View File

@@ -13,6 +13,7 @@ import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
import { EnumKeysPipe } from '../../../shared/utils/enum-keys-pipe';
import { HostWindowService } from '../../../shared/host-window.service';
import { HostWindowServiceStub } from '../../../shared/testing/host-window-service-stub';
import { createSuccessfulRemoteDataObject$ } from '../../../shared/testing/utils';
describe('BitstreamFormatsComponent', () => {
let comp: BitstreamFormatsComponent;
@@ -52,7 +53,7 @@ describe('BitstreamFormatsComponent', () => {
extensions: null
}
];
const mockFormats = observableOf(new RemoteData(false, false, true, undefined, new PaginatedList(null, mockFormatsList)));
const mockFormats = createSuccessfulRemoteDataObject$(new PaginatedList(null, mockFormatsList));
const registryServiceStub = {
getBitstreamFormats: () => mockFormats
};

View File

@@ -1,7 +1,7 @@
import { Action } from '@ngrx/store';
import { type } from '../../../shared/ngrx/type';
import { MetadataSchema } from '../../../core/metadata/metadataschema.model';
import { MetadataField } from '../../../core/metadata/metadatafield.model';
import { MetadataSchema } from '../../../core/metadata/metadata-schema.model';
import { MetadataField } from '../../../core/metadata/metadata-field.model';
/**
* For each action type in an action group, make a simple

View File

@@ -17,6 +17,7 @@ import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core';
import { NotificationsService } from '../../../shared/notifications/notifications.service';
import { NotificationsServiceStub } from '../../../shared/testing/notifications-service-stub';
import { RestResponse } from '../../../core/cache/response.models';
import { createSuccessfulRemoteDataObject$ } from '../../../shared/testing/utils';
describe('MetadataRegistryComponent', () => {
let comp: MetadataRegistryComponent;
@@ -36,7 +37,7 @@ describe('MetadataRegistryComponent', () => {
namespace: 'http://dspace.org/mockschema'
}
];
const mockSchemas = observableOf(new RemoteData(false, false, true, undefined, new PaginatedList(null, mockSchemasList)));
const mockSchemas = createSuccessfulRemoteDataObject$(new PaginatedList(null, mockSchemasList));
/* tslint:disable:no-empty */
const registryServiceStub = {
getMetadataSchemas: () => mockSchemas,

View File

@@ -3,7 +3,6 @@ import { RegistryService } from '../../../core/registry/registry.service';
import { Observable, combineLatest as observableCombineLatest } from 'rxjs';
import { RemoteData } from '../../../core/data/remote-data';
import { PaginatedList } from '../../../core/data/paginated-list';
import { MetadataSchema } from '../../../core/metadata/metadataschema.model';
import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.model';
import { map, take } from 'rxjs/operators';
import { hasValue } from '../../../shared/empty.util';
@@ -12,6 +11,7 @@ import { zip } from 'rxjs/internal/observable/zip';
import { NotificationsService } from '../../../shared/notifications/notifications.service';
import { Route, Router } from '@angular/router';
import { TranslateService } from '@ngx-translate/core';
import { MetadataSchema } from '../../../core/metadata/metadata-schema.model';
@Component({
selector: 'ds-metadata-registry',

View File

@@ -7,8 +7,8 @@ import {
MetadataRegistrySelectSchemaAction
} from './metadata-registry.actions';
import { metadataRegistryReducer, MetadataRegistryState } from './metadata-registry.reducers';
import { MetadataSchema } from '../../../core/metadata/metadataschema.model';
import { MetadataField } from '../../../core/metadata/metadatafield.model';
import { MetadataSchema } from '../../../core/metadata/metadata-schema.model';
import { MetadataField } from '../../../core/metadata/metadata-field.model';
class NullAction extends MetadataRegistryEditSchemaAction {
type = null;

View File

@@ -1,4 +1,3 @@
import { MetadataSchema } from '../../../core/metadata/metadataschema.model';
import {
MetadataRegistryAction,
MetadataRegistryActionTypes,
@@ -9,7 +8,8 @@ import {
MetadataRegistrySelectFieldAction,
MetadataRegistrySelectSchemaAction
} from './metadata-registry.actions';
import { MetadataField } from '../../../core/metadata/metadatafield.model';
import { MetadataField } from '../../../core/metadata/metadata-field.model';
import { MetadataSchema } from '../../../core/metadata/metadata-schema.model';
/**
* The metadata registry state.

View File

@@ -10,7 +10,7 @@ import { EnumKeysPipe } from '../../../../shared/utils/enum-keys-pipe';
import { RegistryService } from '../../../../core/registry/registry.service';
import { FormBuilderService } from '../../../../shared/form/builder/form-builder.service';
import { of as observableOf } from 'rxjs/internal/observable/of';
import { MetadataSchema } from '../../../../core/metadata/metadataschema.model';
import { MetadataSchema } from '../../../../core/metadata/metadata-schema.model';
describe('MetadataSchemaFormComponent', () => {
let component: MetadataSchemaFormComponent;

View File

@@ -9,9 +9,9 @@ import { FormGroup } from '@angular/forms';
import { RegistryService } from '../../../../core/registry/registry.service';
import { FormBuilderService } from '../../../../shared/form/builder/form-builder.service';
import { take } from 'rxjs/operators';
import { MetadataSchema } from '../../../../core/metadata/metadataschema.model';
import { TranslateService } from '@ngx-translate/core';
import { combineLatest } from 'rxjs/internal/observable/combineLatest';
import { MetadataSchema } from '../../../../core/metadata/metadata-schema.model';
@Component({
selector: 'ds-metadata-schema-form',

View File

@@ -3,7 +3,6 @@ import { async, ComponentFixture, inject, TestBed } from '@angular/core/testing'
import { MetadataFieldFormComponent } from './metadata-field-form.component';
import { RegistryService } from '../../../../core/registry/registry.service';
import { of as observableOf } from 'rxjs/internal/observable/of';
import { MetadataField } from '../../../../core/metadata/metadatafield.model';
import { CommonModule } from '@angular/common';
import { RouterTestingModule } from '@angular/router/testing';
import { TranslateModule } from '@ngx-translate/core';
@@ -11,7 +10,8 @@ import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
import { EnumKeysPipe } from '../../../../shared/utils/enum-keys-pipe';
import { FormBuilderService } from '../../../../shared/form/builder/form-builder.service';
import { NO_ERRORS_SCHEMA } from '@angular/core';
import { MetadataSchema } from '../../../../core/metadata/metadataschema.model';
import { MetadataField } from '../../../../core/metadata/metadata-field.model';
import { MetadataSchema } from '../../../../core/metadata/metadata-schema.model';
describe('MetadataFieldFormComponent', () => {
let component: MetadataFieldFormComponent;

View File

@@ -1,5 +1,4 @@
import { Component, EventEmitter, Input, OnDestroy, OnInit, Output } from '@angular/core';
import { MetadataSchema } from '../../../../core/metadata/metadataschema.model';
import {
DynamicFormControlModel,
DynamicFormLayout,
@@ -8,10 +7,11 @@ import {
import { FormGroup } from '@angular/forms';
import { RegistryService } from '../../../../core/registry/registry.service';
import { FormBuilderService } from '../../../../shared/form/builder/form-builder.service';
import { MetadataField } from '../../../../core/metadata/metadatafield.model';
import { take } from 'rxjs/operators';
import { TranslateService } from '@ngx-translate/core';
import { combineLatest } from 'rxjs/internal/observable/combineLatest';
import { MetadataSchema } from '../../../../core/metadata/metadata-schema.model';
import { MetadataField } from '../../../../core/metadata/metadata-field.model';
@Component({
selector: 'ds-metadata-field-form',

View File

@@ -3,7 +3,6 @@ import { async, ComponentFixture, inject, TestBed } from '@angular/core/testing'
import { of as observableOf } from 'rxjs';
import { RemoteData } from '../../../core/data/remote-data';
import { PaginatedList } from '../../../core/data/paginated-list';
import { MetadataSchema } from '../../../core/metadata/metadataschema.model';
import { TranslateModule } from '@ngx-translate/core';
import { CommonModule } from '@angular/common';
import { ActivatedRoute, Router } from '@angular/router';
@@ -21,6 +20,8 @@ import { NO_ERRORS_SCHEMA } from '@angular/core';
import { NotificationsService } from '../../../shared/notifications/notifications.service';
import { NotificationsServiceStub } from '../../../shared/testing/notifications-service-stub';
import { RestResponse } from '../../../core/cache/response.models';
import { MetadataSchema } from '../../../core/metadata/metadata-schema.model';
import { createSuccessfulRemoteDataObject$ } from '../../../shared/testing/utils';
describe('MetadataSchemaComponent', () => {
let comp: MetadataSchemaComponent;
@@ -74,12 +75,12 @@ describe('MetadataSchemaComponent', () => {
schema: mockSchemasList[1]
}
];
const mockSchemas = observableOf(new RemoteData(false, false, true, undefined, new PaginatedList(null, mockSchemasList)));
const mockSchemas = createSuccessfulRemoteDataObject$(new PaginatedList(null, mockSchemasList));
/* tslint:disable:no-empty */
const registryServiceStub = {
getMetadataSchemas: () => mockSchemas,
getMetadataFieldsBySchema: (schema: MetadataSchema) => observableOf(new RemoteData(false, false, true, undefined, new PaginatedList(null, mockFieldsList.filter((value) => value.schema === schema)))),
getMetadataSchemaByName: (schemaName: string) => observableOf(new RemoteData(false, false, true, undefined, mockSchemasList.filter((value) => value.prefix === schemaName)[0])),
getMetadataFieldsBySchema: (schema: MetadataSchema) => createSuccessfulRemoteDataObject$(new PaginatedList(null, mockFieldsList.filter((value) => value.schema === schema))),
getMetadataSchemaByName: (schemaName: string) => createSuccessfulRemoteDataObject$(mockSchemasList.filter((value) => value.prefix === schemaName)[0]),
getActiveMetadataField: () => observableOf(undefined),
getSelectedMetadataFields: () => observableOf([]),
editMetadataField: (schema) => {},

View File

@@ -4,8 +4,6 @@ import { ActivatedRoute, Router } from '@angular/router';
import { Observable, combineLatest as observableCombineLatest } from 'rxjs';
import { RemoteData } from '../../../core/data/remote-data';
import { PaginatedList } from '../../../core/data/paginated-list';
import { MetadataField } from '../../../core/metadata/metadatafield.model';
import { MetadataSchema } from '../../../core/metadata/metadataschema.model';
import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.model';
import { map, take } from 'rxjs/operators';
import { hasValue } from '../../../shared/empty.util';
@@ -13,6 +11,8 @@ import { RestResponse } from '../../../core/cache/response.models';
import { zip } from 'rxjs/internal/observable/zip';
import { NotificationsService } from '../../../shared/notifications/notifications.service';
import { TranslateService } from '@ngx-translate/core';
import { MetadataField } from '../../../core/metadata/metadata-field.model';
import { MetadataSchema } from '../../../core/metadata/metadata-schema.model';
@Component({
selector: 'ds-metadata-schema',

View File

@@ -18,6 +18,7 @@ import { Item } from '../../core/shared/item.model';
import { ENV_CONFIG, GLOBAL_CONFIG } from '../../../config';
import { BrowseEntrySearchOptions } from '../../core/browse/browse-entry-search-options.model';
import { toRemoteData } from '../+browse-by-metadata-page/browse-by-metadata-page.component.spec';
import { createSuccessfulRemoteDataObject$ } from '../../shared/testing/utils';
describe('BrowseByDatePageComponent', () => {
let comp: BrowseByDatePageComponent;
@@ -48,11 +49,11 @@ describe('BrowseByDatePageComponent', () => {
const mockBrowseService = {
getBrowseEntriesFor: (options: BrowseEntrySearchOptions) => toRemoteData([]),
getBrowseItemsFor: (value: string, options: BrowseEntrySearchOptions) => toRemoteData([firstItem]),
getFirstItemFor: () => observableOf(new RemoteData(false, false, true, undefined, firstItem))
getFirstItemFor: () => createSuccessfulRemoteDataObject$(firstItem)
};
const mockDsoService = {
findById: () => observableOf(new RemoteData(false, false, true, null, mockCommunity))
findById: () => createSuccessfulRemoteDataObject$(mockCommunity)
};
const activatedRouteStub = Object.assign(new ActivatedRouteStub(), {

View File

@@ -20,6 +20,9 @@ import { Item } from '../../core/shared/item.model';
import { DSpaceObjectDataService } from '../../core/data/dspace-object-data.service';
import { Community } from '../../core/shared/community.model';
import { MockRouter } from '../../shared/mocks/mock-router';
import { ResourceType } from '../../core/shared/resource-type';
import { createSuccessfulRemoteDataObject$ } from '../../shared/testing/utils';
import { BrowseEntry } from '../../core/shared/browse-entry.model';
describe('BrowseByMetadataPageComponent', () => {
let comp: BrowseByMetadataPageComponent;
@@ -39,21 +42,21 @@ describe('BrowseByMetadataPageComponent', () => {
const mockEntries = [
{
type: 'author',
type: BrowseEntry.type,
authority: null,
value: 'John Doe',
language: 'en',
count: 1
},
{
type: 'author',
type: BrowseEntry.type,
authority: null,
value: 'James Doe',
language: 'en',
count: 3
},
{
type: 'subject',
type: BrowseEntry.type,
authority: null,
value: 'Fake subject',
language: 'en',
@@ -68,12 +71,12 @@ describe('BrowseByMetadataPageComponent', () => {
];
const mockBrowseService = {
getBrowseEntriesFor: (options: BrowseEntrySearchOptions) => toRemoteData(mockEntries.filter((entry) => entry.type === options.metadataDefinition)),
getBrowseEntriesFor: (options: BrowseEntrySearchOptions) => toRemoteData(mockEntries),
getBrowseItemsFor: (value: string, options: BrowseEntrySearchOptions) => toRemoteData(mockItems)
};
const mockDsoService = {
findById: () => observableOf(new RemoteData(false, false, true, null, mockCommunity))
findById: () => createSuccessfulRemoteDataObject$(mockCommunity)
};
const activatedRouteStub = Object.assign(new ActivatedRouteStub(), {
@@ -105,12 +108,6 @@ describe('BrowseByMetadataPageComponent', () => {
fixture.detectChanges();
});
it('should fetch the correct entries depending on the metadata definition', () => {
comp.browseEntries$.subscribe((result) => {
expect(result.payload.page).toEqual(mockEntries.filter((entry) => entry.type === 'author'));
});
});
it('should not fetch any items when no value is provided', () => {
expect(comp.items$).toBeUndefined();
});
@@ -160,5 +157,5 @@ describe('BrowseByMetadataPageComponent', () => {
});
export function toRemoteData(objects: any[]): Observable<RemoteData<PaginatedList<any>>> {
return observableOf(new RemoteData(false, false, true, null, new PaginatedList(new PageInfo(), objects)));
return createSuccessfulRemoteDataObject$(new PaginatedList(new PageInfo(), objects));
}

View File

@@ -17,6 +17,7 @@ import { RemoteData } from '../../core/data/remote-data';
import { DSpaceObjectDataService } from '../../core/data/dspace-object-data.service';
import { BrowseService } from '../../core/browse/browse.service';
import { MockRouter } from '../../shared/mocks/mock-router';
import { createSuccessfulRemoteDataObject$ } from '../../shared/testing/utils';
describe('BrowseByTitlePageComponent', () => {
let comp: BrowseByTitlePageComponent;
@@ -52,7 +53,7 @@ describe('BrowseByTitlePageComponent', () => {
};
const mockDsoService = {
findById: () => observableOf(new RemoteData(false, false, true, null, mockCommunity))
findById: () => createSuccessfulRemoteDataObject$(mockCommunity)
};
const activatedRouteStub = Object.assign(new ActivatedRouteStub(), {

View File

@@ -1,12 +1,9 @@
import { Component, Input } from '@angular/core';
import {
DynamicInputModel,
DynamicTextAreaModel
} from '@ng-dynamic-forms/core';
import { DynamicInputModel, DynamicTextAreaModel } from '@ng-dynamic-forms/core';
import { DynamicFormControlModel } from '@ng-dynamic-forms/core/src/model/dynamic-form-control.model';
import { ResourceType } from '../../core/shared/resource-type';
import { Collection } from '../../core/shared/collection.model';
import { ComColFormComponent } from '../../shared/comcol-forms/comcol-form/comcol-form.component';
import { NormalizedCollection } from '../../core/cache/models/normalized-collection.model';
/**
* Form used for creating and editing collections
@@ -23,9 +20,9 @@ export class CollectionFormComponent extends ComColFormComponent<Collection> {
@Input() dso: Collection = new Collection();
/**
* @type {ResourceType.Collection} This is a collection-type form
* @type {Collection.type} This is a collection-type form
*/
protected type = ResourceType.Collection;
protected type = Collection.type;
/**
* The dynamic form fields used for creating/editing a collection

View File

@@ -1,9 +1,11 @@
import { CreateCollectionPageGuard } from './create-collection-page.guard';
import { MockRouter } from '../../shared/mocks/mock-router';
import { RemoteData } from '../../core/data/remote-data';
import { Community } from '../../core/shared/community.model';
import { of as observableOf } from 'rxjs';
import { first } from 'rxjs/operators';
import {
createFailedRemoteDataObject$,
createSuccessfulRemoteDataObject$
} from '../../shared/testing/utils';
describe('CreateCollectionPageGuard', () => {
describe('canActivate', () => {
@@ -15,11 +17,11 @@ describe('CreateCollectionPageGuard', () => {
communityDataServiceStub = {
findById: (id: string) => {
if (id === 'valid-id') {
return observableOf(new RemoteData(false, false, true, null, new Community()));
return createSuccessfulRemoteDataObject$(new Community());
} else if (id === 'invalid-id') {
return observableOf(new RemoteData(false, false, true, null, undefined));
return createSuccessfulRemoteDataObject$(undefined);
} else if (id === 'error-id') {
return observableOf(new RemoteData(false, false, false, null, new Community()));
return createFailedRemoteDataObject$(new Community());
}
}
};

View File

@@ -20,9 +20,9 @@ export class CommunityFormComponent extends ComColFormComponent<Community> {
@Input() dso: Community = new Community();
/**
* @type {ResourceType.Community} This is a community-type form
* @type {Community.type} This is a community-type form
*/
protected type = ResourceType.Community;
protected type = Community.type;
/**
* The dynamic form fields used for creating/editing a community

View File

@@ -1,9 +1,11 @@
import { CreateCommunityPageGuard } from './create-community-page.guard';
import { MockRouter } from '../../shared/mocks/mock-router';
import { RemoteData } from '../../core/data/remote-data';
import { Community } from '../../core/shared/community.model';
import { of as observableOf } from 'rxjs';
import { first } from 'rxjs/operators';
import {
createFailedRemoteDataObject$,
createSuccessfulRemoteDataObject$
} from '../../shared/testing/utils';
describe('CreateCommunityPageGuard', () => {
describe('canActivate', () => {
@@ -15,11 +17,11 @@ describe('CreateCommunityPageGuard', () => {
communityDataServiceStub = {
findById: (id: string) => {
if (id === 'valid-id') {
return observableOf(new RemoteData(false, false, true, null, new Community()));
return createSuccessfulRemoteDataObject$(new Community());
} else if (id === 'invalid-id') {
return observableOf(new RemoteData(false, false, true, null, undefined));
return createSuccessfulRemoteDataObject$(undefined);
} else if (id === 'error-id') {
return observableOf(new RemoteData(false, false, false, null, new Community()));
return createFailedRemoteDataObject$(new Community());
}
}
};

View File

@@ -11,6 +11,7 @@ import {RouterTestingModule} from '@angular/router/testing';
import {NoopAnimationsModule} from '@angular/platform-browser/animations';
import {By} from '@angular/platform-browser';
import {of as observableOf, Observable } from 'rxjs';
import { createSuccessfulRemoteDataObject$ } from '../../shared/testing/utils';
describe('SubCommunityList Component', () => {
let comp: CommunityPageSubCommunityListComponent;
@@ -40,8 +41,7 @@ describe('SubCommunityList Component', () => {
{ language: 'en_US', value: 'Test title' }
]
},
subcommunities: observableOf(new RemoteData(true, true, true,
undefined, new PaginatedList(new PageInfo(), [])))
subcommunities: createSuccessfulRemoteDataObject$(new PaginatedList(new PageInfo(), []))
});
const mockCommunity = Object.assign(new Community(), {
@@ -50,8 +50,7 @@ describe('SubCommunityList Component', () => {
{ language: 'en_US', value: 'Test title' }
]
},
subcommunities: observableOf(new RemoteData(true, true, true,
undefined, new PaginatedList(new PageInfo(), subcommunities)))
subcommunities: createSuccessfulRemoteDataObject$(new PaginatedList(new PageInfo(), subcommunities))
})
;

View File

@@ -2,6 +2,10 @@ import {RemoteData} from '../../core/data/remote-data';
import {hot} from 'jasmine-marbles';
import {Item} from '../../core/shared/item.model';
import {findSuccessfulAccordingTo} from './edit-item-operators';
import {
createFailedRemoteDataObject,
createSuccessfulRemoteDataObject
} from '../../shared/testing/utils';
describe('findSuccessfulAccordingTo', () => {
let mockItem1;
@@ -19,11 +23,11 @@ describe('findSuccessfulAccordingTo', () => {
});
it('should return first successful RemoteData Observable that complies to predicate', () => {
const testRD = {
a: new RemoteData(false, false, true, null, undefined),
b: new RemoteData(false, false, false, null, mockItem1),
c: new RemoteData(false, false, true, null, mockItem2),
d: new RemoteData(false, false, true, null, mockItem1),
e: new RemoteData(false, false, true, null, mockItem2),
a: createSuccessfulRemoteDataObject(undefined),
b: createFailedRemoteDataObject(mockItem1),
c: createSuccessfulRemoteDataObject(mockItem2),
d: createSuccessfulRemoteDataObject(mockItem1),
e: createSuccessfulRemoteDataObject(mockItem2),
};
const source = hot('abcde', testRD);

View File

@@ -17,6 +17,7 @@ import { By } from '@angular/platform-browser';
import { ItemDeleteComponent } from './item-delete.component';
import { getItemEditPath } from '../../item-page-routing.module';
import { RestResponse } from '../../../core/cache/response.models';
import { createSuccessfulRemoteDataObject } from '../../../shared/testing/utils';
let comp: ItemDeleteComponent;
let fixture: ComponentFixture<ItemDeleteComponent>;
@@ -49,7 +50,7 @@ describe('ItemDeleteComponent', () => {
routeStub = {
data: observableOf({
item: new RemoteData(false, false, true, null, mockItem)
item: createSuccessfulRemoteDataObject(mockItem)
})
};

View File

@@ -6,17 +6,18 @@ import { ObjectUpdatesService } from '../../../../core/data/object-updates/objec
import { of as observableOf } from 'rxjs';
import { RemoteData } from '../../../../core/data/remote-data';
import { PaginatedList } from '../../../../core/data/paginated-list';
import { MetadataField } from '../../../../core/metadata/metadatafield.model';
import { By } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { SharedModule } from '../../../../shared/shared.module';
import { getTestScheduler } from 'jasmine-marbles';
import { InputSuggestion } from '../../../../shared/input-suggestions/input-suggestions.model';
import { TestScheduler } from 'rxjs/testing';
import { MetadataSchema } from '../../../../core/metadata/metadataschema.model';
import { FieldChangeType } from '../../../../core/data/object-updates/object-updates.actions';
import { TranslateModule } from '@ngx-translate/core';
import { MetadatumViewModel } from '../../../../core/shared/metadata.models';
import { MetadataSchema } from '../../../../core/metadata/metadata-schema.model';
import { MetadataField } from '../../../../core/metadata/metadata-field.model';
import { createSuccessfulRemoteDataObject$ } from '../../../../shared/testing/utils';
let comp: EditInPlaceFieldComponent;
let fixture: ComponentFixture<EditInPlaceFieldComponent>;
@@ -59,7 +60,7 @@ describe('EditInPlaceFieldComponent', () => {
paginatedMetadataFields = new PaginatedList(undefined, [mdField1, mdField2, mdField3]);
metadataFieldService = jasmine.createSpyObj({
queryMetadataFields: observableOf(new RemoteData(false, false, true, undefined, paginatedMetadataFields)),
queryMetadataFields: createSuccessfulRemoteDataObject$(paginatedMetadataFields),
});
objectUpdatesService = jasmine.createSpyObj('objectUpdatesService',
{

View File

@@ -4,13 +4,13 @@ import { RegistryService } from '../../../../core/registry/registry.service';
import { cloneDeep } from 'lodash';
import { BehaviorSubject, Observable, of as observableOf } from 'rxjs';
import { map, take } from 'rxjs/operators';
import { MetadataField } from '../../../../core/metadata/metadatafield.model';
import { InputSuggestion } from '../../../../shared/input-suggestions/input-suggestions.model';
import { FieldChangeType } from '../../../../core/data/object-updates/object-updates.actions';
import { FieldUpdate } from '../../../../core/data/object-updates/object-updates.reducer';
import { ObjectUpdatesService } from '../../../../core/data/object-updates/object-updates.service';
import { NgModel } from '@angular/forms';
import { MetadatumViewModel } from '../../../../core/shared/metadata.models';
import { MetadataField } from '../../../../core/metadata/metadata-field.model';
@Component({
// tslint:disable-next-line:component-selector

View File

@@ -20,13 +20,16 @@ import { RouterStub } from '../../../shared/testing/router-stub';
import { GLOBAL_CONFIG } from '../../../../config';
import { Item } from '../../../core/shared/item.model';
import { FieldChangeType } from '../../../core/data/object-updates/object-updates.actions';
import { RemoteData } from '../../../core/data/remote-data';
import { MetadatumViewModel } from '../../../core/shared/metadata.models';
import { RegistryService } from '../../../core/registry/registry.service';
import { PaginatedList } from '../../../core/data/paginated-list';
import { MetadataSchema } from '../../../core/metadata/metadataschema.model';
import { MetadataField } from '../../../core/metadata/metadatafield.model';
import { Metadata } from '../../../core/shared/metadata.utils';
import { MetadataSchema } from '../../../core/metadata/metadata-schema.model';
import { MetadataField } from '../../../core/metadata/metadata-field.model';
import {
createSuccessfulRemoteDataObject,
createSuccessfulRemoteDataObject$
} from '../../../shared/testing/utils';
let comp: ItemMetadataComponent;
let fixture: ComponentFixture<ItemMetadataComponent>;
@@ -116,18 +119,18 @@ describe('ItemMetadataComponent', () => {
)
;
itemService = jasmine.createSpyObj('itemService', {
update: observableOf(new RemoteData(false, false, true, undefined, item)),
update: createSuccessfulRemoteDataObject$(item),
commitUpdates: {}
});
routeStub = {
parent: {
data: observableOf({ item: new RemoteData(false, false, true, null, item) })
data: observableOf({ item: createSuccessfulRemoteDataObject(item) })
}
};
paginatedMetadataFields = new PaginatedList(undefined, [mdField1, mdField2, mdField3]);
metadataFieldService = jasmine.createSpyObj({
getAllMetadataFields: observableOf(new RemoteData(false, false, true, undefined, paginatedMetadataFields))
getAllMetadataFields:createSuccessfulRemoteDataObject$(paginatedMetadataFields)
});
scheduler = getTestScheduler();
objectUpdatesService = jasmine.createSpyObj('objectUpdatesService',

View File

@@ -17,9 +17,9 @@ import { NotificationsService } from '../../../shared/notifications/notification
import { GLOBAL_CONFIG, GlobalConfig } from '../../../../config';
import { TranslateService } from '@ngx-translate/core';
import { RegistryService } from '../../../core/registry/registry.service';
import { MetadataField } from '../../../core/metadata/metadatafield.model';
import { MetadatumViewModel } from '../../../core/shared/metadata.models';
import { Metadata } from '../../../core/shared/metadata.utils';
import { MetadataField } from '../../../core/metadata/metadata-field.model';
@Component({
selector: 'ds-item-metadata',

View File

@@ -16,6 +16,7 @@ import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { By } from '@angular/platform-browser';
import { ItemPrivateComponent } from './item-private.component';
import { RestResponse } from '../../../core/cache/response.models';
import { createSuccessfulRemoteDataObject } from '../../../shared/testing/utils';
let comp: ItemPrivateComponent;
let fixture: ComponentFixture<ItemPrivateComponent>;
@@ -50,7 +51,7 @@ describe('ItemPrivateComponent', () => {
routeStub = {
data: observableOf({
item: new RemoteData(false, false, true, null, {
item: createSuccessfulRemoteDataObject({
id: 'fake-id'
})
})

View File

@@ -16,6 +16,7 @@ import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { By } from '@angular/platform-browser';
import { ItemPublicComponent } from './item-public.component';
import { RestResponse } from '../../../core/cache/response.models';
import { createSuccessfulRemoteDataObject } from '../../../shared/testing/utils';
let comp: ItemPublicComponent;
let fixture: ComponentFixture<ItemPublicComponent>;
@@ -50,7 +51,7 @@ describe('ItemPublicComponent', () => {
routeStub = {
data: observableOf({
item: new RemoteData(false, false, true, null, {
item: createSuccessfulRemoteDataObject({
id: 'fake-id'
})
})

View File

@@ -16,6 +16,7 @@ import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { By } from '@angular/platform-browser';
import { ItemReinstateComponent } from './item-reinstate.component';
import { RestResponse } from '../../../core/cache/response.models';
import { createSuccessfulRemoteDataObject } from '../../../shared/testing/utils';
let comp: ItemReinstateComponent;
let fixture: ComponentFixture<ItemReinstateComponent>;
@@ -50,7 +51,7 @@ describe('ItemReinstateComponent', () => {
routeStub = {
data: observableOf({
item: new RemoteData(false, false, true, null, {
item: createSuccessfulRemoteDataObject({
id: 'fake-id'
})
})

View File

@@ -12,7 +12,7 @@
{{'item.edit.tabs.status.labels.itemPage' | translate}}:
</div>
<div class="col-9 float-left status-data" id="status-itemPage">
<a href="{{getItemPage((itemRD$ | async)?.payload)}}">{{getItemPage((itemRD$ | async)?.payload)}}</a>
<a [routerLink]="getItemPage((itemRD$ | async)?.payload)">{{getItemPage((itemRD$ | async)?.payload)}}</a>
</div>
<div *ngFor="let operation of operations" class="w-100 pt-3">

View File

@@ -11,7 +11,7 @@ import { Item } from '../../../core/shared/item.model';
import { By } from '@angular/platform-browser';
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { of as observableOf } from 'rxjs';
import { RemoteData } from '../../../core/data/remote-data';
import { createSuccessfulRemoteDataObject } from '../../../shared/testing/utils';
describe('ItemStatusComponent', () => {
let comp: ItemStatusComponent;
@@ -27,7 +27,7 @@ describe('ItemStatusComponent', () => {
const routeStub = {
parent: {
data: observableOf({ item: new RemoteData(false, false, true, null, mockItem) })
data: observableOf({ item: createSuccessfulRemoteDataObject(mockItem) })
}
};

View File

@@ -16,6 +16,7 @@ import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { ItemWithdrawComponent } from './item-withdraw.component';
import { By } from '@angular/platform-browser';
import { RestResponse } from '../../../core/cache/response.models';
import { createSuccessfulRemoteDataObject } from '../../../shared/testing/utils';
let comp: ItemWithdrawComponent;
let fixture: ComponentFixture<ItemWithdrawComponent>;
@@ -50,7 +51,7 @@ describe('ItemWithdrawComponent', () => {
routeStub = {
data: observableOf({
item: new RemoteData(false, false, true, null, {
item: createSuccessfulRemoteDataObject({
id: 'fake-id'
})
})

View File

@@ -17,6 +17,10 @@ import { By } from '@angular/platform-browser';
import { of as observableOf } from 'rxjs';
import { getItemEditPath } from '../../item-page-routing.module';
import { RestResponse } from '../../../core/cache/response.models';
import {
createSuccessfulRemoteDataObject,
createSuccessfulRemoteDataObject$
} from '../../../shared/testing/utils';
/**
* Test component that implements the AbstractSimpleItemActionComponent used to test the
@@ -65,12 +69,12 @@ describe('AbstractSimpleItemActionComponent', () => {
});
mockItemDataService = jasmine.createSpyObj({
findById: observableOf(new RemoteData(false, false, true, undefined, mockItem))
findById: createSuccessfulRemoteDataObject$(mockItem)
});
routeStub = {
data: observableOf({
item: new RemoteData(false, false, true, null, {
item: createSuccessfulRemoteDataObject({
id: 'fake-id'
})
})

View File

@@ -9,6 +9,10 @@ import { Item } from '../../../core/shared/item.model';
import { of as observableOf } from 'rxjs';
import { RemoteData } from '../../../core/data/remote-data';
import { TranslateModule } from '@ngx-translate/core';
import {
createFailedRemoteDataObject$,
createSuccessfulRemoteDataObject$
} from '../../../shared/testing/utils';
let collectionsComponent: CollectionsComponent;
let fixture: ComponentFixture<CollectionsComponent>;
@@ -24,8 +28,8 @@ const mockCollection1: Collection = Object.assign(new Collection(), {
}
});
const succeededMockItem: Item = Object.assign(new Item(), {owningCollection: observableOf(new RemoteData(false, false, true, null, mockCollection1))});
const failedMockItem: Item = Object.assign(new Item(), {owningCollection: observableOf(new RemoteData(false, false, false, null, mockCollection1))});
const succeededMockItem: Item = Object.assign(new Item(), {owningCollection: createSuccessfulRemoteDataObject$(mockCollection1)});
const failedMockItem: Item = Object.assign(new Item(), {owningCollection: createFailedRemoteDataObject$(mockCollection1)});
describe('CollectionsComponent', () => {
beforeEach(async(() => {

View File

@@ -17,9 +17,13 @@ import { RemoteData } from '../../core/data/remote-data';
import { of as observableOf } from 'rxjs';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { By } from '@angular/platform-browser';
import {
createSuccessfulRemoteDataObject,
createSuccessfulRemoteDataObject$
} from '../../shared/testing/utils';
const mockItem: Item = Object.assign(new Item(), {
bitstreams: observableOf(new RemoteData(false, false, true, null, new PaginatedList(new PageInfo(), []))),
bitstreams: createSuccessfulRemoteDataObject$(new PaginatedList(new PageInfo(), [])),
metadata: {
'dc.title': [
{
@@ -30,7 +34,7 @@ const mockItem: Item = Object.assign(new Item(), {
}
});
const routeStub = Object.assign(new ActivatedRouteStub(), {
data: observableOf({ item: new RemoteData(false, false, true, null, mockItem) })
data: observableOf({ item: createSuccessfulRemoteDataObject(mockItem) })
});
const metadataServiceStub = {
/* tslint:disable:no-empty */

View File

@@ -11,6 +11,7 @@ import { ItemPageFieldComponent } from './item-page-field.component';
import { MetadataValuesComponent } from '../../../field-components/metadata-values/metadata-values.component';
import { of as observableOf } from 'rxjs';
import { MetadataMap, MetadataValue } from '../../../../core/shared/metadata.models';
import { createSuccessfulRemoteDataObject$ } from '../../../../shared/testing/utils';
let comp: ItemPageFieldComponent;
let fixture: ComponentFixture<ItemPageFieldComponent>;
@@ -52,7 +53,7 @@ describe('ItemPageFieldComponent', () => {
export function mockItemWithMetadataFieldAndValue(field: string, value: string): Item {
const item = Object.assign(new Item(), {
bitstreams: observableOf(new RemoteData(false, false, true, null, new PaginatedList(new PageInfo(), []))),
bitstreams: createSuccessfulRemoteDataObject$(new PaginatedList(new PageInfo(), [])),
metadata: new MetadataMap()
});
item.metadata[field] = [{

View File

@@ -16,9 +16,13 @@ import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { By } from '@angular/platform-browser';
import { createRelationshipsObservable } from './item-types/shared/item.component.spec';
import { of as observableOf } from 'rxjs';
import {
createFailedRemoteDataObject$, createPendingRemoteDataObject$, createSuccessfulRemoteDataObject,
createSuccessfulRemoteDataObject$
} from '../../shared/testing/utils';
const mockItem: Item = Object.assign(new Item(), {
bitstreams: observableOf(new RemoteData(false, false, true, null, new PaginatedList(new PageInfo(), []))),
bitstreams: createSuccessfulRemoteDataObject$(new PaginatedList(new PageInfo(), [])),
metadata: [],
relationships: createRelationshipsObservable()
});
@@ -33,7 +37,7 @@ describe('ItemPageComponent', () => {
/* tslint:enable:no-empty */
};
const mockRoute = Object.assign(new ActivatedRouteStub(), {
data: observableOf({ item: new RemoteData(false, false, true, null, mockItem) })
data: observableOf({ item: createSuccessfulRemoteDataObject(mockItem) })
});
beforeEach(async(() => {
@@ -66,7 +70,8 @@ describe('ItemPageComponent', () => {
describe('when the item is loading', () => {
beforeEach(() => {
comp.itemRD$ = observableOf(new RemoteData(true, true, true, null, undefined));
comp.itemRD$ = createPendingRemoteDataObject$(undefined);
// comp.itemRD$ = observableOf(new RemoteData(true, true, true, null, undefined));
fixture.detectChanges();
});
@@ -78,7 +83,7 @@ describe('ItemPageComponent', () => {
describe('when the item failed loading', () => {
beforeEach(() => {
comp.itemRD$ = observableOf(new RemoteData(false, false, false, null, undefined));
comp.itemRD$ = createFailedRemoteDataObject$(undefined);
fixture.detectChanges();
});

View File

@@ -17,9 +17,10 @@ import { createRelationshipsObservable } from '../shared/item.component.spec';
import { PublicationComponent } from './publication.component';
import { of as observableOf } from 'rxjs';
import { MetadataMap } from '../../../../core/shared/metadata.models';
import { createSuccessfulRemoteDataObject$ } from '../../../../shared/testing/utils';
const mockItem: Item = Object.assign(new Item(), {
bitstreams: observableOf(new RemoteData(false, false, true, null, new PaginatedList(new PageInfo(), []))),
bitstreams: createSuccessfulRemoteDataObject$(new PaginatedList(new PageInfo(), [])),
metadata: new MetadataMap(),
relationships: createRelationshipsObservable()
});

View File

@@ -26,6 +26,7 @@ import { MetadatumRepresentation } from '../../../../core/shared/metadata-repres
import { ItemMetadataRepresentation } from '../../../../core/shared/metadata-representation/item/item-metadata-representation.model';
import { MetadataMap, MetadataValue } from '../../../../core/shared/metadata.models';
import { compareArraysUsing, compareArraysUsingIds } from './item-relationships-utils';
import { createSuccessfulRemoteDataObject$ } from '../../../../shared/testing/utils';
/**
* Create a generic test for an item-page-fields component using a mockItem and the type of component
@@ -102,13 +103,13 @@ export function containsFieldInput(fields: DebugElement[], metadataKey: string):
}
export function createRelationshipsObservable() {
return observableOf(new RemoteData(false, false, true, null, new PaginatedList(new PageInfo(), [
return createSuccessfulRemoteDataObject$(new PaginatedList(new PageInfo(), [
Object.assign(new Relationship(), {
relationshipType: observableOf(new RemoteData(false, false, true, null, new RelationshipType())),
leftItem: observableOf(new RemoteData(false, false, true, null, new Item())),
rightItem: observableOf(new RemoteData(false, false, true, null, new Item()))
relationshipType: createSuccessfulRemoteDataObject$(new RelationshipType()),
leftItem: createSuccessfulRemoteDataObject$(new Item()),
rightItem: createSuccessfulRemoteDataObject$(new Item())
})
])));
]));
}
describe('ItemComponent', () => {
const arr1 = [
@@ -337,15 +338,15 @@ describe('ItemComponent', () => {
uuid: '1',
metadata: new MetadataMap()
});
mockItem.relationships = observableOf(new RemoteData(false, false, true, null, new PaginatedList(new PageInfo(), [
mockItem.relationships = createSuccessfulRemoteDataObject$(new PaginatedList(new PageInfo(), [
Object.assign(new Relationship(), {
uuid: '123',
id: '123',
leftItem: observableOf(new RemoteData(false, false, true, null, mockItem)),
rightItem: observableOf(new RemoteData(false, false, true, null, relatedItem)),
relationshipType: observableOf(new RemoteData(false, false, true, null, new RelationshipType()))
leftItem: createSuccessfulRemoteDataObject$(mockItem),
rightItem: createSuccessfulRemoteDataObject$(relatedItem),
relationshipType: createSuccessfulRemoteDataObject$(new RelationshipType())
})
])));
]));
mockItem.metadata[metadataField] = [
{
value: 'Second value',
@@ -369,7 +370,7 @@ describe('ItemComponent', () => {
const mockItemDataService = Object.assign({
findById: (id) => {
if (id === relatedItem.id) {
return observableOf(new RemoteData(false, false, true, null, relatedItem))
return createSuccessfulRemoteDataObject$(relatedItem)
}
}
}) as ItemDataService;

View File

@@ -8,14 +8,15 @@ import { PageInfo } from '../../../core/shared/page-info.model';
import { By } from '@angular/platform-browser';
import { createRelationshipsObservable } from '../item-types/shared/item.component.spec';
import { of as observableOf } from 'rxjs';
import { createSuccessfulRemoteDataObject$ } from '../../../shared/testing/utils';
const mockItem1: Item = Object.assign(new Item(), {
bitstreams: observableOf(new RemoteData(false, false, true, null, new PaginatedList(new PageInfo(), []))),
bitstreams: createSuccessfulRemoteDataObject$(new PaginatedList(new PageInfo(), [])),
metadata: [],
relationships: createRelationshipsObservable()
});
const mockItem2: Item = Object.assign(new Item(), {
bitstreams: observableOf(new RemoteData(false, false, true, null, new PaginatedList(new PageInfo(), []))),
bitstreams: createSuccessfulRemoteDataObject$(new PaginatedList(new PageInfo(), [])),
metadata: [],
relationships: createRelationshipsObservable()
});

View File

@@ -29,6 +29,7 @@ import { RoleDirective } from '../shared/roles/role.directive';
import { RoleService } from '../core/roles/role.service';
import { MockRoleService } from '../shared/mocks/mock-role-service';
import { SearchFixedFilterService } from '../+search-page/search-filters/search-filter/search-fixed-filter.service';
import { createSuccessfulRemoteDataObject$ } from '../shared/testing/utils';
describe('MyDSpacePageComponent', () => {
let comp: MyDSpacePageComponent;
@@ -46,7 +47,7 @@ describe('MyDSpacePageComponent', () => {
pagination.currentPage = 1;
pagination.pageSize = 10;
const sort: SortOptions = new SortOptions('score', SortDirection.DESC);
const mockResults = observableOf(new RemoteData(false, false, true, null, ['test', 'data']));
const mockResults = createSuccessfulRemoteDataObject$(['test', 'data']);
const searchServiceStub = jasmine.createSpyObj('SearchService', {
search: mockResults,
getSearchLink: '/mydspace',

View File

@@ -1,10 +1,12 @@
import { autoserialize, autoserializeAs } from 'cerialize';
import { autoserialize, inheritSerialization } from 'cerialize';
import { MetadataMap } from '../core/shared/metadata.models';
import { ListableObject } from '../shared/object-collection/shared/listable-object.model';
import { NormalizedObject } from '../core/cache/models/normalized-object.model';
/**
* Represents a normalized version of a search result object of a certain DSpaceObject
*/
@inheritSerialization(NormalizedObject)
export class NormalizedSearchResult implements ListableObject {
/**
* The UUID of the DSpaceObject that was found

View File

@@ -20,6 +20,7 @@ import { RemoteDataBuildService } from '../../../../core/cache/builders/remote-d
import { SearchConfigurationServiceStub } from '../../../../shared/testing/search-configuration-service-stub';
import { SEARCH_CONFIG_SERVICE } from '../../../../+my-dspace-page/my-dspace-page.component';
import { tap } from 'rxjs/operators';
import { createSuccessfulRemoteDataObject$ } from '../../../../shared/testing/utils';
describe('SearchFacetFilterComponent', () => {
let comp: SearchFacetFilterComponent;
@@ -61,7 +62,7 @@ describe('SearchFacetFilterComponent', () => {
let router;
const page = observableOf(0);
const mockValues = observableOf(new RemoteData(false, false, true, null, new PaginatedList(new PageInfo(), values)));
const mockValues = createSuccessfulRemoteDataObject$(new PaginatedList(new PageInfo(), values));
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [TranslateModule.forRoot(), NoopAnimationsModule, FormsModule],

View File

@@ -20,6 +20,7 @@ import { RouteService } from '../../../../shared/services/route.service';
import { RemoteDataBuildService } from '../../../../core/cache/builders/remote-data-build.service';
import { SEARCH_CONFIG_SERVICE } from '../../../../+my-dspace-page/my-dspace-page.component';
import { SearchConfigurationServiceStub } from '../../../../shared/testing/search-configuration-service-stub';
import { createSuccessfulRemoteDataObject$ } from '../../../../shared/testing/utils';
describe('SearchRangeFilterComponent', () => {
let comp: SearchRangeFilterComponent;
@@ -66,7 +67,7 @@ describe('SearchRangeFilterComponent', () => {
let router;
const page = observableOf(0);
const mockValues = observableOf(new RemoteData(false, false, true, null, new PaginatedList(new PageInfo(), values)));
const mockValues = createSuccessfulRemoteDataObject$(new PaginatedList(new PageInfo(), values));
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [TranslateModule.forRoot(), NoopAnimationsModule, FormsModule],

View File

@@ -25,6 +25,7 @@ import { RouteService } from '../shared/services/route.service';
import { SearchConfigurationServiceStub } from '../shared/testing/search-configuration-service-stub';
import { PaginatedSearchOptions } from './paginated-search-options.model';
import { SearchFixedFilterService } from './search-filters/search-filter/search-fixed-filter.service';
import { createSuccessfulRemoteDataObject$ } from '../shared/testing/utils';
let comp: SearchPageComponent;
let fixture: ComponentFixture<SearchPageComponent>;
@@ -41,7 +42,7 @@ pagination.id = 'search-results-pagination';
pagination.currentPage = 1;
pagination.pageSize = 10;
const sort: SortOptions = new SortOptions('score', SortDirection.DESC);
const mockResults = observableOf(new RemoteData(false, false, true, null, ['test', 'data']));
const mockResults = createSuccessfulRemoteDataObject$(['test', 'data']);
const searchServiceStub = jasmine.createSpyObj('SearchService', {
search: mockResults,
getSearchLink: '/search',

View File

@@ -114,7 +114,7 @@ export const objects = [
self: 'https://dspace7.4science.it/dspace-spring-rest/api/core/communities/7669c72a-3f2a-451f-a3b9-9210e7a4c02f',
id: '7669c72a-3f2a-451f-a3b9-9210e7a4c02f',
uuid: '7669c72a-3f2a-451f-a3b9-9210e7a4c02f',
type: ResourceType.Community,
type: Community.type,
metadata: {
'dc.description': [
{
@@ -168,7 +168,7 @@ export const objects = [
self: 'https://dspace7.4science.it/dspace-spring-rest/api/core/communities/9076bd16-e69a-48d6-9e41-0238cb40d863',
id: '9076bd16-e69a-48d6-9e41-0238cb40d863',
uuid: '9076bd16-e69a-48d6-9e41-0238cb40d863',
type: ResourceType.Community,
type: Community.type,
metadata: {
'dc.description': [
{

View File

@@ -21,6 +21,7 @@ import { getSucceededRemoteData } from '../../core/shared/operators';
import { SearchFilter } from '../search-filter.model';
import { DSpaceObjectType } from '../../core/shared/dspace-object-type.model';
import { SearchFixedFilterService } from '../search-filters/search-filter/search-fixed-filter.service';
import { createSuccessfulRemoteDataObject$ } from '../../shared/testing/utils';
/**
* Service that performs all actions that have to do with the current search configuration
@@ -269,7 +270,7 @@ export class SearchConfigurationService implements OnDestroy {
scope: this.defaultScope,
query: this.defaultQuery
});
this._defaults = observableOf(new RemoteData(false, false, true, null, options));
this._defaults = createSuccessfulRemoteDataObject$(options);
}
return this._defaults;
}

View File

@@ -28,6 +28,7 @@ import { DSpaceObjectDataService } from '../../core/data/dspace-object-data.serv
import { map } from 'rxjs/operators';
import { RouteService } from '../../shared/services/route.service';
import { routeServiceStub } from '../../shared/testing/route-service-stub';
import { createSuccessfulRemoteDataObject$ } from '../../shared/testing/utils';
@Component({ template: '' })
class DummyComponent {
@@ -91,7 +92,7 @@ describe('SearchService', () => {
);
},
aggregate: (input: Array<Observable<RemoteData<any>>>): Observable<RemoteData<any[]>> => {
return observableOf(new RemoteData(false, false, true, null, []));
return createSuccessfulRemoteDataObject$([]);
}
};

View File

@@ -1,6 +1,6 @@
import { combineLatest as observableCombineLatest, Observable, of as observableOf } from 'rxjs';
import { Injectable, OnDestroy } from '@angular/core';
import { NavigationExtras, PRIMARY_OUTLET, Router, UrlSegmentGroup } from '@angular/router';
import { NavigationExtras, Router } from '@angular/router';
import { first, map, switchMap } from 'rxjs/operators';
import { RemoteDataBuildService } from '../../core/cache/builders/remote-data-build.service';
import {
@@ -40,7 +40,6 @@ import { PaginatedSearchOptions } from '../paginated-search-options.model';
import { Community } from '../../core/shared/community.model';
import { CommunityDataService } from '../../core/data/community-data.service';
import { ViewMode } from '../../core/shared/view-mode.model';
import { ResourceType } from '../../core/shared/resource-type';
import { DSpaceObjectDataService } from '../../core/data/dspace-object-data.service';
import { RouteService } from '../../shared/services/route.service';
@@ -296,7 +295,7 @@ export class SearchService implements OnDestroy {
const scopeObject: Observable<RemoteData<DSpaceObject>> = this.dspaceObjectService.findById(scopeId).pipe(getSucceededRemoteData());
const scopeList: Observable<DSpaceObject[]> = scopeObject.pipe(
switchMap((dsoRD: RemoteData<DSpaceObject>) => {
if (dsoRD.payload.type === ResourceType.Community) {
if ((dsoRD.payload as any).type === Community.type.value) {
const community: Community = dsoRD.payload as Community;
return observableCombineLatest(community.subcommunities, community.collections).pipe(
map(([subCommunities, collections]) => {

View File

@@ -20,4 +20,4 @@ import { SubmissionEditComponent } from '../submission/edit/submission-edit.comp
/**
* This module defines the default component to load when navigating to the workflowitems edit page path.
*/
export class WorkflowitemsEditPageRoutingModule { }
export class WorkflowItemsEditPageRoutingModule { }

View File

@@ -1,12 +1,12 @@
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { SharedModule } from '../shared/shared.module';
import { WorkflowitemsEditPageRoutingModule } from './workflowitems-edit-page-routing.module';
import { WorkflowItemsEditPageRoutingModule } from './workflowitems-edit-page-routing.module';
import { SubmissionModule } from '../submission/submission.module';
@NgModule({
imports: [
WorkflowitemsEditPageRoutingModule,
WorkflowItemsEditPageRoutingModule,
CommonModule,
SharedModule,
SubmissionModule,
@@ -16,6 +16,6 @@ import { SubmissionModule } from '../submission/submission.module';
/**
* This module handles all modules that need to access the workflowitems edit page.
*/
export class WorkflowitemsEditPageModule {
export class WorkflowItemsEditPageModule {
}

View File

@@ -32,7 +32,7 @@ export function getCommunityModulePath() {
{ path: 'logout', loadChildren: './+logout-page/logout-page.module#LogoutPageModule' },
{ path: 'submit', loadChildren: './+submit-page/submit-page.module#SubmitPageModule' },
{ path: 'workspaceitems', loadChildren: './+workspaceitems-edit-page/workspaceitems-edit-page.module#WorkspaceitemsEditPageModule' },
{ path: 'workflowitems', loadChildren: './+workflowitems-edit-page/workflowitems-edit-page.module#WorkflowitemsEditPageModule' },
{ path: 'workflowitems', loadChildren: './+workflowitems-edit-page/workflowitems-edit-page.module#WorkflowItemsEditPageModule' },
{ path: '**', pathMatch: 'full', component: PageNotFoundComponent },
])
],

View File

@@ -1,29 +0,0 @@
import { AuthType } from './auth-type';
import { GenericConstructor } from '../shared/generic-constructor';
import { NormalizedAuthStatus } from './models/normalized-auth-status.model';
import { NormalizedEPerson } from '../eperson/models/normalized-eperson.model';
import { NormalizedObject } from '../cache/models/normalized-object.model';
import { CacheableObject } from '../cache/object-cache.reducer';
import { NormalizedGroup } from '../eperson/models/normalized-group.model';
export class AuthObjectFactory {
public static getConstructor(type): GenericConstructor<NormalizedObject<CacheableObject>> {
switch (type) {
case AuthType.EPerson: {
return NormalizedEPerson
}
case AuthType.Group: {
return NormalizedGroup
}
case AuthType.Status: {
return NormalizedAuthStatus
}
default: {
return undefined;
}
}
}
}

View File

@@ -35,95 +35,103 @@ describe('AuthResponseParsingService', () => {
});
describe('parse', () => {
const validRequest = new AuthPostRequest(
'69f375b5-19f4-4453-8c7a-7dc5c55aafbb',
'https://rest.api/dspace-spring-rest/api/authn/login',
'password=test&user=myself@testshib.org');
let validRequest;
let validRequest2;
let validResponse;
let validResponse1;
let validResponse2;
beforeEach(() => {
const validRequest2 = new AuthGetRequest(
'69f375b5-19f4-4453-8c7a-7dc5c55aafbb',
'https://rest.api/dspace-spring-rest/api/authn/status');
validRequest = new AuthPostRequest(
'69f375b5-19f4-4453-8c7a-7dc5c55aafbb',
'https://rest.api/dspace-spring-rest/api/authn/login',
'password=test&user=myself@testshib.org');
const validResponse = {
payload: {
authenticated: true,
id: null,
okay: true,
token: {
accessToken: 'eyJhbGciOiJIUzI1NiJ9.eyJlaWQiOiI0ZGM3MGFiNS1jZDczLTQ5MmYtYjAwNy0zMTc5ZDJkOTI5NmIiLCJzZyI6W10sImV4cCI6MTUyNjMxODMyMn0.ASmvcbJFBfzhN7D5ncloWnaVZr5dLtgTuOgHaCKiimc',
expires: 1526318322000
},
} as AuthStatus,
statusCode: 200,
statusText: '200'
};
validRequest2 = new AuthGetRequest(
'69f375b5-19f4-4453-8c7a-7dc5c55aafbb',
'https://rest.api/dspace-spring-rest/api/authn/status');
const validResponse1 = {
payload: {},
statusCode: 404,
statusText: '404'
};
validResponse = {
payload: {
authenticated: true,
id: null,
okay: true,
token: {
accessToken: 'eyJhbGciOiJIUzI1NiJ9.eyJlaWQiOiI0ZGM3MGFiNS1jZDczLTQ5MmYtYjAwNy0zMTc5ZDJkOTI5NmIiLCJzZyI6W10sImV4cCI6MTUyNjMxODMyMn0.ASmvcbJFBfzhN7D5ncloWnaVZr5dLtgTuOgHaCKiimc',
expires: 1526318322000
},
} as AuthStatus,
statusCode: 200,
statusText: '200'
};
const validResponse2 = {
payload: {
authenticated: true,
id: null,
okay: true,
type: 'status',
_embedded: {
eperson: {
canLogIn: true,
email: 'myself@testshib.org',
groups: [],
handle: null,
id: '4dc70ab5-cd73-492f-b007-3179d2d9296b',
lastActive: '2018-05-14T17:03:31.277+0000',
metadata: {
'eperson.firstname': [
{
language: null,
value: 'User'
validResponse1 = {
payload: {},
statusCode: 404,
statusText: '404'
};
validResponse2 = {
payload: {
authenticated: true,
id: null,
okay: true,
type: 'status',
_embedded: {
eperson: {
canLogIn: true,
email: 'myself@testshib.org',
groups: [],
handle: null,
id: '4dc70ab5-cd73-492f-b007-3179d2d9296b',
lastActive: '2018-05-14T17:03:31.277+0000',
metadata: {
'eperson.firstname': [
{
language: null,
value: 'User'
}
],
'eperson.lastname': [
{
language: null,
value: 'Test'
}
],
'eperson.language': [
{
language: null,
value: 'en'
}
]
},
name: 'User Test',
netid: 'myself@testshib.org',
requireCertificate: false,
selfRegistered: false,
type: 'eperson',
uuid: '4dc70ab5-cd73-492f-b007-3179d2d9296b',
_links: {
self: {
href: 'https://hasselt-dspace.dev01.4science.it/dspace-spring-rest/api/eperson/epersons/4dc70ab5-cd73-492f-b007-3179d2d9296b'
}
],
'eperson.lastname': [
{
language: null,
value: 'Test'
}
],
'eperson.language': [
{
language: null,
value: 'en'
}
]
},
name: 'User Test',
netid: 'myself@testshib.org',
requireCertificate: false,
selfRegistered: false,
type: 'eperson',
uuid: '4dc70ab5-cd73-492f-b007-3179d2d9296b',
_links: {
self: {
href: 'https://hasselt-dspace.dev01.4science.it/dspace-spring-rest/api/eperson/epersons/4dc70ab5-cd73-492f-b007-3179d2d9296b'
}
}
},
_links: {
eperson: {
href: 'https://hasselt-dspace.dev01.4science.it/dspace-spring-rest/api/eperson/epersons/4dc70ab5-cd73-492f-b007-3179d2d9296b'
},
self: {
href: 'https://hasselt-dspace.dev01.4science.it/dspace-spring-rest/api/authn/status'
}
}
},
_links: {
eperson: {
href: 'https://hasselt-dspace.dev01.4science.it/dspace-spring-rest/api/eperson/epersons/4dc70ab5-cd73-492f-b007-3179d2d9296b'
},
self: {
href: 'https://hasselt-dspace.dev01.4science.it/dspace-spring-rest/api/authn/status'
}
}
},
statusCode: 200,
statusText: '200'
statusCode: 200,
statusText: '200'
};
};
});
it('should return a AuthStatusResponse if data contains a valid AuthStatus object as payload', () => {
const response = service.parse(validRequest, validResponse);

View File

@@ -1,6 +1,5 @@
import { Inject, Injectable } from '@angular/core';
import { AuthObjectFactory } from './auth-object-factory';
import { BaseResponseParsingService } from '../data/base-response-parsing.service';
import { AuthStatusResponse, RestResponse } from '../cache/response.models';
import { DSpaceRESTV2Response } from '../dspace-rest-v2/dspace-rest-v2-response.model';
@@ -10,7 +9,6 @@ import { isNotEmpty } from '../../shared/empty.util';
import { ObjectCacheService } from '../cache/object-cache.service';
import { ResponseParsingService } from '../data/parsing.service';
import { RestRequest } from '../data/request.models';
import { AuthType } from './auth-type';
import { AuthStatus } from './models/auth-status.model';
import { NormalizedAuthStatus } from './models/normalized-auth-status.model';
import { NormalizedObject } from '../cache/models/normalized-object.model';
@@ -18,7 +16,6 @@ import { NormalizedObject } from '../cache/models/normalized-object.model';
@Injectable()
export class AuthResponseParsingService extends BaseResponseParsingService implements ResponseParsingService {
protected objectFactory = AuthObjectFactory;
protected toCache = true;
constructor(@Inject(GLOBAL_CONFIG) protected EnvConfig: GlobalConfig,
@@ -28,7 +25,7 @@ export class AuthResponseParsingService extends BaseResponseParsingService imple
parse(request: RestRequest, data: DSpaceRESTV2Response): RestResponse {
if (isNotEmpty(data.payload) && isNotEmpty(data.payload._links) && (data.statusCode === 200)) {
const response = this.process<NormalizedObject<AuthStatus>, AuthType>(data.payload, request.uuid);
const response = this.process<NormalizedObject<AuthStatus>>(data.payload, request.uuid);
return new AuthStatusResponse(response, data.statusCode, data.statusText);
} else {
return new AuthStatusResponse(data.payload as NormalizedAuthStatus, data.statusCode, data.statusText);

View File

@@ -1,5 +0,0 @@
export enum AuthType {
EPerson = 'eperson',
Status = 'status',
Group = 'group'
}

View File

@@ -4,20 +4,51 @@ import { EPerson } from '../../eperson/models/eperson.model';
import { RemoteData } from '../../data/remote-data';
import { Observable } from 'rxjs';
import { CacheableObject } from '../../cache/object-cache.reducer';
import { ResourceType } from '../../shared/resource-type';
/**
* Object that represents the authenticated status of a user
*/
export class AuthStatus implements CacheableObject {
static type = new ResourceType('status');
/**
* The unique identifier of this auth status
*/
id: string;
/**
* The unique uuid of this auth status
*/
uuid: string;
/**
* True if REST API is up and running, should never return false
*/
okay: boolean;
/**
* If the auth status represents an authenticated state
*/
authenticated: boolean;
/**
* Authentication error if there was one for this status
*/
error?: AuthError;
/**
* The eperson of this auth status
*/
eperson: Observable<RemoteData<EPerson>>;
/**
* True if the token is valid, false if there was no token or the token wasn't valid
*/
token?: AuthTokenInfo;
/**
* The self link of this auth status' REST object
*/
self: string;
}

View File

@@ -1,16 +1,22 @@
import { AuthStatus } from './auth-status.model';
import { autoserialize, autoserializeAs, inheritSerialization } from 'cerialize';
import { mapsTo, relationship } from '../../cache/builders/build-decorators';
import { ResourceType } from '../../shared/resource-type';
import { NormalizedObject } from '../../cache/models/normalized-object.model';
import { IDToUUIDSerializer } from '../../cache/id-to-uuid-serializer';
import { EPerson } from '../../eperson/models/eperson.model';
@mapsTo(AuthStatus)
@inheritSerialization(NormalizedObject)
export class NormalizedAuthStatus extends NormalizedObject<AuthStatus> {
/**
* The unique identifier of this auth status
*/
@autoserialize
id: string;
/**
* The unique generated uuid of this auth status
*/
@autoserializeAs(new IDToUUIDSerializer('auth-status'), 'id')
uuid: string;
@@ -26,7 +32,10 @@ export class NormalizedAuthStatus extends NormalizedObject<AuthStatus> {
@autoserialize
authenticated: boolean;
@relationship(ResourceType.EPerson, false)
/**
* The self link to the eperson of this auth status
*/
@relationship(EPerson, false)
@autoserialize
eperson: string;
}

View File

@@ -1,8 +1,9 @@
import { Injectable } from '@angular/core';
import { Observable, of as observableOf } from 'rxjs';
import { distinctUntilChanged, map, startWith, take } from 'rxjs/operators';
import { distinctUntilChanged, map, startWith } from 'rxjs/operators';
import {
ensureArrayHasValue, hasValue,
ensureArrayHasValue,
hasValue,
hasValueOperator,
isEmpty,
isNotEmpty,
@@ -23,7 +24,9 @@ import { BrowseEntry } from '../shared/browse-entry.model';
import { HALEndpointService } from '../shared/hal-endpoint.service';
import {
configureRequest,
filterSuccessfulResponses, getBrowseDefinitionLinks, getFirstOccurrence,
filterSuccessfulResponses,
getBrowseDefinitionLinks,
getFirstOccurrence,
getRemoteDataPayload,
getRequestFromRequestHref
} from '../shared/operators';
@@ -32,7 +35,6 @@ import { Item } from '../shared/item.model';
import { DSpaceObject } from '../shared/dspace-object.model';
import { BrowseEntrySearchOptions } from './browse-entry-search-options.model';
import { GenericSuccessResponse } from '../cache/response.models';
import { RequestEntry } from '../data/request.reducer';
/**
* The service handling all browse requests

View File

@@ -1,23 +1,59 @@
import 'reflect-metadata';
import { GenericConstructor } from '../../shared/generic-constructor';
import { CacheableObject } from '../object-cache.reducer';
import { CacheableObject, TypedObject } from '../object-cache.reducer';
import { ResourceType } from '../../shared/resource-type';
const mapsToMetadataKey = Symbol('mapsTo');
const relationshipKey = Symbol('relationship');
const relationshipMap = new Map();
const typeMap = new Map();
export function mapsTo(value: GenericConstructor<CacheableObject>) {
return Reflect.metadata(mapsToMetadataKey, value);
/**
* Decorator function to map a normalized class to it's not-normalized counter part class
* It will also maps a type to the matching class
* @param value The not-normalized class to map to
*/
export function mapsTo(value: GenericConstructor<TypedObject>) {
return function decorator(objectConstructor: GenericConstructor<TypedObject>) {
Reflect.defineMetadata(mapsToMetadataKey, value, objectConstructor);
mapsToType((value as any).type, objectConstructor);
}
}
/**
* Maps a type to the matching class
* @param value The resourse type
* @param objectConstructor The class to map to
*/
function mapsToType(value: ResourceType, objectConstructor: GenericConstructor<TypedObject>) {
if (!objectConstructor || !value) {
return;
}
typeMap.set(value.value, objectConstructor);
}
/**
* Returns the mapped class for the given normalized class
* @param target The normalized class
*/
export function getMapsTo(target: any) {
return Reflect.getOwnMetadata(mapsToMetadataKey, target);
}
export function relationship(value: ResourceType, isList: boolean = false): any {
/**
* Returns the mapped class for the given type
* @param type The resource type
*/
export function getMapsToType(type: string | ResourceType) {
if (typeof(type) === 'object') {
type = (type as ResourceType).value;
}
return typeMap.get(type);
}
export function relationship<T extends CacheableObject>(value: GenericConstructor<T>, isList: boolean = false): any {
return function r(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
if (!target || !propertyKey) {
return;
@@ -28,8 +64,10 @@ export function relationship(value: ResourceType, isList: boolean = false): any
metaDataList.push(propertyKey);
}
relationshipMap.set(target.constructor, metaDataList);
return Reflect.metadata(relationshipKey, { resourceType: value, isList }).apply(this, arguments);
return Reflect.metadata(relationshipKey, {
resourceType: (value as any).type.value,
isList
}).apply(this, arguments);
};
}

View File

@@ -1,9 +1,8 @@
import { Injectable } from '@angular/core';
import { NormalizedObject } from '../models/normalized-object.model';
import { CacheableObject } from '../object-cache.reducer';
import { getRelationships } from './build-decorators';
import { NormalizedObjectFactory } from '../models/normalized-object-factory';
import { getMapsToType, getRelationships } from './build-decorators';
import { hasValue, isNotEmpty } from '../../../shared/empty.util';
import { TypedObject } from '../object-cache.reducer';
/**
* Return true if halObj has a value for `_links.self`
@@ -35,8 +34,8 @@ export class NormalizedObjectBuildService {
*
* @param {TDomain} domainModel a domain model
*/
normalize<T extends CacheableObject>(domainModel: T): NormalizedObject<T> {
const normalizedConstructor = NormalizedObjectFactory.getConstructor(domainModel.type);
normalize<T extends TypedObject>(domainModel: T): NormalizedObject<T> {
const normalizedConstructor = getMapsToType((domainModel as any).type);
const relationships = getRelationships(normalizedConstructor) || [];
const normalizedModel = Object.assign({}, domainModel) as any;

View File

@@ -4,6 +4,7 @@ import { PaginatedList } from '../../data/paginated-list';
import { PageInfo } from '../../shared/page-info.model';
import { RemoteData } from '../../data/remote-data';
import { of as observableOf } from 'rxjs';
import { createSuccessfulRemoteDataObject } from '../../../shared/testing/utils';
const pageInfo = new PageInfo();
const array = [
@@ -29,8 +30,8 @@ const array = [
})
];
const paginatedList = new PaginatedList(pageInfo, array);
const arrayRD = new RemoteData(false, false, true, undefined, array);
const paginatedListRD = new RemoteData(false, false, true, undefined, paginatedList);
const arrayRD = createSuccessfulRemoteDataObject(array);
const paginatedListRD = createSuccessfulRemoteDataObject(paginatedList);
describe('RemoteDataBuildService', () => {
let service: RemoteDataBuildService;

View File

@@ -21,7 +21,8 @@ import {
getRequestFromRequestUUID,
getResourceLinksFromResponse
} from '../../shared/operators';
import { CacheableObject } from '../object-cache.reducer';
import { CacheableObject, TypedObject } from '../object-cache.reducer';
import { createSuccessfulRemoteDataObject$ } from '../../../shared/testing/utils';
@Injectable()
export class RemoteDataBuildService {
@@ -200,7 +201,7 @@ export class RemoteDataBuildService {
aggregate<T>(input: Array<Observable<RemoteData<T>>>): Observable<RemoteData<T[]>> {
if (isEmpty(input)) {
return observableOf(new RemoteData(false, false, true, null, []));
return createSuccessfulRemoteDataObject$([]);
}
return observableCombineLatest(...input).pipe(

View File

@@ -1,6 +1,5 @@
import { autoserialize, autoserializeAs, inheritSerialization } from 'cerialize';
import { ItemType } from '../../../shared/item-relationships/item-type.model';
import { ResourceType } from '../../../shared/resource-type';
import { mapsTo } from '../../builders/build-decorators';
import { NormalizedObject } from '../normalized-object.model';
import { IDToUUIDSerializer } from '../../id-to-uuid-serializer';
@@ -11,7 +10,6 @@ import { IDToUUIDSerializer } from '../../id-to-uuid-serializer';
@mapsTo(ItemType)
@inheritSerialization(NormalizedObject)
export class NormalizedItemType extends NormalizedObject<ItemType> {
/**
* The label that describes the ResourceType of the Item
*/
@@ -27,6 +25,6 @@ export class NormalizedItemType extends NormalizedObject<ItemType> {
/**
* The universally unique identifier of this ItemType
*/
@autoserializeAs(new IDToUUIDSerializer(ResourceType.ItemType), 'id')
@autoserializeAs(new IDToUUIDSerializer(ItemType.type.value), 'id')
uuid: string;
}

View File

@@ -5,6 +5,7 @@ import { mapsTo, relationship } from '../../builders/build-decorators';
import { NormalizedDSpaceObject } from '../normalized-dspace-object.model';
import { NormalizedObject } from '../normalized-object.model';
import { IDToUUIDSerializer } from '../../id-to-uuid-serializer';
import { ItemType } from '../../../shared/item-relationships/item-type.model';
/**
* Normalized model class for a DSpace RelationshipType
@@ -12,7 +13,6 @@ import { IDToUUIDSerializer } from '../../id-to-uuid-serializer';
@mapsTo(RelationshipType)
@inheritSerialization(NormalizedDSpaceObject)
export class NormalizedRelationshipType extends NormalizedObject<RelationshipType> {
/**
* The identifier of this RelationshipType
*/
@@ -59,19 +59,19 @@ export class NormalizedRelationshipType extends NormalizedObject<RelationshipTyp
* The type of Item found to the left of this RelationshipType
*/
@autoserialize
@relationship(ResourceType.ItemType, false)
@relationship(ItemType, false)
leftType: string;
/**
* The type of Item found to the right of this RelationshipType
*/
@autoserialize
@relationship(ResourceType.ItemType, false)
@relationship(ItemType, false)
rightType: string;
/**
* The universally unique identifier of this RelationshipType
*/
@autoserializeAs(new IDToUUIDSerializer(ResourceType.RelationshipType), 'id')
@autoserializeAs(new IDToUUIDSerializer(RelationshipType.type.value), 'id')
uuid: string;
}

View File

@@ -1,9 +1,10 @@
import { autoserialize, autoserializeAs, inheritSerialization } from 'cerialize';
import { Relationship } from '../../../shared/item-relationships/relationship.model';
import { ResourceType } from '../../../shared/resource-type';
import { mapsTo, relationship } from '../../builders/build-decorators';
import { NormalizedObject } from '../normalized-object.model';
import { IDToUUIDSerializer } from '../../id-to-uuid-serializer';
import { RelationshipType } from '../../../shared/item-relationships/relationship-type.model';
import { Item } from '../../../shared/item.model';
/**
* Normalized model class for a DSpace Relationship
@@ -22,14 +23,14 @@ export class NormalizedRelationship extends NormalizedObject<Relationship> {
* The item to the left of this relationship
*/
@autoserialize
@relationship(ResourceType.Item, false)
@relationship(Item, false)
leftItem: string;
/**
* The item to the right of this relationship
*/
@autoserialize
@relationship(ResourceType.Item, false)
@relationship(Item, false)
rightItem: string;
/**
@@ -48,12 +49,12 @@ export class NormalizedRelationship extends NormalizedObject<Relationship> {
* The type of Relationship
*/
@autoserialize
@relationship(ResourceType.RelationshipType, false)
@relationship(RelationshipType, false)
relationshipType: string;
/**
* The universally unique identifier of this Relationship
*/
@autoserializeAs(new IDToUUIDSerializer(ResourceType.Relationship), 'id')
@autoserializeAs(new IDToUUIDSerializer(Relationship.type.value), 'id')
uuid: string;
}

View File

@@ -12,7 +12,6 @@ import { SupportLevel } from './support-level.model';
@mapsTo(BitstreamFormat)
@inheritSerialization(NormalizedObject)
export class NormalizedBitstreamFormat extends NormalizedObject<BitstreamFormat> {
/**
* Short description of this Bitstream Format
*/

View File

@@ -1,9 +1,10 @@
import { inheritSerialization, autoserialize } from 'cerialize';
import { autoserialize, inheritSerialization } from 'cerialize';
import { NormalizedDSpaceObject } from './normalized-dspace-object.model';
import { Bitstream } from '../../shared/bitstream.model';
import { mapsTo, relationship } from '../builders/build-decorators';
import { ResourceType } from '../../shared/resource-type';
import { Item } from '../../shared/item.model';
import { BitstreamFormat } from '../../shared/bitstream-format.model';
/**
* Normalized model class for a DSpace Bitstream
@@ -11,7 +12,6 @@ import { ResourceType } from '../../shared/resource-type';
@mapsTo(Bitstream)
@inheritSerialization(NormalizedDSpaceObject)
export class NormalizedBitstream extends NormalizedDSpaceObject<Bitstream> {
/**
* The size of this bitstream in bytes
*/
@@ -28,7 +28,7 @@ export class NormalizedBitstream extends NormalizedDSpaceObject<Bitstream> {
* The format of this Bitstream
*/
@autoserialize
@relationship(ResourceType.BitstreamFormat, false)
@relationship(BitstreamFormat, false)
format: string;
/**
@@ -41,14 +41,14 @@ export class NormalizedBitstream extends NormalizedDSpaceObject<Bitstream> {
* An array of Bundles that are direct parents of this Bitstream
*/
@autoserialize
@relationship(ResourceType.Item, true)
@relationship(Item, true)
parents: string[];
/**
* The Bundle that owns this Bitstream
*/
@autoserialize
@relationship(ResourceType.Item, false)
@relationship(Item, false)
owner: string;
/**

View File

@@ -3,7 +3,7 @@ import { autoserialize, inheritSerialization } from 'cerialize';
import { NormalizedDSpaceObject } from './normalized-dspace-object.model';
import { Bundle } from '../../shared/bundle.model';
import { mapsTo, relationship } from '../builders/build-decorators';
import { ResourceType } from '../../shared/resource-type';
import { Bitstream } from '../../shared/bitstream.model';
/**
* Normalized model class for a DSpace Bundle
@@ -15,7 +15,7 @@ export class NormalizedBundle extends NormalizedDSpaceObject<Bundle> {
* The primary bitstream of this Bundle
*/
@autoserialize
@relationship(ResourceType.Bitstream, false)
@relationship(Bitstream, false)
primaryBitstream: string;
/**
@@ -32,7 +32,7 @@ export class NormalizedBundle extends NormalizedDSpaceObject<Bundle> {
* List of Bitstreams that are part of this Bundle
*/
@autoserialize
@relationship(ResourceType.Bitstream, true)
@relationship(Bitstream, true)
bitstreams: string[];
}

View File

@@ -3,7 +3,15 @@ import { autoserialize, deserialize, inheritSerialization } from 'cerialize';
import { NormalizedDSpaceObject } from './normalized-dspace-object.model';
import { Collection } from '../../shared/collection.model';
import { mapsTo, relationship } from '../builders/build-decorators';
import { ResourceType } from '../../shared/resource-type';
import { NormalizedResourcePolicy } from './normalized-resource-policy.model';
import { NormalizedBitstream } from './normalized-bitstream.model';
import { NormalizedCommunity } from './normalized-community.model';
import { NormalizedItem } from './normalized-item.model';
import { License } from '../../shared/license.model';
import { ResourcePolicy } from '../../shared/resource-policy.model';
import { Bitstream } from '../../shared/bitstream.model';
import { Community } from '../../shared/community.model';
import { Item } from '../../shared/item.model';
/**
* Normalized model class for a DSpace Collection
@@ -22,42 +30,42 @@ export class NormalizedCollection extends NormalizedDSpaceObject<Collection> {
* The Bitstream that represents the license of this Collection
*/
@autoserialize
@relationship(ResourceType.License, false)
@relationship(License, false)
license: string;
/**
* The Bitstream that represents the default Access Conditions of this Collection
*/
@autoserialize
@relationship(ResourceType.ResourcePolicy, false)
@relationship(ResourcePolicy, false)
defaultAccessConditions: string;
/**
* The Bitstream that represents the logo of this Collection
*/
@deserialize
@relationship(ResourceType.Bitstream, false)
@relationship(Bitstream, false)
logo: string;
/**
* An array of Communities that are direct parents of this Collection
*/
@deserialize
@relationship(ResourceType.Community, true)
@relationship(Community, true)
parents: string[];
/**
* The Community that owns this Collection
*/
@deserialize
@relationship(ResourceType.Community, false)
@relationship(Community, false)
owner: string;
/**
* List of Items that are part of (not necessarily owned by) this Collection
*/
@deserialize
@relationship(ResourceType.Item, true)
@relationship(Item, true)
items: string[];
}

View File

@@ -1,9 +1,13 @@
import { autoserialize, deserialize, inheritSerialization, serialize } from 'cerialize';
import { autoserialize, deserialize, inheritSerialization } from 'cerialize';
import { NormalizedDSpaceObject } from './normalized-dspace-object.model';
import { Community } from '../../shared/community.model';
import { mapsTo, relationship } from '../builders/build-decorators';
import { ResourceType } from '../../shared/resource-type';
import { NormalizedBitstream } from './normalized-bitstream.model';
import { NormalizedCollection } from './normalized-collection.model';
import { Bitstream } from '../../shared/bitstream.model';
import { Collection } from '../../shared/collection.model';
/**
* Normalized model class for a DSpace Community
@@ -11,7 +15,6 @@ import { ResourceType } from '../../shared/resource-type';
@mapsTo(Community)
@inheritSerialization(NormalizedDSpaceObject)
export class NormalizedCommunity extends NormalizedDSpaceObject<Community> {
/**
* A string representing the unique handle of this Community
*/
@@ -22,32 +25,32 @@ export class NormalizedCommunity extends NormalizedDSpaceObject<Community> {
* The Bitstream that represents the logo of this Community
*/
@deserialize
@relationship(ResourceType.Bitstream, false)
@relationship(Bitstream, false)
logo: string;
/**
* An array of Communities that are direct parents of this Community
*/
@deserialize
@relationship(ResourceType.Community, true)
@relationship(Community, true)
parents: string[];
/**
* The Community that owns this Community
*/
@deserialize
@relationship(ResourceType.Community, false)
@relationship(Community, false)
owner: string;
/**
* List of Collections that are owned by this Community
*/
@deserialize
@relationship(ResourceType.Collection, true)
@relationship(Collection, true)
collections: string[];
@deserialize
@relationship(ResourceType.Community, true)
@relationship(Community, true)
subcommunities: string[];
}

View File

@@ -1,15 +1,15 @@
import { autoserializeAs, deserializeAs } from 'cerialize';
import { autoserializeAs, deserializeAs, autoserialize } from 'cerialize';
import { DSpaceObject } from '../../shared/dspace-object.model';
import { MetadataMap, MetadataMapSerializer } from '../../shared/metadata.models';
import { ResourceType } from '../../shared/resource-type';
import { mapsTo } from '../builders/build-decorators';
import { NormalizedObject } from './normalized-object.model';
import { TypedObject } from '../object-cache.reducer';
/**
* An model class for a DSpaceObject.
*/
@mapsTo(DSpaceObject)
export class NormalizedDSpaceObject<T extends DSpaceObject> extends NormalizedObject<T> {
export class NormalizedDSpaceObject<T extends DSpaceObject> extends NormalizedObject<T> implements TypedObject {
/**
* The link to the rest endpoint where this object can be found
@@ -38,8 +38,8 @@ export class NormalizedDSpaceObject<T extends DSpaceObject> extends NormalizedOb
/**
* A string representing the kind of DSpaceObject, e.g. community, item, …
*/
@autoserializeAs(String)
type: ResourceType;
@autoserialize
type: string;
/**
* All metadata of this DSpaceObject

View File

@@ -4,6 +4,12 @@ import { NormalizedDSpaceObject } from './normalized-dspace-object.model';
import { Item } from '../../shared/item.model';
import { mapsTo, relationship } from '../builders/build-decorators';
import { ResourceType } from '../../shared/resource-type';
import { NormalizedCollection } from './normalized-collection.model';
import { NormalizedBitstream } from './normalized-bitstream.model';
import { NormalizedRelationship } from './items/normalized-relationship.model';
import { Collection } from '../../shared/collection.model';
import { Bitstream } from '../../shared/bitstream.model';
import { Relationship } from '../../shared/item-relationships/relationship.model';
/**
* Normalized model class for a DSpace Item
@@ -46,25 +52,25 @@ export class NormalizedItem extends NormalizedDSpaceObject<Item> {
* An array of Collections that are direct parents of this Item
*/
@deserialize
@relationship(ResourceType.Collection, true)
@relationship(Collection, true)
parents: string[];
/**
* The Collection that owns this Item
*/
@deserialize
@relationship(ResourceType.Collection, false)
@relationship(Collection, false)
owningCollection: string;
/**
* List of Bitstreams that are owned by this Item
*/
@deserialize
@relationship(ResourceType.Bitstream, true)
@relationship(Bitstream, true)
bitstreams: string[];
@autoserialize
@relationship(ResourceType.Relationship, true)
@relationship(Relationship, true)
relationships: string[];
}

View File

@@ -1,104 +0,0 @@
import { NormalizedItemType } from './items/normalized-item-type.model';
import { NormalizedRelationshipType } from './items/normalized-relationship-type.model';
import { NormalizedRelationship } from './items/normalized-relationship.model';
import { NormalizedBitstream } from './normalized-bitstream.model';
import { NormalizedBundle } from './normalized-bundle.model';
import { NormalizedItem } from './normalized-item.model';
import { NormalizedCollection } from './normalized-collection.model';
import { GenericConstructor } from '../../shared/generic-constructor';
import { NormalizedCommunity } from './normalized-community.model';
import { ResourceType } from '../../shared/resource-type';
import { NormalizedObject } from './normalized-object.model';
import { NormalizedLicense } from './normalized-license.model';
import { NormalizedResourcePolicy } from './normalized-resource-policy.model';
import { NormalizedWorkspaceItem } from '../../submission/models/normalized-workspaceitem.model';
import { NormalizedEPerson } from '../../eperson/models/normalized-eperson.model';
import { NormalizedGroup } from '../../eperson/models/normalized-group.model';
import { NormalizedWorkflowItem } from '../../submission/models/normalized-workflowitem.model';
import { NormalizedClaimedTask } from '../../tasks/models/normalized-claimed-task-object.model';
import { NormalizedPoolTask } from '../../tasks/models/normalized-pool-task-object.model';
import { NormalizedBitstreamFormat } from './normalized-bitstream-format.model';
import { NormalizedMetadataSchema } from '../../metadata/normalized-metadata-schema.model';
import { CacheableObject } from '../object-cache.reducer';
import { NormalizedSubmissionDefinitionsModel } from '../../config/models/normalized-config-submission-definitions.model';
import { NormalizedSubmissionFormsModel } from '../../config/models/normalized-config-submission-forms.model';
import { NormalizedSubmissionSectionModel } from '../../config/models/normalized-config-submission-section.model';
export class NormalizedObjectFactory {
public static getConstructor(type: ResourceType): GenericConstructor<NormalizedObject<CacheableObject>> {
switch (type) {
case ResourceType.Bitstream: {
return NormalizedBitstream
}
case ResourceType.Bundle: {
return NormalizedBundle
}
case ResourceType.Item: {
return NormalizedItem
}
case ResourceType.Collection: {
return NormalizedCollection
}
case ResourceType.Community: {
return NormalizedCommunity
}
case ResourceType.BitstreamFormat: {
return NormalizedBitstreamFormat
}
case ResourceType.License: {
return NormalizedLicense
}
case ResourceType.ResourcePolicy: {
return NormalizedResourcePolicy
}
case ResourceType.Relationship: {
return NormalizedRelationship
}
case ResourceType.RelationshipType: {
return NormalizedRelationshipType
}
case ResourceType.ItemType: {
return NormalizedItemType
}
case ResourceType.EPerson: {
return NormalizedEPerson
}
case ResourceType.Group: {
return NormalizedGroup
}
case ResourceType.MetadataSchema: {
return NormalizedMetadataSchema
}
case ResourceType.MetadataField: {
return NormalizedGroup
}
case ResourceType.Workspaceitem: {
return NormalizedWorkspaceItem
}
case ResourceType.Workflowitem: {
return NormalizedWorkflowItem
}
case ResourceType.ClaimedTask: {
return NormalizedClaimedTask
}
case ResourceType.PoolTask: {
return NormalizedPoolTask
}
case ResourceType.SubmissionDefinition:
case ResourceType.SubmissionDefinitions: {
return NormalizedSubmissionDefinitionsModel
}
case ResourceType.SubmissionForm:
case ResourceType.SubmissionForms: {
return NormalizedSubmissionFormsModel
}
case ResourceType.SubmissionSection:
case ResourceType.SubmissionSections: {
return NormalizedSubmissionSectionModel
}
default: {
return undefined;
}
}
}
}

View File

@@ -1,25 +1,24 @@
import { CacheableObject } from '../object-cache.reducer';
import { CacheableObject, TypedObject } from '../object-cache.reducer';
import { autoserialize } from 'cerialize';
import { ResourceType } from '../../shared/resource-type';
/**
* An abstract model class for a NormalizedObject.
*/
export abstract class NormalizedObject<T extends CacheableObject> implements CacheableObject {
export abstract class NormalizedObject<T extends TypedObject> implements CacheableObject {
/**
* The link to the rest endpoint where this object can be found
*/
@autoserialize
self: string;
/**
* A string representing the kind of DSpaceObject, e.g. community, item, …
*/
@autoserialize
type: ResourceType;
@autoserialize
_links: {
[name: string]: string
}
};
/**
* A string representing the kind of object
*/
@autoserialize
type: string;
}

View File

@@ -12,7 +12,6 @@ import { ActionType } from './action-type.model';
@mapsTo(ResourcePolicy)
@inheritSerialization(NormalizedObject)
export class NormalizedResourcePolicy extends NormalizedObject<ResourcePolicy> {
/**
* The action that is allowed by this Resource Policy
*/

View File

@@ -8,7 +8,7 @@ export enum SupportLevel {
Unknown = 0,
/**
* Unknown for Bitstream Formats that are known to the system, but not fully supported
* Known for Bitstream Formats that are known to the system, but not fully supported
*/
Known = 1,

View File

@@ -9,6 +9,7 @@ import {
ResetObjectCacheTimestampsAction
} from './object-cache.actions';
import { Operation } from 'fast-json-patch';
import { Item } from '../shared/item.model';
class NullAction extends RemoveFromObjectCacheAction {
type = null;
@@ -28,6 +29,7 @@ describe('objectCacheReducer', () => {
const testState = {
[selfLink1]: {
data: {
type: Item.type,
self: selfLink1,
foo: 'bar'
},
@@ -39,6 +41,7 @@ describe('objectCacheReducer', () => {
},
[selfLink2]: {
data: {
type: Item.type,
self: requestUUID2,
foo: 'baz'
},
@@ -67,7 +70,7 @@ describe('objectCacheReducer', () => {
it('should add the payload to the cache in response to an ADD action', () => {
const state = Object.create(null);
const objectToCache = { self: selfLink1 };
const objectToCache = { self: selfLink1, type: Item.type };
const timeAdded = new Date().getTime();
const msToLive = 900000;
const requestUUID = requestUUID1;
@@ -80,7 +83,12 @@ describe('objectCacheReducer', () => {
});
it('should overwrite an object in the cache in response to an ADD action if it already exists', () => {
const objectToCache = { self: selfLink1, foo: 'baz', somethingElse: true };
const objectToCache = {
self: selfLink1,
foo: 'baz',
somethingElse: true,
type: Item.type
};
const timeAdded = new Date().getTime();
const msToLive = 900000;
const requestUUID = requestUUID1;
@@ -95,7 +103,7 @@ describe('objectCacheReducer', () => {
it('should perform the ADD action without affecting the previous state', () => {
const state = Object.create(null);
const objectToCache = { self: selfLink1 };
const objectToCache = { self: selfLink1, type: Item.type };
const timeAdded = new Date().getTime();
const msToLive = 900000;
const requestUUID = requestUUID1;

View File

@@ -32,15 +32,19 @@ export interface Patch {
operations: Operation[];
}
export abstract class TypedObject {
static type: ResourceType;
}
/* tslint:disable:max-classes-per-file */
/**
* An interface to represent objects that can be cached
*
* A cacheable object should have a self link
*/
export interface CacheableObject {
export class CacheableObject extends TypedObject {
uuid?: string;
self: string;
type?: ResourceType;
// isNew: boolean;
// dirtyType: DirtyType;
// hasDirtyAttributes: boolean;
@@ -59,6 +63,7 @@ export class ObjectCacheEntry implements CacheEntry {
patches: Patch[] = [];
isDirty: boolean;
}
/* tslint:enable:max-classes-per-file */
/**
* The ObjectCache State

View File

@@ -10,13 +10,13 @@ import {
RemoveFromObjectCacheAction
} from './object-cache.actions';
import { CoreState } from '../core.reducers';
import { ResourceType } from '../shared/resource-type';
import { NormalizedItem } from './models/normalized-item.model';
import { first } from 'rxjs/operators';
import { Operation } from 'fast-json-patch';
import { RestRequestMethod } from '../data/rest-request-method';
import { AddToSSBAction } from './server-sync-buffer.actions';
import { Patch } from './object-cache.reducer';
import { Item } from '../shared/item.model';
describe('ObjectCacheService', () => {
let service: ObjectCacheService;
@@ -28,7 +28,7 @@ describe('ObjectCacheService', () => {
const msToLive = 900000;
let objectToCache = {
self: selfLink,
type: ResourceType.Item
type: Item.type
};
let cacheEntry;
let invalidCacheEntry;
@@ -37,7 +37,7 @@ describe('ObjectCacheService', () => {
function init() {
objectToCache = {
self: selfLink,
type: ResourceType.Item
type: Item.type
};
cacheEntry = {
data: objectToCache,

View File

@@ -10,7 +10,6 @@ import { coreSelector } from '../core.selectors';
import { RestRequestMethod } from '../data/rest-request-method';
import { selfLinkFromUuidSelector } from '../index/index.selectors';
import { GenericConstructor } from '../shared/generic-constructor';
import { NormalizedObjectFactory } from './models/normalized-object-factory';
import { NormalizedObject } from './models/normalized-object.model';
import {
AddPatchObjectCacheAction,
@@ -21,6 +20,7 @@ import {
import { CacheableObject, ObjectCacheEntry, ObjectCacheState } from './object-cache.reducer';
import { AddToSSBAction } from './server-sync-buffer.actions';
import { getMapsToType } from './builders/build-decorators';
/**
* The base selector function to select the object cache in the store
@@ -109,7 +109,7 @@ export class ObjectCacheService {
}
),
map((entry: ObjectCacheEntry) => {
const type: GenericConstructor<NormalizedObject<T>> = NormalizedObjectFactory.getConstructor(entry.data.type);
const type: GenericConstructor<NormalizedObject<T>> = getMapsToType((entry.data as any).type);
return Object.assign(new type(), entry.data) as NormalizedObject<T>
})
);

View File

@@ -8,12 +8,12 @@ import { IntegrationModel } from '../integration/models/integration.model';
import { RegistryMetadataschemasResponse } from '../registry/registry-metadataschemas-response.model';
import { RegistryMetadatafieldsResponse } from '../registry/registry-metadatafields-response.model';
import { RegistryBitstreamformatsResponse } from '../registry/registry-bitstreamformats-response.model';
import { MetadataSchema } from '../metadata/metadataschema.model';
import { MetadataField } from '../metadata/metadatafield.model';
import { PaginatedList } from '../data/paginated-list';
import { SubmissionObject } from '../submission/models/submission-object.model';
import { DSpaceObject } from '../shared/dspace-object.model';
import { NormalizedAuthStatus } from '../auth/models/normalized-auth-status.model';
import { MetadataSchema } from '../metadata/metadata-schema.model';
import { MetadataField } from '../metadata/metadata-field.model';
/* tslint:disable:max-classes-per-file */
export class RestResponse {

View File

@@ -8,8 +8,8 @@ import { Store } from '@ngrx/store';
import { CoreState } from '../core.reducers';
import { PaginatedList } from '../data/paginated-list';
import { PageInfo } from '../shared/page-info.model';
import { NormalizedSubmissionDefinitionsModel } from './models/normalized-config-submission-definitions.model';
import { NormalizedSubmissionSectionModel } from './models/normalized-config-submission-section.model';
import { NormalizedSubmissionDefinitionModel } from './models/normalized-config-submission-definition.model';
describe('ConfigResponseParsingService', () => {
let service: ConfigResponseParsingService;
@@ -173,7 +173,7 @@ describe('ConfigResponseParsingService', () => {
self: 'https://rest.api/config/submissiondefinitions/traditional/sections'
});
const definitions =
Object.assign(new NormalizedSubmissionDefinitionsModel(), {
Object.assign(new NormalizedSubmissionDefinitionModel(), {
isDefault: true,
name: 'traditional',
type: 'submissiondefinition',

View File

@@ -5,10 +5,8 @@ import { RestRequest } from '../data/request.models';
import { DSpaceRESTV2Response } from '../dspace-rest-v2/dspace-rest-v2-response.model';
import { ConfigSuccessResponse, ErrorResponse, RestResponse } from '../cache/response.models';
import { isNotEmpty } from '../../shared/empty.util';
import { ConfigObjectFactory } from './models/config-object-factory';
import { ConfigObject } from './models/config.model';
import { ConfigType } from './models/config-type';
import { BaseResponseParsingService } from '../data/base-response-parsing.service';
import { GLOBAL_CONFIG } from '../../../config';
import { GlobalConfig } from '../../../config/global-config.interface';
@@ -16,8 +14,6 @@ import { ObjectCacheService } from '../cache/object-cache.service';
@Injectable()
export class ConfigResponseParsingService extends BaseResponseParsingService implements ResponseParsingService {
protected objectFactory = ConfigObjectFactory;
protected toCache = false;
constructor(
@@ -28,7 +24,7 @@ export class ConfigResponseParsingService extends BaseResponseParsingService imp
parse(request: RestRequest, data: DSpaceRESTV2Response): RestResponse {
if (isNotEmpty(data.payload) && isNotEmpty(data.payload._links) && (data.statusCode === 201 || data.statusCode === 200)) {
const configDefinition = this.process<ConfigObject,ConfigType>(data.payload, request.uuid);
const configDefinition = this.process<ConfigObject>(data.payload, request.uuid);
return new ConfigSuccessResponse(configDefinition, data.statusCode, data.statusText, this.processPageInfo(data.payload));
} else {
return new ErrorResponse(

View File

@@ -1,36 +0,0 @@
import { GenericConstructor } from '../../shared/generic-constructor';
import { ConfigType } from './config-type';
import { ConfigObject } from './config.model';
import { NormalizedSubmissionDefinitionsModel } from './normalized-config-submission-definitions.model';
import { NormalizedSubmissionFormsModel } from './normalized-config-submission-forms.model';
import { NormalizedSubmissionSectionModel } from './normalized-config-submission-section.model';
import { NormalizedSubmissionUploadsModel } from './normalized-config-submission-uploads.model';
/**
* Class to return normalized models for config objects
*/
export class ConfigObjectFactory {
public static getConstructor(type): GenericConstructor<ConfigObject> {
switch (type) {
case ConfigType.SubmissionDefinition:
case ConfigType.SubmissionDefinitions: {
return NormalizedSubmissionDefinitionsModel
}
case ConfigType.SubmissionForm:
case ConfigType.SubmissionForms: {
return NormalizedSubmissionFormsModel
}
case ConfigType.SubmissionSection:
case ConfigType.SubmissionSections: {
return NormalizedSubmissionSectionModel
}
case ConfigType.SubmissionUpload:
case ConfigType.SubmissionUploads: {
return NormalizedSubmissionUploadsModel
}
default: {
return undefined;
}
}
}
}

View File

@@ -0,0 +1,22 @@
import { ConfigObject } from './config.model';
import { SubmissionSectionModel } from './config-submission-section.model';
import { PaginatedList } from '../../data/paginated-list';
import { ResourceType } from '../../shared/resource-type';
/**
* Class for the configuration describing the submission
*/
export class SubmissionDefinitionModel extends ConfigObject {
static type = new ResourceType('submissiondefinition');
/**
* A boolean representing if this submission definition is the default or not
*/
isDefault: boolean;
/**
* A list of SubmissionSectionModel that are present in this submission definition
*/
sections: PaginatedList<SubmissionSectionModel>;
}

View File

@@ -1,17 +1,7 @@
import { ConfigObject } from './config.model';
import { SubmissionSectionModel } from './config-submission-section.model';
import { PaginatedList } from '../../data/paginated-list';
import { SubmissionDefinitionModel } from './config-submission-definition.model';
import { ResourceType } from '../../shared/resource-type';
export class SubmissionDefinitionsModel extends ConfigObject {
/**
* A boolean representing if this submission definition is the default or not
*/
isDefault: boolean;
/**
* A list of SubmissionSectionModel that are present in this submission definition
*/
sections: PaginatedList<SubmissionSectionModel>;
export class SubmissionDefinitionsModel extends SubmissionDefinitionModel {
static type = new ResourceType('submissiondefinitions');
}

View File

@@ -0,0 +1,22 @@
import { ConfigObject } from './config.model';
import { FormFieldModel } from '../../../shared/form/builder/models/form-field.model';
import { ResourceType } from '../../shared/resource-type';
/**
* An interface that define a form row and its properties.
*/
export interface FormRowModel {
fields: FormFieldModel[];
}
/**
* A model class for a NormalizedObject.
*/
export class SubmissionFormModel extends ConfigObject {
static type = new ResourceType('submissionform');
/**
* An array of [FormRowModel] that are present in this form
*/
rows: FormRowModel[];
}

View File

@@ -1,20 +1,9 @@
import { ConfigObject } from './config.model';
import { FormFieldModel } from '../../../shared/form/builder/models/form-field.model';
/**
* An interface that define a form row and its properties.
*/
export interface FormRowModel {
fields: FormFieldModel[];
}
import { SubmissionFormModel } from './config-submission-form.model';
import { ResourceType } from '../../shared/resource-type';
/**
* A model class for a NormalizedObject.
*/
export class SubmissionFormsModel extends ConfigObject {
/**
* An array of [FormRowModel] that are present in this form
*/
rows: FormRowModel[];
export class SubmissionFormsModel extends SubmissionFormModel {
static type = new ResourceType('submissionforms');
}

View File

@@ -1,5 +1,6 @@
import { ConfigObject } from './config.model';
import { SectionsType } from '../../../submission/sections/sections-type';
import { ResourceType } from '../../shared/resource-type';
/**
* An interface that define section visibility and its properties.
@@ -10,6 +11,7 @@ export interface SubmissionSectionVisibility {
}
export class SubmissionSectionModel extends ConfigObject {
static type = new ResourceType('submissionsection');
/**
* The header for this section

View File

@@ -0,0 +1,6 @@
import { SubmissionSectionModel } from './config-submission-section.model';
import { ResourceType } from '../../shared/resource-type';
export class SubmissionSectionsModel extends SubmissionSectionModel {
static type = new ResourceType('submissionsections');
}

View File

@@ -1,9 +1,10 @@
import { ConfigObject } from './config.model';
import { AccessConditionOption } from './config-access-condition-option.model';
import { SubmissionFormsModel } from './config-submission-forms.model';
import { ResourceType } from '../../shared/resource-type';
export class SubmissionUploadsModel extends ConfigObject {
static type = new ResourceType('submissionupload');
/**
* A list of available bitstream access conditions
*/

View File

@@ -8,11 +8,6 @@ export abstract class ConfigObject implements CacheableObject {
*/
public name: string;
/**
* A string representing the kind of config object
*/
public type: ResourceType;
/**
* The links to all related resources returned by the rest api.
*/

View File

@@ -0,0 +1,28 @@
import { autoserialize, autoserializeAs, inheritSerialization } from 'cerialize';
import { SubmissionSectionModel } from './config-submission-section.model';
import { PaginatedList } from '../../data/paginated-list';
import { NormalizedConfigObject } from './normalized-config.model';
import { SubmissionDefinitionsModel } from './config-submission-definitions.model';
import { mapsTo } from '../../cache/builders/build-decorators';
import { SubmissionDefinitionModel } from './config-submission-definition.model';
/**
* Normalized class for the configuration describing the submission
*/
@mapsTo(SubmissionDefinitionModel)
@inheritSerialization(NormalizedConfigObject)
export class NormalizedSubmissionDefinitionModel extends NormalizedConfigObject<SubmissionDefinitionModel> {
/**
* A boolean representing if this submission definition is the default or not
*/
@autoserialize
isDefault: boolean;
/**
* A list of SubmissionSectionModel that are present in this submission definition
*/
@autoserializeAs(SubmissionSectionModel)
sections: PaginatedList<SubmissionSectionModel>;
}

View File

@@ -1,25 +1,13 @@
import { autoserialize, autoserializeAs, inheritSerialization } from 'cerialize';
import { SubmissionSectionModel } from './config-submission-section.model';
import { PaginatedList } from '../../data/paginated-list';
import { inheritSerialization } from 'cerialize';
import { NormalizedConfigObject } from './normalized-config.model';
import { SubmissionDefinitionsModel } from './config-submission-definitions.model';
import { mapsTo } from '../../cache/builders/build-decorators';
import { NormalizedSubmissionDefinitionModel } from './normalized-config-submission-definition.model';
/**
* Normalized class for the configuration describing the submission
*/
@mapsTo(SubmissionDefinitionsModel)
@inheritSerialization(NormalizedConfigObject)
export class NormalizedSubmissionDefinitionsModel extends NormalizedConfigObject<SubmissionDefinitionsModel> {
/**
* A boolean representing if this submission definition is the default or not
*/
@autoserialize
isDefault: boolean;
/**
* A list of SubmissionSectionModel that are present in this submission definition
*/
@autoserializeAs(SubmissionSectionModel)
sections: PaginatedList<SubmissionSectionModel>;
export class NormalizedSubmissionDefinitionsModel extends NormalizedSubmissionDefinitionModel {
}

Some files were not shown because too many files have changed in this diff Show More