Merge branch 'master' into Virtual-metadata-on-item-delete

This commit is contained in:
Samuel
2020-01-14 12:51:54 +01:00
59 changed files with 3597 additions and 1321 deletions

View File

@@ -11,6 +11,7 @@
"node": "8.* || >= 10.*" "node": "8.* || >= 10.*"
}, },
"resolutions": { "resolutions": {
"serialize-javascript": ">= 2.1.2",
"set-value": ">= 2.0.1" "set-value": ">= 2.0.1"
}, },
"scripts": { "scripts": {
@@ -74,38 +75,38 @@
"sync-i18n": "node ./scripts/sync-i18n-files.js" "sync-i18n": "node ./scripts/sync-i18n-files.js"
}, },
"dependencies": { "dependencies": {
"@angular/animations": "^6.1.4", "@angular/animations": "^7.2.15",
"@angular/cdk": "^6.4.7", "@angular/cdk": "7.3.7",
"@angular/cli": "^6.1.5", "@angular/cli": "^7.3.5",
"@angular/common": "^6.1.4", "@angular/common": "^7.2.15",
"@angular/core": "^6.1.4", "@angular/core": "^7.2.15",
"@angular/forms": "^6.1.4", "@angular/forms": "^7.2.15",
"@angular/http": "^6.1.4", "@angular/http": "^7.2.15",
"@angular/platform-browser": "^6.1.4", "@angular/platform-browser": "^7.2.15",
"@angular/platform-browser-dynamic": "^6.1.4", "@angular/platform-browser-dynamic": "^7.2.15",
"@angular/platform-server": "^6.1.4", "@angular/platform-server": "^7.2.15",
"@angular/router": "^6.1.4", "@angular/router": "^7.2.15",
"@angularclass/bootloader": "1.0.1", "@angularclass/bootloader": "1.0.1",
"@ng-bootstrap/ng-bootstrap": "^2.0.0", "@ng-bootstrap/ng-bootstrap": "^4.1.0",
"@ng-dynamic-forms/core": "6.2.0", "@ng-dynamic-forms/core": "^7.1.0",
"@ng-dynamic-forms/ui-ng-bootstrap": "6.2.0", "@ng-dynamic-forms/ui-ng-bootstrap": "^7.1.0",
"@ngrx/effects": "^6.1.0", "@ngrx/effects": "^7.3.0",
"@ngrx/router-store": "^6.1.0", "@ngrx/router-store": "^7.3.0",
"@ngrx/store": "^6.1.0", "@ngrx/store": "^7.3.0",
"@nguniversal/express-engine": "6.1.0", "@nguniversal/express-engine": "^7.1.1",
"@ngx-translate/core": "10.0.2", "@ngx-translate/core": "11.0.1",
"@ngx-translate/http-loader": "3.0.1", "@ngx-translate/http-loader": "4.0.0",
"@nicky-lenaers/ngx-scroll-to": "^1.0.0", "@nicky-lenaers/ngx-scroll-to": "^1.0.0",
"angular-idle-preload": "3.0.0", "angular-idle-preload": "3.0.0",
"angular-sortablejs": "^2.5.0", "angular-sortablejs": "^2.5.0",
"angular2-text-mask": "9.0.0", "angular2-text-mask": "9.0.0",
"angulartics2": "^6.2.0", "angulartics2": "7.5.2",
"body-parser": "1.18.2", "body-parser": "1.18.2",
"bootstrap": "4.3.1", "bootstrap": "4.3.1",
"cerialize": "0.1.18", "cerialize": "0.1.18",
"compression": "1.7.1", "compression": "1.7.1",
"cookie-parser": "1.4.3", "cookie-parser": "1.4.3",
"core-js": "^2.5.7", "core-js": "^2.6.5",
"debug-loader": "^0.0.1", "debug-loader": "^0.0.1",
"express": "4.16.2", "express": "4.16.2",
"express-session": "1.15.6", "express-session": "1.15.6",
@@ -113,6 +114,7 @@
"file-saver": "^1.3.8", "file-saver": "^1.3.8",
"font-awesome": "4.7.0", "font-awesome": "4.7.0",
"fork-ts-checker-webpack-plugin": "^0.4.10", "fork-ts-checker-webpack-plugin": "^0.4.10",
"hammerjs": "^2.0.8",
"http-server": "0.11.1", "http-server": "0.11.1",
"https": "1.0.0", "https": "1.0.0",
"js-cookie": "2.2.0", "js-cookie": "2.2.0",
@@ -122,18 +124,19 @@
"jwt-decode": "^2.2.0", "jwt-decode": "^2.2.0",
"methods": "1.1.2", "methods": "1.1.2",
"moment": "^2.22.1", "moment": "^2.22.1",
"moment-range": "^4.0.2",
"morgan": "^1.9.1", "morgan": "^1.9.1",
"ng-mocks": "^6.2.1", "ng-mocks": "^7.6.0",
"ng2-file-upload": "1.2.1", "ng2-file-upload": "1.2.1",
"ng2-nouislider": "^1.7.11", "ng2-nouislider": "^1.8.2",
"ngx-bootstrap": "^3.2.0", "ngx-bootstrap": "^3.2.0",
"ngx-infinite-scroll": "6.0.1", "ngx-infinite-scroll": "6.0.1",
"ngx-moment": "^3.1.0", "ngx-moment": "^3.4.0",
"ngx-pagination": "3.0.3", "ngx-pagination": "3.0.3",
"nouislider": "^11.0.0", "nouislider": "^11.0.0",
"pem": "1.13.2", "pem": "1.13.2",
"reflect-metadata": "0.1.12", "reflect-metadata": "0.1.12",
"rxjs": "6.2.2", "rxjs": "6.4.0",
"rxjs-spy": "^7.5.1", "rxjs-spy": "^7.5.1",
"sass-resources-loader": "^2.0.0", "sass-resources-loader": "^2.0.0",
"sortablejs": "1.7.0", "sortablejs": "1.7.0",
@@ -143,17 +146,18 @@
"url-parse": "^1.4.7", "url-parse": "^1.4.7",
"uuid": "^3.2.1", "uuid": "^3.2.1",
"webfontloader": "1.6.28", "webfontloader": "1.6.28",
"webpack-cli": "^3.1.0", "webpack-cli": "^3.2.0",
"zone.js": "^0.8.26" "zone.js": "^0.8.29"
}, },
"devDependencies": { "devDependencies": {
"@angular/compiler": "^6.1.4", "@angular-devkit/build-angular": "^0.13.5",
"@angular/compiler-cli": "^6.1.4", "@angular/compiler": "^7.2.15",
"@angular/compiler-cli": "^7.2.15",
"@fortawesome/fontawesome-free": "^5.5.0", "@fortawesome/fontawesome-free": "^5.5.0",
"@ngrx/entity": "^6.1.0", "@ngrx/entity": "^7.3.0",
"@ngrx/schematics": "^6.1.0", "@ngrx/schematics": "^7.3.0",
"@ngrx/store-devtools": "^6.1.0", "@ngrx/store-devtools": "^7.3.0",
"@ngtools/webpack": "^6.1.5", "@ngtools/webpack": "^7.3.9",
"@schematics/angular": "^0.7.5", "@schematics/angular": "^0.7.5",
"@types/acorn": "^4.0.3", "@types/acorn": "^4.0.3",
"@types/cookie-parser": "1.4.1", "@types/cookie-parser": "1.4.1",
@@ -162,44 +166,47 @@
"@types/express-serve-static-core": "4.16.0", "@types/express-serve-static-core": "4.16.0",
"@types/file-saver": "^1.3.0", "@types/file-saver": "^1.3.0",
"@types/hammerjs": "2.0.35", "@types/hammerjs": "2.0.35",
"@types/jasmine": "^2.8.6", "@types/jasmine": "^3.3.9",
"@types/js-cookie": "2.1.0", "@types/js-cookie": "2.1.0",
"@types/json5": "^0.0.30", "@types/json5": "^0.0.30",
"@types/lodash": "^4.14.110", "@types/lodash": "^4.14.110",
"@types/memory-cache": "0.2.0", "@types/memory-cache": "0.2.0",
"@types/mime": "2.0.0", "@types/mime": "2.0.0",
"@types/node": "^10.9.4", "@types/node": "^11.11.2",
"@types/serve-static": "1.13.2", "@types/serve-static": "1.13.2",
"@types/uuid": "^3.4.3", "@types/uuid": "^3.4.3",
"@types/webfontloader": "1.6.29", "@types/webfontloader": "1.6.29",
"@typescript-eslint/eslint-plugin": "^2.12.0",
"@typescript-eslint/parser": "^2.12.0",
"ajv": "^6.1.1", "ajv": "^6.1.1",
"ajv-keywords": "^3.1.0", "ajv-keywords": "^3.1.0",
"angular2-template-loader": "0.6.2", "angular2-template-loader": "0.6.2",
"autoprefixer": "^9.1.3", "autoprefixer": "^9.1.3",
"caniuse-lite": "^1.0.30000697", "caniuse-lite": "^1.0.30000697",
"cli-progress": "^3.3.1", "cli-progress": "^3.3.1",
"codelyzer": "^4.4.4", "codelyzer": "^5.1.0",
"commander": "^3.0.2", "commander": "^3.0.2",
"compression-webpack-plugin": "^1.1.6", "compression-webpack-plugin": "^3.0.1",
"copy-webpack-plugin": "^4.4.1", "copy-webpack-plugin": "^5.1.1",
"copyfiles": "^2.1.1", "copyfiles": "^2.1.1",
"coveralls": "3.0.0", "coveralls": "3.0.0",
"css-loader": "1.0.0", "css-loader": "3.4.0",
"cssnano": "^4.1.10", "cssnano": "^4.1.10",
"deep-freeze": "0.0.1", "deep-freeze": "0.0.1",
"eslint": "^6.7.2",
"exports-loader": "^0.7.0", "exports-loader": "^0.7.0",
"html-webpack-plugin": "^4.0.0-alpha", "html-webpack-plugin": "3.2.0",
"imports-loader": "0.8.0", "imports-loader": "0.8.0",
"istanbul-instrumenter-loader": "3.0.1", "istanbul-instrumenter-loader": "3.0.1",
"jasmine-core": "^3.2.1", "jasmine-core": "^3.3.0",
"jasmine-marbles": "0.3.1", "jasmine-marbles": "0.3.1",
"jasmine-spec-reporter": "4.2.1", "jasmine-spec-reporter": "4.2.1",
"karma": "3.0.0", "karma": "4.0.1",
"karma-chrome-launcher": "2.2.0", "karma-chrome-launcher": "2.2.0",
"karma-cli": "1.0.1", "karma-cli": "2.0.0",
"karma-coverage": "1.1.2", "karma-coverage": "1.1.2",
"karma-istanbul-preprocessor": "0.0.2", "karma-istanbul-preprocessor": "0.0.2",
"karma-jasmine": "1.1.2", "karma-jasmine": "2.0.1",
"karma-mocha-reporter": "2.2.5", "karma-mocha-reporter": "2.2.5",
"karma-phantomjs-launcher": "1.0.4", "karma-phantomjs-launcher": "1.0.4",
"karma-remap-coverage": "^0.1.5", "karma-remap-coverage": "^0.1.5",
@@ -223,26 +230,26 @@
"protractor": "^5.4.2", "protractor": "^5.4.2",
"protractor-istanbul-plugin": "2.0.0", "protractor-istanbul-plugin": "2.0.0",
"raw-loader": "0.5.1", "raw-loader": "0.5.1",
"resolve-url-loader": "^2.3.0",
"rimraf": "2.6.2", "rimraf": "2.6.2",
"rollup": "^0.65.0", "rollup": "^0.65.0",
"rollup-plugin-commonjs": "^9.1.6", "rollup-plugin-commonjs": "^9.1.6",
"rollup-plugin-node-globals": "1.2.1", "rollup-plugin-node-globals": "1.2.1",
"rollup-plugin-node-resolve": "^3.0.3", "rollup-plugin-node-resolve": "^3.0.3",
"rollup-plugin-terser": "^2.0.2", "rollup-plugin-terser": "^2.0.2",
"sass-loader": "^7.1.0", "sass-loader": "7.3.1",
"script-ext-html-webpack-plugin": "2.0.1", "script-ext-html-webpack-plugin": "2.1.4",
"source-map": "0.7.3", "source-map": "0.7.3",
"source-map-loader": "0.2.4", "source-map-loader": "0.2.4",
"string-replace-loader": "^2.1.1", "string-replace-loader": "^2.1.1",
"terser-webpack-plugin": "^2.3.1",
"to-string-loader": "1.1.5", "to-string-loader": "1.1.5",
"ts-helpers": "1.1.2", "ts-helpers": "1.1.2",
"ts-node": "4.1.0", "ts-node": "4.1.0",
"tslint": "5.11.0", "tslint": "5.11.0",
"typedoc": "^0.9.0", "typedoc": "^0.9.0",
"typescript": "^2.9.1", "typescript": "3.1.6",
"webdriver-manager": "^12.1.7", "webdriver-manager": "^12.1.7",
"webpack": "^4.17.1", "webpack": "^4.29.6",
"webpack-bundle-analyzer": "^3.3.2", "webpack-bundle-analyzer": "^3.3.2",
"webpack-dev-middleware": "3.2.0", "webpack-dev-middleware": "3.2.0",
"webpack-dev-server": "^3.1.11", "webpack-dev-server": "^3.1.11",

View File

@@ -1,7 +1,6 @@
import { MetadataRegistryComponent } from './metadata-registry.component'; import { MetadataRegistryComponent } from './metadata-registry.component';
import { async, ComponentFixture, inject, TestBed } from '@angular/core/testing'; import { async, ComponentFixture, inject, TestBed } from '@angular/core/testing';
import { of as observableOf } from 'rxjs'; import { of as observableOf } from 'rxjs';
import { RemoteData } from '../../../core/data/remote-data';
import { PaginatedList } from '../../../core/data/paginated-list'; import { PaginatedList } from '../../../core/data/paginated-list';
import { TranslateModule } from '@ngx-translate/core'; import { TranslateModule } from '@ngx-translate/core';
import { By } from '@angular/platform-browser'; import { By } from '@angular/platform-browser';
@@ -18,6 +17,7 @@ import { NotificationsService } from '../../../shared/notifications/notification
import { NotificationsServiceStub } from '../../../shared/testing/notifications-service-stub'; import { NotificationsServiceStub } from '../../../shared/testing/notifications-service-stub';
import { RestResponse } from '../../../core/cache/response.models'; import { RestResponse } from '../../../core/cache/response.models';
import { createSuccessfulRemoteDataObject$ } from '../../../shared/testing/utils'; import { createSuccessfulRemoteDataObject$ } from '../../../shared/testing/utils';
import { MetadataSchema } from '../../../core/metadata/metadata-schema.model';
describe('MetadataRegistryComponent', () => { describe('MetadataRegistryComponent', () => {
let comp: MetadataRegistryComponent; let comp: MetadataRegistryComponent;
@@ -101,12 +101,12 @@ describe('MetadataRegistryComponent', () => {
it('should start editing the selected schema', async(() => { it('should start editing the selected schema', async(() => {
fixture.whenStable().then(() => { fixture.whenStable().then(() => {
expect(registryService.editMetadataSchema).toHaveBeenCalledWith(mockSchemasList[0]); expect(registryService.editMetadataSchema).toHaveBeenCalledWith(mockSchemasList[0] as MetadataSchema);
}); });
})); }));
it('should cancel editing the selected schema when clicked again', async(() => { it('should cancel editing the selected schema when clicked again', async(() => {
spyOn(registryService, 'getActiveMetadataSchema').and.returnValue(observableOf(mockSchemasList[0])); spyOn(registryService, 'getActiveMetadataSchema').and.returnValue(observableOf(mockSchemasList[0] as MetadataSchema));
spyOn(registryService, 'cancelEditMetadataSchema'); spyOn(registryService, 'cancelEditMetadataSchema');
row.click(); row.click();
fixture.detectChanges(); fixture.detectChanges();
@@ -121,7 +121,7 @@ describe('MetadataRegistryComponent', () => {
beforeEach(() => { beforeEach(() => {
spyOn(registryService, 'deleteMetadataSchema').and.callThrough(); spyOn(registryService, 'deleteMetadataSchema').and.callThrough();
spyOn(registryService, 'getSelectedMetadataSchemas').and.returnValue(observableOf(selectedSchemas)); spyOn(registryService, 'getSelectedMetadataSchemas').and.returnValue(observableOf(selectedSchemas as MetadataSchema[]));
comp.deleteSchemas(); comp.deleteSchemas();
fixture.detectChanges(); fixture.detectChanges();
}); });

View File

@@ -1,7 +1,6 @@
import { MetadataSchemaComponent } from './metadata-schema.component'; import { MetadataSchemaComponent } from './metadata-schema.component';
import { async, ComponentFixture, inject, TestBed } from '@angular/core/testing'; import { async, ComponentFixture, inject, TestBed } from '@angular/core/testing';
import { of as observableOf } from 'rxjs'; import { of as observableOf } from 'rxjs';
import { RemoteData } from '../../../core/data/remote-data';
import { PaginatedList } from '../../../core/data/paginated-list'; import { PaginatedList } from '../../../core/data/paginated-list';
import { TranslateModule } from '@ngx-translate/core'; import { TranslateModule } from '@ngx-translate/core';
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';
@@ -22,6 +21,7 @@ import { NotificationsServiceStub } from '../../../shared/testing/notifications-
import { RestResponse } from '../../../core/cache/response.models'; import { RestResponse } from '../../../core/cache/response.models';
import { MetadataSchema } from '../../../core/metadata/metadata-schema.model'; import { MetadataSchema } from '../../../core/metadata/metadata-schema.model';
import { createSuccessfulRemoteDataObject$ } from '../../../shared/testing/utils'; import { createSuccessfulRemoteDataObject$ } from '../../../shared/testing/utils';
import { MetadataField } from '../../../core/metadata/metadata-field.model';
describe('MetadataSchemaComponent', () => { describe('MetadataSchemaComponent', () => {
let comp: MetadataSchemaComponent; let comp: MetadataSchemaComponent;
@@ -152,12 +152,12 @@ describe('MetadataSchemaComponent', () => {
it('should start editing the selected field', async(() => { it('should start editing the selected field', async(() => {
fixture.whenStable().then(() => { fixture.whenStable().then(() => {
expect(registryService.editMetadataField).toHaveBeenCalledWith(mockFieldsList[2]); expect(registryService.editMetadataField).toHaveBeenCalledWith(mockFieldsList[2] as MetadataField);
}); });
})); }));
it('should cancel editing the selected field when clicked again', async(() => { it('should cancel editing the selected field when clicked again', async(() => {
spyOn(registryService, 'getActiveMetadataField').and.returnValue(observableOf(mockFieldsList[2])); spyOn(registryService, 'getActiveMetadataField').and.returnValue(observableOf(mockFieldsList[2] as MetadataField));
spyOn(registryService, 'cancelEditMetadataField'); spyOn(registryService, 'cancelEditMetadataField');
row.click(); row.click();
fixture.detectChanges(); fixture.detectChanges();
@@ -172,7 +172,7 @@ describe('MetadataSchemaComponent', () => {
beforeEach(() => { beforeEach(() => {
spyOn(registryService, 'deleteMetadataField').and.callThrough(); spyOn(registryService, 'deleteMetadataField').and.callThrough();
spyOn(registryService, 'getSelectedMetadataFields').and.returnValue(observableOf(selectedFields)); spyOn(registryService, 'getSelectedMetadataFields').and.returnValue(observableOf(selectedFields as MetadataField[]));
comp.deleteFields(); comp.deleteFields();
fixture.detectChanges(); fixture.detectChanges();
}); });

View File

@@ -1,6 +1,10 @@
import { Component, Input } from '@angular/core'; import { Component, Input } from '@angular/core';
import { DynamicFormService, DynamicInputModel, DynamicTextAreaModel } from '@ng-dynamic-forms/core'; import {
import { DynamicFormControlModel } from '@ng-dynamic-forms/core/src/model/dynamic-form-control.model'; DynamicFormControlModel,
DynamicFormService,
DynamicInputModel,
DynamicTextAreaModel
} from '@ng-dynamic-forms/core';
import { Collection } from '../../core/shared/collection.model'; import { Collection } from '../../core/shared/collection.model';
import { ComColFormComponent } from '../../shared/comcol-forms/comcol-form/comcol-form.component'; import { ComColFormComponent } from '../../shared/comcol-forms/comcol-form/comcol-form.component';
import { Location } from '@angular/common'; import { Location } from '@angular/common';

View File

@@ -1,8 +1,11 @@
import { Component, Input } from '@angular/core'; import { Component, Input } from '@angular/core';
import { DynamicFormService, DynamicInputModel, DynamicTextAreaModel } from '@ng-dynamic-forms/core'; import {
import { DynamicFormControlModel } from '@ng-dynamic-forms/core/src/model/dynamic-form-control.model'; DynamicFormControlModel,
DynamicFormService,
DynamicInputModel,
DynamicTextAreaModel
} from '@ng-dynamic-forms/core';
import { Community } from '../../core/shared/community.model'; import { Community } from '../../core/shared/community.model';
import { ResourceType } from '../../core/shared/resource-type';
import { ComColFormComponent } from '../../shared/comcol-forms/comcol-form/comcol-form.component'; import { ComColFormComponent } from '../../shared/comcol-forms/comcol-form/comcol-form.component';
import { Location } from '@angular/common'; import { Location } from '@angular/common';
import { TranslateService } from '@ngx-translate/core'; import { TranslateService } from '@ngx-translate/core';

View File

@@ -82,6 +82,7 @@ export class AppComponent implements OnInit, AfterViewInit {
} }
} }
angulartics2GoogleAnalytics.startTracking();
angulartics2DSpace.startTracking(); angulartics2DSpace.startTracking();
metadata.listenForRouteChange(); metadata.listenForRouteChange();

View File

@@ -1,5 +1,6 @@
import { ActionReducerMap, createSelector, MemoizedSelector } from '@ngrx/store'; import { ActionReducerMap, createSelector, MemoizedSelector } from '@ngrx/store';
import * as fromRouter from '@ngrx/router-store'; import * as fromRouter from '@ngrx/router-store';
import { hostWindowReducer, HostWindowState } from './shared/search/host-window.reducer'; import { hostWindowReducer, HostWindowState } from './shared/search/host-window.reducer';
import { CommunityListReducer, CommunityListState } from './community-list-page/community-list.reducer'; import { CommunityListReducer, CommunityListState } from './community-list-page/community-list.reducer';
import { formReducer, FormState } from './shared/form/form.reducer'; import { formReducer, FormState } from './shared/form/form.reducer';
@@ -8,23 +9,28 @@ import { sidebarFilterReducer, SidebarFiltersState } from './shared/sidebar/filt
import { filterReducer, SearchFiltersState } from './shared/search/search-filters/search-filter/search-filter.reducer'; import { filterReducer, SearchFiltersState } from './shared/search/search-filters/search-filter/search-filter.reducer';
import { notificationsReducer, NotificationsState } from './shared/notifications/notifications.reducers'; import { notificationsReducer, NotificationsState } from './shared/notifications/notifications.reducers';
import { truncatableReducer, TruncatablesState } from './shared/truncatable/truncatable.reducer'; import { truncatableReducer, TruncatablesState } from './shared/truncatable/truncatable.reducer';
import { metadataRegistryReducer, MetadataRegistryState } from './+admin/admin-registries/metadata-registry/metadata-registry.reducers'; import {
metadataRegistryReducer,
MetadataRegistryState
} from './+admin/admin-registries/metadata-registry/metadata-registry.reducers';
import { hasValue } from './shared/empty.util'; import { hasValue } from './shared/empty.util';
import { cssVariablesReducer, CSSVariablesState } from './shared/sass-helper/sass-helper.reducer'; import { cssVariablesReducer, CSSVariablesState } from './shared/sass-helper/sass-helper.reducer';
import { menusReducer, MenusState } from './shared/menu/menu.reducer'; import { menusReducer, MenusState } from './shared/menu/menu.reducer';
import { historyReducer, HistoryState } from './shared/history/history.reducer'; import {
import { selectableListReducer, SelectableListsState } from './shared/object-list/selectable-list/selectable-list.reducer'; selectableListReducer,
import { bitstreamFormatReducer, BitstreamFormatRegistryState } from './+admin/admin-registries/bitstream-formats/bitstream-format.reducers'; SelectableListsState
} from './shared/object-list/selectable-list/selectable-list.reducer';
import { ObjectSelectionListState, objectSelectionReducer } from './shared/object-select/object-select.reducer'; import { ObjectSelectionListState, objectSelectionReducer } from './shared/object-select/object-select.reducer';
import { NameVariantListsState, nameVariantReducer } from './shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/name-variant.reducer'; import {
NameVariantListsState,
nameVariantReducer
} from './shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/name-variant.reducer';
export interface AppState { export interface AppState {
router: fromRouter.RouterReducerState; router: fromRouter.RouterReducerState;
history: HistoryState;
hostWindow: HostWindowState; hostWindow: HostWindowState;
forms: FormState; forms: FormState;
metadataRegistry: MetadataRegistryState; metadataRegistry: MetadataRegistryState;
bitstreamFormats: BitstreamFormatRegistryState;
notifications: NotificationsState; notifications: NotificationsState;
sidebar: SidebarState; sidebar: SidebarState;
sidebarFilter: SidebarFiltersState; sidebarFilter: SidebarFiltersState;
@@ -40,11 +46,9 @@ export interface AppState {
export const appReducers: ActionReducerMap<AppState> = { export const appReducers: ActionReducerMap<AppState> = {
router: fromRouter.routerReducer, router: fromRouter.routerReducer,
history: historyReducer,
hostWindow: hostWindowReducer, hostWindow: hostWindowReducer,
forms: formReducer, forms: formReducer,
metadataRegistry: metadataRegistryReducer, metadataRegistry: metadataRegistryReducer,
bitstreamFormats: bitstreamFormatReducer,
notifications: notificationsReducer, notifications: notificationsReducer,
sidebar: sidebarReducer, sidebar: sidebarReducer,
sidebarFilter: sidebarFilterReducer, sidebarFilter: sidebarFilterReducer,

View File

@@ -312,7 +312,7 @@ export class CommunityListService {
hasColls$ = this.collectionDataService.findByParent(community.uuid, { elementsPerPage: 1 }) hasColls$ = this.collectionDataService.findByParent(community.uuid, { elementsPerPage: 1 })
.pipe( .pipe(
filter((rd: RemoteData<PaginatedList<Community>>) => rd.hasSucceeded), filter((rd: RemoteData<PaginatedList<Collection>>) => rd.hasSucceeded),
take(1), take(1),
map((results) => results.payload.totalElements > 0), map((results) => results.payload.totalElements > 0),
); );
@@ -320,8 +320,8 @@ export class CommunityListService {
let hasChildren$: Observable<boolean>; let hasChildren$: Observable<boolean>;
hasChildren$ = observableCombineLatest(hasSubcoms$, hasColls$).pipe( hasChildren$ = observableCombineLatest(hasSubcoms$, hasColls$).pipe(
take(1), take(1),
map((result: [boolean]) => { map(([hasSubcoms, hasColls]: [boolean, boolean]) => {
if (result[0] || result[1]) { if (hasSubcoms || hasColls) {
return true; return true;
} else { } else {
return false; return false;

View File

@@ -60,7 +60,8 @@ export class AuthService {
// and is not the login route, clear redirect url and messages // and is not the login route, clear redirect url and messages
const routeUrl$ = this.store.pipe( const routeUrl$ = this.store.pipe(
select(routerStateSelector), select(routerStateSelector),
filter((routerState: RouterReducerState) => isNotUndefined(routerState) && isNotUndefined(routerState.state)), filter((routerState: RouterReducerState) => isNotUndefined(routerState)
&& isNotUndefined(routerState.state) && isNotEmpty(routerState.state.url)),
filter((routerState: RouterReducerState) => !this.isLoginRoute(routerState.state.url)), filter((routerState: RouterReducerState) => !this.isLoginRoute(routerState.state.url)),
map((routerState: RouterReducerState) => routerState.state.url) map((routerState: RouterReducerState) => routerState.state.url)
); );

View File

@@ -1,7 +1,4 @@
import { import { ActionReducerMap, } from '@ngrx/store';
ActionReducerMap,
createFeatureSelector,
} from '@ngrx/store';
import { objectCacheReducer, ObjectCacheState } from './cache/object-cache.reducer'; import { objectCacheReducer, ObjectCacheState } from './cache/object-cache.reducer';
import { indexReducer, MetaIndexState } from './index/index.reducer'; import { indexReducer, MetaIndexState } from './index/index.reducer';
@@ -9,17 +6,21 @@ import { requestReducer, RequestState } from './data/request.reducer';
import { authReducer, AuthState } from './auth/auth.reducer'; import { authReducer, AuthState } from './auth/auth.reducer';
import { jsonPatchOperationsReducer, JsonPatchOperationsState } from './json-patch/json-patch-operations.reducer'; import { jsonPatchOperationsReducer, JsonPatchOperationsState } from './json-patch/json-patch-operations.reducer';
import { serverSyncBufferReducer, ServerSyncBufferState } from './cache/server-sync-buffer.reducer'; import { serverSyncBufferReducer, ServerSyncBufferState } from './cache/server-sync-buffer.reducer';
import { import { objectUpdatesReducer, ObjectUpdatesState } from './data/object-updates/object-updates.reducer';
objectUpdatesReducer,
ObjectUpdatesState
} from './data/object-updates/object-updates.reducer';
import { routeReducer, RouteState } from './services/route.reducer'; import { routeReducer, RouteState } from './services/route.reducer';
import {
bitstreamFormatReducer,
BitstreamFormatRegistryState
} from '../+admin/admin-registries/bitstream-formats/bitstream-format.reducers';
import { historyReducer, HistoryState } from './history/history.reducer';
export interface CoreState { export interface CoreState {
'bitstreamFormats': BitstreamFormatRegistryState;
'cache/object': ObjectCacheState, 'cache/object': ObjectCacheState,
'cache/syncbuffer': ServerSyncBufferState, 'cache/syncbuffer': ServerSyncBufferState,
'cache/object-updates': ObjectUpdatesState 'cache/object-updates': ObjectUpdatesState
'data/request': RequestState, 'data/request': RequestState,
'history': HistoryState;
'index': MetaIndexState, 'index': MetaIndexState,
'auth': AuthState, 'auth': AuthState,
'json/patch': JsonPatchOperationsState, 'json/patch': JsonPatchOperationsState,
@@ -27,10 +28,12 @@ export interface CoreState {
} }
export const coreReducers: ActionReducerMap<CoreState> = { export const coreReducers: ActionReducerMap<CoreState> = {
'bitstreamFormats': bitstreamFormatReducer,
'cache/object': objectCacheReducer, 'cache/object': objectCacheReducer,
'cache/syncbuffer': serverSyncBufferReducer, 'cache/syncbuffer': serverSyncBufferReducer,
'cache/object-updates': objectUpdatesReducer, 'cache/object-updates': objectUpdatesReducer,
'data/request': requestReducer, 'data/request': requestReducer,
'history': historyReducer,
'index': indexReducer, 'index': indexReducer,
'auth': authReducer, 'auth': authReducer,
'json/patch': jsonPatchOperationsReducer, 'json/patch': jsonPatchOperationsReducer,

View File

@@ -3,7 +3,6 @@ import { RequestEntry } from './request.reducer';
import { RestResponse } from '../cache/response.models'; import { RestResponse } from '../cache/response.models';
import { Observable, of as observableOf } from 'rxjs'; import { Observable, of as observableOf } from 'rxjs';
import { Action, Store } from '@ngrx/store'; import { Action, Store } from '@ngrx/store';
import { CoreState } from '../core.reducers';
import { ObjectCacheService } from '../cache/object-cache.service'; import { ObjectCacheService } from '../cache/object-cache.service';
import { cold, getTestScheduler, hot } from 'jasmine-marbles'; import { cold, getTestScheduler, hot } from 'jasmine-marbles';
import { HALEndpointService } from '../shared/hal-endpoint.service'; import { HALEndpointService } from '../shared/hal-endpoint.service';
@@ -19,6 +18,7 @@ import {
BitstreamFormatsRegistrySelectAction BitstreamFormatsRegistrySelectAction
} from '../../+admin/admin-registries/bitstream-formats/bitstream-format.actions'; } from '../../+admin/admin-registries/bitstream-formats/bitstream-format.actions';
import { TestScheduler } from 'rxjs/testing'; import { TestScheduler } from 'rxjs/testing';
import { CoreState } from '../core.reducers';
describe('BitstreamFormatDataService', () => { describe('BitstreamFormatDataService', () => {
let service: BitstreamFormatDataService; let service: BitstreamFormatDataService;

View File

@@ -5,7 +5,6 @@ import { RequestService } from './request.service';
import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service';
import { NormalizedObjectBuildService } from '../cache/builders/normalized-object-build.service'; import { NormalizedObjectBuildService } from '../cache/builders/normalized-object-build.service';
import { createSelector, select, Store } from '@ngrx/store'; import { createSelector, select, Store } from '@ngrx/store';
import { CoreState } from '../core.reducers';
import { ObjectCacheService } from '../cache/object-cache.service'; import { ObjectCacheService } from '../cache/object-cache.service';
import { HALEndpointService } from '../shared/hal-endpoint.service'; import { HALEndpointService } from '../shared/hal-endpoint.service';
import { NotificationsService } from '../../shared/notifications/notifications.service'; import { NotificationsService } from '../../shared/notifications/notifications.service';
@@ -17,7 +16,6 @@ import { find, map, tap } from 'rxjs/operators';
import { configureRequest, getResponseFromEntry } from '../shared/operators'; import { configureRequest, getResponseFromEntry } from '../shared/operators';
import { distinctUntilChanged } from 'rxjs/internal/operators/distinctUntilChanged'; import { distinctUntilChanged } from 'rxjs/internal/operators/distinctUntilChanged';
import { RestResponse } from '../cache/response.models'; import { RestResponse } from '../cache/response.models';
import { AppState } from '../../app.reducer';
import { BitstreamFormatRegistryState } from '../../+admin/admin-registries/bitstream-formats/bitstream-format.reducers'; import { BitstreamFormatRegistryState } from '../../+admin/admin-registries/bitstream-formats/bitstream-format.reducers';
import { import {
BitstreamFormatsRegistryDeselectAction, BitstreamFormatsRegistryDeselectAction,
@@ -26,8 +24,9 @@ import {
} from '../../+admin/admin-registries/bitstream-formats/bitstream-format.actions'; } from '../../+admin/admin-registries/bitstream-formats/bitstream-format.actions';
import { hasValue } from '../../shared/empty.util'; import { hasValue } from '../../shared/empty.util';
import { RequestEntry } from './request.reducer'; import { RequestEntry } from './request.reducer';
import { CoreState } from '../core.reducers';
const bitstreamFormatsStateSelector = (state: AppState) => state.bitstreamFormats; const bitstreamFormatsStateSelector = (state: CoreState) => state.bitstreamFormats;
const selectedBitstreamFormatSelector = createSelector(bitstreamFormatsStateSelector, const selectedBitstreamFormatSelector = createSelector(bitstreamFormatsStateSelector,
(bitstreamFormatRegistryState: BitstreamFormatRegistryState) => bitstreamFormatRegistryState.selectedBitstreamFormats); (bitstreamFormatRegistryState: BitstreamFormatRegistryState) => bitstreamFormatRegistryState.selectedBitstreamFormats);
@@ -55,6 +54,7 @@ export class BitstreamFormatDataService extends DataService<BitstreamFormat> {
/** /**
* Get the endpoint for browsing bitstream formats * Get the endpoint for browsing bitstream formats
* @param {FindListOptions} options * @param {FindListOptions} options
* @param {string} linkPath
* @returns {Observable<string>} * @returns {Observable<string>}
*/ */
getBrowseEndpoint(options: FindListOptions = {}, linkPath?: string): Observable<string> { getBrowseEndpoint(options: FindListOptions = {}, linkPath?: string): Observable<string> {
@@ -99,7 +99,7 @@ export class BitstreamFormatDataService extends DataService<BitstreamFormat> {
/** /**
* Create a new BitstreamFormat * Create a new BitstreamFormat
* @param BitstreamFormat * @param {BitstreamFormat} bitstreamFormat
*/ */
public createBitstreamFormat(bitstreamFormat: BitstreamFormat): Observable<RestResponse> { public createBitstreamFormat(bitstreamFormat: BitstreamFormat): Observable<RestResponse> {
const requestId = this.requestService.generateRequestId(); const requestId = this.requestService.generateRequestId();

View File

@@ -1,12 +1,22 @@
import { HttpClient } from '@angular/common/http'; import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
import { distinctUntilChanged, filter, find, first, map, mergeMap, skipWhile, switchMap, take, tap } from 'rxjs/operators'; import {
distinctUntilChanged,
filter,
find,
first,
map,
mergeMap,
skipWhile,
switchMap,
take,
tap
} from 'rxjs/operators';
import { Store } from '@ngrx/store'; import { Store } from '@ngrx/store';
import { hasValue, isNotEmpty, isNotEmptyOperator } from '../../shared/empty.util'; import { hasValue, isNotEmpty, isNotEmptyOperator } from '../../shared/empty.util';
import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service';
import { CoreState } from '../core.reducers';
import { HALEndpointService } from '../shared/hal-endpoint.service'; import { HALEndpointService } from '../shared/hal-endpoint.service';
import { URLCombiner } from '../url-combiner/url-combiner'; import { URLCombiner } from '../url-combiner/url-combiner';
import { PaginatedList } from './paginated-list'; import { PaginatedList } from './paginated-list';
@@ -14,9 +24,9 @@ import { RemoteData } from './remote-data';
import { import {
CreateRequest, CreateRequest,
DeleteByIDRequest, DeleteByIDRequest,
FindByIDRequest,
FindListOptions, FindListOptions,
FindListRequest, FindListRequest,
FindByIDRequest,
GetRequest GetRequest
} from './request.models'; } from './request.models';
import { RequestService } from './request.service'; import { RequestService } from './request.service';
@@ -37,6 +47,7 @@ import { NormalizedObjectBuildService } from '../cache/builders/normalized-objec
import { ChangeAnalyzer } from './change-analyzer'; import { ChangeAnalyzer } from './change-analyzer';
import { RestRequestMethod } from './rest-request-method'; import { RestRequestMethod } from './rest-request-method';
import { getMapsToType } from '../cache/builders/build-decorators'; import { getMapsToType } from '../cache/builders/build-decorators';
import { CoreState } from '../core.reducers';
export abstract class DataService<T extends CacheableObject> { export abstract class DataService<T extends CacheableObject> {
protected abstract requestService: RequestService; protected abstract requestService: RequestService;
@@ -238,7 +249,7 @@ export abstract class DataService<T extends CacheableObject> {
*/ */
update(object: T): Observable<RemoteData<T>> { update(object: T): Observable<RemoteData<T>> {
const oldVersion$ = this.objectCache.getObjectBySelfLink(object.self); const oldVersion$ = this.objectCache.getObjectBySelfLink(object.self);
return oldVersion$.pipe(take(1), mergeMap((oldVersion: T) => { return oldVersion$.pipe(take(1), mergeMap((oldVersion: NormalizedObject<T>) => {
const operations = this.comparator.diff(oldVersion, object); const operations = this.comparator.diff(oldVersion, object);
if (isNotEmpty(operations)) { if (isNotEmpty(operations)) {
this.objectCache.addPatch(object.self, operations); this.objectCache.addPatch(object.self, operations);

View File

@@ -6,22 +6,14 @@ import { CoreState } from '../core.reducers';
import { ItemDataService } from './item-data.service'; import { ItemDataService } from './item-data.service';
import { RequestService } from './request.service'; import { RequestService } from './request.service';
import { HALEndpointService } from '../shared/hal-endpoint.service'; import { HALEndpointService } from '../shared/hal-endpoint.service';
import { import { DeleteRequest, FindListOptions, PostRequest, RestRequest } from './request.models';
DeleteRequest,
FindListOptions,
GetRequest,
MappedCollectionsRequest,
PostRequest,
RestRequest
} from './request.models';
import { ObjectCacheService } from '../cache/object-cache.service'; import { ObjectCacheService } from '../cache/object-cache.service';
import { Observable } from 'rxjs'; import { Observable, of as observableOf } from 'rxjs';
import { RestResponse } from '../cache/response.models'; import { RestResponse } from '../cache/response.models';
import { NotificationsService } from '../../shared/notifications/notifications.service'; import { NotificationsService } from '../../shared/notifications/notifications.service';
import { NormalizedObjectBuildService } from '../cache/builders/normalized-object-build.service'; import { NormalizedObjectBuildService } from '../cache/builders/normalized-object-build.service';
import { HttpClient } from '@angular/common/http'; import { HttpClient } from '@angular/common/http';
import { RequestEntry } from './request.reducer'; import { RequestEntry } from './request.reducer';
import { of as observableOf } from 'rxjs';
import { getMockRequestService } from '../../shared/mocks/mock-request.service'; import { getMockRequestService } from '../../shared/mocks/mock-request.service';
describe('ItemDataService', () => { describe('ItemDataService', () => {
@@ -184,7 +176,7 @@ describe('ItemDataService', () => {
}); });
it('should configure a DELETE request', () => { it('should configure a DELETE request', () => {
result.subscribe(() => expect(requestService.configure).toHaveBeenCalledWith(jasmine.any(DeleteRequest), undefined)); result.subscribe(() => expect(requestService.configure).toHaveBeenCalledWith(jasmine.any(DeleteRequest)));
}); });
}); });
@@ -198,7 +190,7 @@ describe('ItemDataService', () => {
}); });
it('should configure a POST request', () => { it('should configure a POST request', () => {
result.subscribe(() => expect(requestService.configure).toHaveBeenCalledWith(jasmine.any(PostRequest), undefined)); result.subscribe(() => expect(requestService.configure).toHaveBeenCalledWith(jasmine.any(PostRequest)));
}); });
}); });

View File

@@ -2,7 +2,7 @@ import { Injectable } from '@angular/core';
import { RequestService } from './request.service'; import { RequestService } from './request.service';
import { HALEndpointService } from '../shared/hal-endpoint.service'; import { HALEndpointService } from '../shared/hal-endpoint.service';
import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service';
import { filter, find, map, switchMap, tap } from 'rxjs/operators'; import { filter, find, map, switchMap } from 'rxjs/operators';
import { configureRequest, getSucceededRemoteData } from '../shared/operators'; import { configureRequest, getSucceededRemoteData } from '../shared/operators';
import { Observable } from 'rxjs/internal/Observable'; import { Observable } from 'rxjs/internal/Observable';
import { RelationshipType } from '../shared/item-relationships/relationship-type.model'; import { RelationshipType } from '../shared/item-relationships/relationship-type.model';
@@ -42,7 +42,7 @@ export class RelationshipTypeService {
map((endpointURL: string) => new FindListRequest(this.requestService.generateRequestId(), endpointURL, options)), map((endpointURL: string) => new FindListRequest(this.requestService.generateRequestId(), endpointURL, options)),
configureRequest(this.requestService), configureRequest(this.requestService),
switchMap(() => this.rdbService.buildList(link$)) switchMap(() => this.rdbService.buildList(link$))
); ) as Observable<RemoteData<PaginatedList<RelationshipType>>>;
} }
/** /**

View File

@@ -3,9 +3,14 @@ import { RequestService } from './request.service';
import { HALEndpointService } from '../shared/hal-endpoint.service'; import { HALEndpointService } from '../shared/hal-endpoint.service';
import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service';
import { hasValue, hasValueOperator, isNotEmpty, isNotEmptyOperator } from '../../shared/empty.util'; import { hasValue, hasValueOperator, isNotEmpty, isNotEmptyOperator } from '../../shared/empty.util';
import { distinctUntilChanged, filter, map, mergeMap, skipWhile, startWith, switchMap, take, tap } from 'rxjs/operators'; import { distinctUntilChanged, filter, map, mergeMap, startWith, switchMap, take, tap } from 'rxjs/operators';
import { configureRequest, getRemoteDataPayload, getResponseFromEntry, getSucceededRemoteData } from '../shared/operators'; import {
import {DeleteRequest, FindListOptions, PostRequest, RestRequest} from './request.models'; configureRequest,
getRemoteDataPayload,
getResponseFromEntry,
getSucceededRemoteData
} from '../shared/operators';
import { DeleteRequest, FindListOptions, PostRequest, RestRequest } from './request.models';
import { Observable } from 'rxjs/internal/Observable'; import { Observable } from 'rxjs/internal/Observable';
import { RestResponse } from '../cache/response.models'; import { RestResponse } from '../cache/response.models';
import { Item } from '../shared/item.model'; import { Item } from '../shared/item.model';
@@ -15,7 +20,11 @@ import { RemoteData } from './remote-data';
import { combineLatest, combineLatest as observableCombineLatest } from 'rxjs'; import { combineLatest, combineLatest as observableCombineLatest } from 'rxjs';
import { PaginatedList } from './paginated-list'; import { PaginatedList } from './paginated-list';
import { ItemDataService } from './item-data.service'; import { ItemDataService } from './item-data.service';
import { compareArraysUsingIds, paginatedRelationsToItems, relationsToItems } from '../../+item-page/simple/item-types/shared/item-relationships-utils'; import {
compareArraysUsingIds,
paginatedRelationsToItems,
relationsToItems
} from '../../+item-page/simple/item-types/shared/item-relationships-utils';
import { ObjectCacheService } from '../cache/object-cache.service'; import { ObjectCacheService } from '../cache/object-cache.service';
import { DataService } from './data.service'; import { DataService } from './data.service';
import { NormalizedObjectBuildService } from '../cache/builders/normalized-object-build.service'; import { NormalizedObjectBuildService } from '../cache/builders/normalized-object-build.service';
@@ -28,7 +37,10 @@ import { SearchParam } from '../cache/models/search-param.model';
import { HttpOptions } from '../dspace-rest-v2/dspace-rest-v2.service'; import { HttpOptions } from '../dspace-rest-v2/dspace-rest-v2.service';
import { AppState, keySelector } from '../../app.reducer'; import { AppState, keySelector } from '../../app.reducer';
import { NameVariantListState } from '../../shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/name-variant.reducer'; import { NameVariantListState } from '../../shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/name-variant.reducer';
import { RemoveNameVariantAction, SetNameVariantAction } from '../../shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/name-variant.actions'; import {
RemoveNameVariantAction,
SetNameVariantAction
} from '../../shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/name-variant.actions';
const relationshipListsStateSelector = (state: AppState) => state.relationshipLists; const relationshipListsStateSelector = (state: AppState) => state.relationshipLists;
@@ -124,7 +136,7 @@ export class RelationshipService extends DataService<Relationship> {
getResponseFromEntry(), getResponseFromEntry(),
tap(() => this.removeRelationshipItemsFromCache(item1)), tap(() => this.removeRelationshipItemsFromCache(item1)),
tap(() => this.removeRelationshipItemsFromCache(item2)) tap(() => this.removeRelationshipItemsFromCache(item2))
); ) as Observable<RestResponse>;
} }
/** /**

View File

@@ -21,6 +21,7 @@ import {
} from './request.models'; } from './request.models';
import { RequestService } from './request.service'; import { RequestService } from './request.service';
import { TestScheduler } from 'rxjs/testing'; import { TestScheduler } from 'rxjs/testing';
import { RequestEntry } from './request.reducer';
describe('RequestService', () => { describe('RequestService', () => {
let scheduler: TestScheduler; let scheduler: TestScheduler;
@@ -107,7 +108,7 @@ describe('RequestService', () => {
beforeEach(() => { beforeEach(() => {
spyOn(service, 'getByHref').and.returnValue(observableOf({ spyOn(service, 'getByHref').and.returnValue(observableOf({
completed: false completed: false
})) } as RequestEntry))
}); });
it('should return true', () => { it('should return true', () => {
@@ -122,7 +123,7 @@ describe('RequestService', () => {
beforeEach(() => { beforeEach(() => {
spyOn(service, 'getByHref').and.returnValues(observableOf({ spyOn(service, 'getByHref').and.returnValues(observableOf({
completed: true completed: true
})); } as RequestEntry));
}); });
it('should return false', () => { it('should return false', () => {
@@ -432,7 +433,7 @@ describe('RequestService', () => {
let valid; let valid;
const requestEntry = { completed: false }; const requestEntry = { completed: false };
beforeEach(() => { beforeEach(() => {
spyOn(service, 'getByUUID').and.returnValue(observableOf(requestEntry)); spyOn(service, 'getByUUID').and.returnValue(observableOf(requestEntry as RequestEntry));
valid = serviceAsAny.isValid(requestEntry); valid = serviceAsAny.isValid(requestEntry);
}); });
it('return an observable emitting false', () => { it('return an observable emitting false', () => {
@@ -444,7 +445,7 @@ describe('RequestService', () => {
let valid; let valid;
const requestEntry = { completed: true, response: { isSuccessful: false } }; const requestEntry = { completed: true, response: { isSuccessful: false } };
beforeEach(() => { beforeEach(() => {
spyOn(service, 'getByUUID').and.returnValue(observableOf(requestEntry)); spyOn(service, 'getByUUID').and.returnValue(observableOf(requestEntry as RequestEntry));
valid = serviceAsAny.isValid(requestEntry); valid = serviceAsAny.isValid(requestEntry);
}); });
it('return an observable emitting false', () => { it('return an observable emitting false', () => {
@@ -470,7 +471,7 @@ describe('RequestService', () => {
beforeEach(() => { beforeEach(() => {
spyOn(Date.prototype, 'getTime').and.returnValue(now); spyOn(Date.prototype, 'getTime').and.returnValue(now);
spyOn(service, 'getByUUID').and.returnValue(observableOf(requestEntry)); spyOn(service, 'getByUUID').and.returnValue(observableOf(requestEntry as RequestEntry));
valid = serviceAsAny.isValid(requestEntry); valid = serviceAsAny.isValid(requestEntry);
}); });
@@ -497,7 +498,7 @@ describe('RequestService', () => {
}; };
beforeEach(() => { beforeEach(() => {
spyOn(Date.prototype, 'getTime').and.returnValue(now); spyOn(Date.prototype, 'getTime').and.returnValue(now);
spyOn(service, 'getByUUID').and.returnValue(observableOf(requestEntry)); spyOn(service, 'getByUUID').and.returnValue(observableOf(requestEntry as RequestEntry));
valid = serviceAsAny.isValid(requestEntry); valid = serviceAsAny.isValid(requestEntry);
}); });

View File

@@ -5,8 +5,6 @@ import { createSelector, MemoizedSelector, select, Store } from '@ngrx/store';
import { Observable, race as observableRace } from 'rxjs'; import { Observable, race as observableRace } from 'rxjs';
import { filter, map, mergeMap, switchMap, take } from 'rxjs/operators'; import { filter, map, mergeMap, switchMap, take } from 'rxjs/operators';
import { cloneDeep, remove } from 'lodash'; import { cloneDeep, remove } from 'lodash';
import { AppState } from '../../app.reducer';
import { hasValue, isEmpty, isNotEmpty } from '../../shared/empty.util'; import { hasValue, isEmpty, isNotEmpty } from '../../shared/empty.util';
import { CacheableObject } from '../cache/object-cache.reducer'; import { CacheableObject } from '../cache/object-cache.reducer';
import { ObjectCacheService } from '../cache/object-cache.service'; import { ObjectCacheService } from '../cache/object-cache.service';
@@ -19,7 +17,7 @@ import {
} from '../index/index.selectors'; } from '../index/index.selectors';
import { UUIDService } from '../shared/uuid.service'; import { UUIDService } from '../shared/uuid.service';
import { RequestConfigureAction, RequestExecuteAction, RequestRemoveAction } from './request.actions'; import { RequestConfigureAction, RequestExecuteAction, RequestRemoveAction } from './request.actions';
import { GetRequest, RestRequest, SubmissionRequest } from './request.models'; import { GetRequest, RestRequest } from './request.models';
import { RequestEntry, RequestState } from './request.reducer'; import { RequestEntry, RequestState } from './request.reducer';
import { CommitSSBAction } from '../cache/server-sync-buffer.actions'; import { CommitSSBAction } from '../cache/server-sync-buffer.actions';
import { RestRequestMethod } from './rest-request-method'; import { RestRequestMethod } from './rest-request-method';
@@ -52,7 +50,7 @@ const entryFromUUIDSelector = (uuid: string): MemoizedSelector<CoreState, Reques
* @param href Substring that the request's href should contain * @param href Substring that the request's href should contain
*/ */
const uuidsFromHrefSubstringSelector = const uuidsFromHrefSubstringSelector =
(selector: MemoizedSelector<AppState, IndexState>, href: string): MemoizedSelector<AppState, string[]> => createSelector( (selector: MemoizedSelector<CoreState, IndexState>, href: string): MemoizedSelector<CoreState, string[]> => createSelector(
selector, selector,
(state: IndexState) => getUuidsFromHrefSubstring(state, href) (state: IndexState) => getUuidsFromHrefSubstring(state, href)
); );

View File

@@ -1,6 +1,6 @@
import { Action } from '@ngrx/store'; import { Action } from '@ngrx/store';
import { type } from '../ngrx/type'; import { type } from '../../shared/ngrx/type';
export const HistoryActionTypes = { export const HistoryActionTypes = {
ADD_TO_HISTORY: type('dspace/history/ADD_TO_HISTORY'), ADD_TO_HISTORY: type('dspace/history/ADD_TO_HISTORY'),

View File

@@ -0,0 +1,3 @@
import { CoreState } from '../core.reducers';
export const historySelector = (state: CoreState) => state.history;

View File

@@ -1,5 +1,4 @@
import { createSelector, MemoizedSelector } from '@ngrx/store'; import { createSelector, MemoizedSelector } from '@ngrx/store';
import { AppState } from '../../app.reducer';
import { hasValue } from '../../shared/empty.util'; import { hasValue } from '../../shared/empty.util';
import { CoreState } from '../core.reducers'; import { CoreState } from '../core.reducers';
import { coreSelector } from '../core.selectors'; import { coreSelector } from '../core.selectors';
@@ -11,7 +10,7 @@ import { IndexName, IndexState, MetaIndexState } from './index.reducer';
* @returns * @returns
* a MemoizedSelector to select the MetaIndexState * a MemoizedSelector to select the MetaIndexState
*/ */
export const metaIndexSelector: MemoizedSelector<AppState, MetaIndexState> = createSelector( export const metaIndexSelector: MemoizedSelector<CoreState, MetaIndexState> = createSelector(
coreSelector, coreSelector,
(state: CoreState) => state.index (state: CoreState) => state.index
); );
@@ -23,7 +22,7 @@ export const metaIndexSelector: MemoizedSelector<AppState, MetaIndexState> = cre
* @returns * @returns
* a MemoizedSelector to select the object index * a MemoizedSelector to select the object index
*/ */
export const objectIndexSelector: MemoizedSelector<AppState, IndexState> = createSelector( export const objectIndexSelector: MemoizedSelector<CoreState, IndexState> = createSelector(
metaIndexSelector, metaIndexSelector,
(state: MetaIndexState) => state[IndexName.OBJECT] (state: MetaIndexState) => state[IndexName.OBJECT]
); );
@@ -34,7 +33,7 @@ export const objectIndexSelector: MemoizedSelector<AppState, IndexState> = creat
* @returns * @returns
* a MemoizedSelector to select the request index * a MemoizedSelector to select the request index
*/ */
export const requestIndexSelector: MemoizedSelector<AppState, IndexState> = createSelector( export const requestIndexSelector: MemoizedSelector<CoreState, IndexState> = createSelector(
metaIndexSelector, metaIndexSelector,
(state: MetaIndexState) => state[IndexName.REQUEST] (state: MetaIndexState) => state[IndexName.REQUEST]
); );
@@ -45,7 +44,7 @@ export const requestIndexSelector: MemoizedSelector<AppState, IndexState> = crea
* @returns * @returns
* a MemoizedSelector to select the request UUID mapping * a MemoizedSelector to select the request UUID mapping
*/ */
export const requestUUIDIndexSelector: MemoizedSelector<AppState, IndexState> = createSelector( export const requestUUIDIndexSelector: MemoizedSelector<CoreState, IndexState> = createSelector(
metaIndexSelector, metaIndexSelector,
(state: MetaIndexState) => state[IndexName.UUID_MAPPING] (state: MetaIndexState) => state[IndexName.UUID_MAPPING]
); );
@@ -53,14 +52,13 @@ export const requestUUIDIndexSelector: MemoizedSelector<AppState, IndexState> =
/** /**
* Return the self link of an object in the object-cache based on its UUID * Return the self link of an object in the object-cache based on its UUID
* *
* @param id * @param uuid
* the UUID for which you want to find the matching self link * the UUID for which you want to find the matching self link
* @param identifierType the type of index, used to select index from state
* @returns * @returns
* a MemoizedSelector to select the self link * a MemoizedSelector to select the self link
*/ */
export const selfLinkFromUuidSelector = export const selfLinkFromUuidSelector =
(uuid: string): MemoizedSelector<AppState, string> => createSelector( (uuid: string): MemoizedSelector<CoreState, string> => createSelector(
objectIndexSelector, objectIndexSelector,
(state: IndexState) => hasValue(state) ? state[uuid] : undefined (state: IndexState) => hasValue(state) ? state[uuid] : undefined
); );
@@ -74,7 +72,7 @@ export const selfLinkFromUuidSelector =
* a MemoizedSelector to select the UUID * a MemoizedSelector to select the UUID
*/ */
export const uuidFromHrefSelector = export const uuidFromHrefSelector =
(href: string): MemoizedSelector<AppState, string> => createSelector( (href: string): MemoizedSelector<CoreState, string> => createSelector(
requestIndexSelector, requestIndexSelector,
(state: IndexState) => hasValue(state) ? state[href] : undefined (state: IndexState) => hasValue(state) ? state[href] : undefined
); );
@@ -89,7 +87,7 @@ export const uuidFromHrefSelector =
* a MemoizedSelector to select the UUID of the cached request * a MemoizedSelector to select the UUID of the cached request
*/ */
export const originalRequestUUIDFromRequestUUIDSelector = export const originalRequestUUIDFromRequestUUIDSelector =
(uuid: string): MemoizedSelector<AppState, string> => createSelector( (uuid: string): MemoizedSelector<CoreState, string> => createSelector(
requestUUIDIndexSelector, requestUUIDIndexSelector,
(state: IndexState) => hasValue(state) ? state[uuid] : undefined (state: IndexState) => hasValue(state) ? state[uuid] : undefined
); );

View File

@@ -17,7 +17,6 @@ import {
} from './json-patch-operations.actions'; } from './json-patch-operations.actions';
import { JsonPatchOperationModel } from './json-patch.model'; import { JsonPatchOperationModel } from './json-patch.model';
import { getResponseFromEntry } from '../shared/operators'; import { getResponseFromEntry } from '../shared/operators';
import { ObjectCacheEntry } from '../cache/object-cache.reducer';
/** /**
* An abstract class that provides methods to make JSON Patch requests. * An abstract class that provides methods to make JSON Patch requests.
@@ -88,8 +87,8 @@ export abstract class JsonPatchOperationsService<ResponseDefinitionDomain, Patch
flatMap(() => { flatMap(() => {
const [successResponse$, errorResponse$] = partition((response: RestResponse) => response.isSuccessful)(this.requestService.getByUUID(requestId).pipe( const [successResponse$, errorResponse$] = partition((response: RestResponse) => response.isSuccessful)(this.requestService.getByUUID(requestId).pipe(
getResponseFromEntry(), getResponseFromEntry(),
find((entry: ObjectCacheEntry) => startTransactionTime < entry.timeAdded), find((entry: RestResponse) => startTransactionTime < entry.timeAdded),
map((entry: ObjectCacheEntry) => entry), map((entry: RestResponse) => entry),
)); ));
return observableMerge( return observableMerge(
errorResponse$.pipe( errorResponse$.pipe(

View File

@@ -8,7 +8,7 @@ import { getTestScheduler, hot } from 'jasmine-marbles';
import { RouteService } from './route.service'; import { RouteService } from './route.service';
import { MockRouter } from '../../shared/mocks/mock-router'; import { MockRouter } from '../../shared/mocks/mock-router';
import { TestScheduler } from 'rxjs/testing'; import { TestScheduler } from 'rxjs/testing';
import { AddUrlToHistoryAction } from '../../shared/history/history.actions'; import { AddUrlToHistoryAction } from '../history/history.actions';
describe('RouteService', () => { describe('RouteService', () => {
let scheduler: TestScheduler; let scheduler: TestScheduler;

View File

@@ -1,28 +1,17 @@
import { distinctUntilChanged, filter, map, take, tap } from 'rxjs/operators'; import { distinctUntilChanged, filter, map, take } from 'rxjs/operators';
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { import { ActivatedRoute, NavigationEnd, Params, Router, RouterStateSnapshot, } from '@angular/router';
ActivatedRoute,
NavigationEnd,
Params,
Router,
RouterStateSnapshot,
} from '@angular/router';
import { combineLatest, Observable } from 'rxjs'; import { combineLatest, Observable } from 'rxjs';
import { createSelector, MemoizedSelector, select, Store } from '@ngrx/store'; import { createSelector, MemoizedSelector, select, Store } from '@ngrx/store';
import { isEqual } from 'lodash'; import { isEqual } from 'lodash';
import { import { AddParameterAction, SetParameterAction, SetParametersAction, SetQueryParametersAction } from './route.actions';
AddParameterAction, import { CoreState } from '../core.reducers';
SetParameterAction, import { coreSelector } from '../core.selectors';
SetParametersAction,
SetQueryParametersAction
} from './route.actions';
import { CoreState } from '../../core/core.reducers';
import { coreSelector } from '../../core/core.selectors';
import { hasValue } from '../../shared/empty.util'; import { hasValue } from '../../shared/empty.util';
import { historySelector } from '../../shared/history/selectors'; import { historySelector } from '../history/selectors';
import { AddUrlToHistoryAction } from '../../shared/history/history.actions'; import { AddUrlToHistoryAction } from '../history/history.actions';
/** /**
* Selector to select all route parameters from the store * Selector to select all route parameters from the store

View File

@@ -1,6 +1,6 @@
<ul class="navbar-nav" [ngClass]="{'mr-auto': (isXsOrSm$ | async)}"> <ul class="navbar-nav" [ngClass]="{'mr-auto': (isXsOrSm$ | async)}">
<li *ngIf="!(isAuthenticated | async) && !(isXsOrSm$ | async) && (showAuth | async)" class="nav-item" (click)="$event.stopPropagation();"> <li *ngIf="!(isAuthenticated | async) && !(isXsOrSm$ | async) && (showAuth | async)" class="nav-item" (click)="$event.stopPropagation();">
<div ngbDropdown placement="bottom-right" class="d-inline-block" @fadeInOut> <div ngbDropdown display="dynamic" placement="bottom-right" class="d-inline-block" @fadeInOut>
<a href="#" id="dropdownLogin" (click)="$event.preventDefault()" ngbDropdownToggle class="px-1">{{ 'nav.login' | translate }}</a> <a href="#" id="dropdownLogin" (click)="$event.preventDefault()" ngbDropdownToggle class="px-1">{{ 'nav.login' | translate }}</a>
<div id="loginDropdownMenu" [ngClass]="{'pl-3 pr-3': (loading | async)}" ngbDropdownMenu aria-labelledby="dropdownLogin"> <div id="loginDropdownMenu" [ngClass]="{'pl-3 pr-3': (loading | async)}" ngbDropdownMenu aria-labelledby="dropdownLogin">
<ds-log-in <ds-log-in
@@ -12,7 +12,7 @@
<a id="loginLink" routerLink="/login" routerLinkActive="active" class="px-1" >{{ 'nav.login' | translate }}<span class="sr-only">(current)</span></a> <a id="loginLink" routerLink="/login" routerLinkActive="active" class="px-1" >{{ 'nav.login' | translate }}<span class="sr-only">(current)</span></a>
</li> </li>
<li *ngIf="(isAuthenticated | async) && !(isXsOrSm$ | async) && (showAuth | async)" class="nav-item"> <li *ngIf="(isAuthenticated | async) && !(isXsOrSm$ | async) && (showAuth | async)" class="nav-item">
<div ngbDropdown placement="bottom-right" class="d-inline-block" @fadeInOut> <div ngbDropdown display="dynamic" placement="bottom-right" class="d-inline-block" @fadeInOut>
<a href="#" id="dropdownUser" (click)="$event.preventDefault()" class="px-1" ngbDropdownToggle><i class="fas fa-user-circle fa-lg fa-fw" [title]="'nav.logout' | translate"></i></a> <a href="#" id="dropdownUser" (click)="$event.preventDefault()" class="px-1" ngbDropdownToggle><i class="fas fa-user-circle fa-lg fa-fw" [title]="'nav.logout' | translate"></i></a>
<div id="logoutDropdownMenu" ngbDropdownMenu aria-labelledby="dropdownUser"> <div id="logoutDropdownMenu" ngbDropdownMenu aria-labelledby="dropdownUser">
<ds-user-menu></ds-user-menu> <ds-user-menu></ds-user-menu>

View File

@@ -3,9 +3,8 @@ import { TranslateModule } from '@ngx-translate/core';
import { Location } from '@angular/common'; import { Location } from '@angular/common';
import { RouterTestingModule } from '@angular/router/testing'; import { RouterTestingModule } from '@angular/router/testing';
import { NO_ERRORS_SCHEMA } from '@angular/core'; import { NO_ERRORS_SCHEMA } from '@angular/core';
import { DynamicFormService, DynamicInputModel } from '@ng-dynamic-forms/core'; import { DynamicFormControlModel, DynamicFormService, DynamicInputModel } from '@ng-dynamic-forms/core';
import { FormControl, FormGroup } from '@angular/forms'; import { FormControl, FormGroup } from '@angular/forms';
import { DynamicFormControlModel } from '@ng-dynamic-forms/core/src/model/dynamic-form-control.model';
import { Community } from '../../../core/shared/community.model'; import { Community } from '../../../core/shared/community.model';
import { ComColFormComponent } from './comcol-form.component'; import { ComColFormComponent } from './comcol-form.component';
import { DSpaceObject } from '../../../core/shared/dspace-object.model'; import { DSpaceObject } from '../../../core/shared/dspace-object.model';
@@ -137,7 +136,7 @@ describe('ComColFormComponent', () => {
type: Community.type type: Community.type
}, },
), ),
uploader: {}, uploader: {} as any,
deleteLogo: false deleteLogo: false
} }
); );

View File

@@ -1,9 +1,13 @@
import { Component, EventEmitter, Input, OnDestroy, OnInit, Output, ViewChild } from '@angular/core'; import { Component, EventEmitter, Input, OnDestroy, OnInit, Output, ViewChild } from '@angular/core';
import { Location } from '@angular/common'; import { Location } from '@angular/common';
import { DynamicFormService, DynamicInputModel } from '@ng-dynamic-forms/core'; import {
DynamicFormControlModel,
DynamicFormService,
DynamicInputModel
} from '@ng-dynamic-forms/core';
import { FormGroup } from '@angular/forms'; import { FormGroup } from '@angular/forms';
import { DynamicFormControlModel } from '@ng-dynamic-forms/core/src/model/dynamic-form-control.model';
import { TranslateService } from '@ngx-translate/core'; import { TranslateService } from '@ngx-translate/core';
import { DSpaceObject } from '../../../core/shared/dspace-object.model'; import { DSpaceObject } from '../../../core/shared/dspace-object.model';
import { MetadataMap, MetadataValue } from '../../../core/shared/metadata.models'; import { MetadataMap, MetadataValue } from '../../../core/shared/metadata.models';
import { ResourceType } from '../../../core/shared/resource-type'; import { ResourceType } from '../../../core/shared/resource-type';
@@ -186,7 +190,7 @@ export class ComColFormComponent<T extends DSpaceObject> implements OnInit, OnDe
}); });
} }
const formMetadata = new Object() as MetadataMap; const formMetadata = {} as MetadataMap;
this.formModel.forEach((fieldModel: DynamicInputModel) => { this.formModel.forEach((fieldModel: DynamicInputModel) => {
const value: MetadataValue = { const value: MetadataValue = {
value: fieldModel.value as string, value: fieldModel.value as string,

View File

@@ -32,7 +32,7 @@ import {
DynamicFormControl, DynamicFormControl,
DynamicFormControlContainerComponent, DynamicFormControlContainerComponent,
DynamicFormControlEvent, DynamicFormControlEvent,
DynamicFormControlModel, DynamicFormControlModel, DynamicFormInstancesService,
DynamicFormLayout, DynamicFormLayout,
DynamicFormLayoutService, DynamicFormLayoutService,
DynamicFormValidationService, DynamicFormValidationService,
@@ -213,6 +213,7 @@ export class DsDynamicFormControlContainerComponent extends DynamicFormControlCo
constructor( constructor(
protected componentFactoryResolver: ComponentFactoryResolver, protected componentFactoryResolver: ComponentFactoryResolver,
protected dynamicFormInstanceService: DynamicFormInstancesService,
protected layoutService: DynamicFormLayoutService, protected layoutService: DynamicFormLayoutService,
protected validationService: DynamicFormValidationService, protected validationService: DynamicFormValidationService,
protected translateService: TranslateService, protected translateService: TranslateService,
@@ -225,7 +226,8 @@ export class DsDynamicFormControlContainerComponent extends DynamicFormControlCo
private store: Store<AppState>, private store: Store<AppState>,
private submissionObjectService: SubmissionObjectDataService private submissionObjectService: SubmissionObjectDataService
) { ) {
super(componentFactoryResolver, layoutService, validationService);
super(componentFactoryResolver, layoutService, validationService, dynamicFormInstanceService);
} }
/** /**

View File

@@ -1,5 +1,10 @@
import { DynamicDateControlModel, DynamicFormControlLayout, serializable } from '@ng-dynamic-forms/core'; import {
import { DynamicDateControlModelConfig } from '@ng-dynamic-forms/core/src/model/dynamic-date-control.model'; DynamicDateControlModel,
DynamicDateControlModelConfig,
DynamicFormControlLayout,
serializable
} from '@ng-dynamic-forms/core';
import { Subject } from 'rxjs'; import { Subject } from 'rxjs';
export const DYNAMIC_FORM_CONTROL_TYPE_DSDATEPICKER = 'DATE'; export const DYNAMIC_FORM_CONTROL_TYPE_DSDATEPICKER = 'DATE';

View File

@@ -1,7 +1,12 @@
import { DynamicFormControlLayout, DynamicFormGroupModel, serializable } from '@ng-dynamic-forms/core'; import {
DynamicFormControlLayout,
DynamicFormGroupModel,
DynamicFormGroupModelConfig,
serializable
} from '@ng-dynamic-forms/core';
import { DsDynamicInputModel } from './ds-dynamic-input.model'; import { DsDynamicInputModel } from './ds-dynamic-input.model';
import { Subject } from 'rxjs'; import { Subject } from 'rxjs';
import { DynamicFormGroupModelConfig } from '@ng-dynamic-forms/core/src/model/form-group/dynamic-form-group.model';
import { LanguageCode } from '../../models/form-field-language-value.model'; import { LanguageCode } from '../../models/form-field-language-value.model';
export const QUALDROP_GROUP_SUFFIX = '_QUALDROP_GROUP'; export const QUALDROP_GROUP_SUFFIX = '_QUALDROP_GROUP';

View File

@@ -136,7 +136,10 @@ export class DsDynamicLookupRelationModalComponent implements OnInit, OnDestroy
); );
const relatedItems$: Observable<Item[]> = relatedItemPairs$.pipe( const relatedItems$: Observable<Item[]> = relatedItemPairs$.pipe(
map(([relatedItemPairs,]: [Array<[Item, Item]>]) => relatedItemPairs.map(([left, right]: [Item, Item]) => left.uuid === this.item.uuid ? left : right)) map((relatedItemPairs: Array<[Item, Item]>) => {
return relatedItemPairs
.map(([left, right]: [Item, Item]) => left.uuid === this.item.uuid ? left : right)
})
); );
relatedItems$.pipe(take(1)).subscribe((relatedItems) => { relatedItems$.pipe(take(1)).subscribe((relatedItems) => {

View File

@@ -113,7 +113,7 @@ describe('DsDynamicLookupRelationSearchTabComponent', () => {
}); });
it('should emit the page filtered from not yet selected objects and call select on the service for all objects', () => { it('should emit the page filtered from not yet selected objects and call select on the service for all objects', () => {
expect(component.deselectObject.emit).toHaveBeenCalledWith(searchResult1, searchResult2); expect((component.deselectObject as any).emit).toHaveBeenCalledWith(searchResult1, searchResult2);
expect(selectableListService.deselect).toHaveBeenCalledWith(listID, [searchResult1, searchResult2, searchResult3]); expect(selectableListService.deselect).toHaveBeenCalledWith(listID, [searchResult1, searchResult2, searchResult3]);
}); });
}); });
@@ -137,7 +137,7 @@ describe('DsDynamicLookupRelationSearchTabComponent', () => {
}); });
it('should emit the page filtered from not yet selected objects and call select on the service for all objects', () => { it('should emit the page filtered from not yet selected objects and call select on the service for all objects', () => {
expect(component.deselectObject.emit).toHaveBeenCalledWith(searchResult1, searchResult2); expect((component.deselectObject as any).emit).toHaveBeenCalledWith(searchResult1, searchResult2);
expect(selectableListService.deselectAll).toHaveBeenCalledWith(listID); expect(selectableListService.deselectAll).toHaveBeenCalledWith(listID);
}); });
}); });

View File

@@ -15,7 +15,6 @@ import { Router } from '@angular/router';
import { SelectableListService } from '../../../../../object-list/selectable-list/selectable-list.service'; import { SelectableListService } from '../../../../../object-list/selectable-list/selectable-list.service';
import { hasValue, isNotEmpty } from '../../../../../empty.util'; import { hasValue, isNotEmpty } from '../../../../../empty.util';
import { concat, map, multicast, switchMap, take, takeWhile, tap } from 'rxjs/operators'; import { concat, map, multicast, switchMap, take, takeWhile, tap } from 'rxjs/operators';
import { DSpaceObject } from '../../../../../../core/shared/dspace-object.model';
import { getSucceededRemoteData } from '../../../../../../core/shared/operators'; import { getSucceededRemoteData } from '../../../../../../core/shared/operators';
import { RouteService } from '../../../../../../core/services/route.service'; import { RouteService } from '../../../../../../core/services/route.service';
import { CollectionElementLinkType } from '../../../../../object-collection/collection-element-link.type'; import { CollectionElementLinkType } from '../../../../../object-collection/collection-element-link.type';
@@ -87,13 +86,13 @@ export class DsDynamicLookupRelationSearchTabComponent implements OnInit, OnDest
multicast( multicast(
() => new ReplaySubject(1), () => new ReplaySubject(1),
(subject) => subject.pipe( (subject) => subject.pipe(
takeWhile((rd: RemoteData<PaginatedList<SearchResult<DSpaceObject>>>) => rd.isLoading), takeWhile((rd: RemoteData<PaginatedList<SearchResult<Item>>>) => rd.isLoading),
concat(subject.pipe(take(1))) concat(subject.pipe(take(1)))
) )
) as any ) as any
) )
}) })
); ) as Observable<RemoteData<PaginatedList<SearchResult<Item>>>>;
} }
/** /**

View File

@@ -10,10 +10,8 @@ import {
DynamicFormArrayModel, DynamicFormArrayModel,
DynamicFormControlModel, DynamicFormControlModel,
DynamicFormGroupModel, DynamicFormGroupModel,
DynamicFormService, DynamicFormService, DynamicFormValidationService,
DynamicFormValidationService, DynamicPathable, parseReviver,
DynamicPathable,
JSONUtils,
} from '@ng-dynamic-forms/core'; } from '@ng-dynamic-forms/core';
import { isObject, isString, mergeWith } from 'lodash'; import { isObject, isString, mergeWith } from 'lodash';
@@ -205,7 +203,7 @@ export class FormBuilderService extends DynamicFormService {
modelFromConfiguration(submissionId: string, json: string | SubmissionFormsModel, scopeUUID: string, sectionData: any = {}, submissionScope?: string, readOnly = false): DynamicFormControlModel[] | never { modelFromConfiguration(submissionId: string, json: string | SubmissionFormsModel, scopeUUID: string, sectionData: any = {}, submissionScope?: string, readOnly = false): DynamicFormControlModel[] | never {
let rows: DynamicFormControlModel[] = []; let rows: DynamicFormControlModel[] = [];
const rawData = typeof json === 'string' ? JSON.parse(json, JSONUtils.parseReviver) : json; const rawData = typeof json === 'string' ? JSON.parse(json, parseReviver) : json;
if (rawData.rows && !isEmpty(rawData.rows)) { if (rawData.rows && !isEmpty(rawData.rows)) {
rawData.rows.forEach((currentRow) => { rawData.rows.forEach((currentRow) => {

View File

@@ -1,3 +0,0 @@
import { AppState } from '../../app.reducer';
export const historySelector = (state: AppState) => state.history;

View File

@@ -1,40 +1,43 @@
import * as ngrx from '@ngrx/store';
import { Store } from '@ngrx/store';
import { async, TestBed } from '@angular/core/testing'; import { async, TestBed } from '@angular/core/testing';
import { MenuService } from './menu.service';
import { cold, hot } from 'jasmine-marbles';
import { MenuID } from './initial-menus-state';
import { of as observableOf } from 'rxjs'; import { of as observableOf } from 'rxjs';
import * as ngrx from '@ngrx/store';
import { Store, StoreModule } from '@ngrx/store';
import { provideMockStore } from '@ngrx/store/testing';
import { cold, hot } from 'jasmine-marbles';
import { MenuService } from './menu.service';
import { MenuID } from './initial-menus-state';
import { import {
ActivateMenuSectionAction, ActivateMenuSectionAction,
AddMenuSectionAction, AddMenuSectionAction,
CollapseMenuAction, CollapseMenuPreviewAction, DeactivateMenuSectionAction, CollapseMenuAction,
ExpandMenuAction, ExpandMenuPreviewAction, HideMenuAction, CollapseMenuPreviewAction,
RemoveMenuSectionAction, ShowMenuAction, ToggleActiveMenuSectionAction, ToggleMenuAction DeactivateMenuSectionAction,
ExpandMenuAction,
ExpandMenuPreviewAction,
HideMenuAction,
RemoveMenuSectionAction,
ShowMenuAction,
ToggleActiveMenuSectionAction,
ToggleMenuAction
} from './menu.actions'; } from './menu.actions';
import { MenuSection, menusReducer } from './menu.reducer';
describe('MenuService', () => { describe('MenuService', () => {
let service: MenuService; let service: MenuService;
let selectSpy; let selectSpy;
let store; let store: any;
let fakeMenu; let fakeMenu;
let visibleSection1; let visibleSection1;
let visibleSection2; let visibleSection2;
let hiddenSection3; let hiddenSection3;
let subSection4; let subSection4;
let topSections; let topSections;
let initialState;
function init() { function init() {
store = Object.assign(observableOf({}), {
dispatch: () => {/***/
}
}) as any;
fakeMenu = {
id: MenuID.ADMIN,
collapsed: true,
visible: false,
previewCollapsed: true
} as any;
visibleSection1 = { visibleSection1 = {
id: 'section', id: 'section',
visible: true, visible: true,
@@ -60,35 +63,44 @@ describe('MenuService', () => {
section_3: hiddenSection3, section_3: hiddenSection3,
section_4: subSection4 section_4: subSection4
}; };
fakeMenu = {
id: MenuID.ADMIN,
collapsed: true,
visible: false,
sections: topSections,
previewCollapsed: true
} as any;
initialState = {
menus: {
'admin-sidebar' : fakeMenu
}
};
} }
beforeEach(async(() => { beforeEach(async(() => {
init(); init();
TestBed.configureTestingModule({ TestBed.configureTestingModule({
imports: [
StoreModule.forRoot({ menus: menusReducer })
],
providers: [ providers: [
{ provide: Store, useValue: store }, provideMockStore({ initialState }),
{ provide: MenuService, useValue: service } { provide: MenuService, useValue: service }
] ]
}).compileComponents(); }).compileComponents();
})); }));
beforeEach(() => { beforeEach(() => {
store = TestBed.get(Store);
service = new MenuService(store); service = new MenuService(store);
selectSpy = spyOnProperty(ngrx, 'select'); selectSpy = spyOnProperty(ngrx, 'select').and.callThrough();
spyOn(store, 'dispatch'); spyOn(store, 'dispatch');
}); });
describe('getMenu', () => { describe('getMenu', () => {
beforeEach(() => {
selectSpy.and.callFake(() => {
return () => {
return () => hot('a', {
a: fakeMenu
}
);
};
});
});
it('should return the menu', () => { it('should return the menu', () => {
const result = service.getMenu(MenuID.ADMIN); const result = service.getMenu(MenuID.ADMIN);
@@ -136,7 +148,7 @@ describe('MenuService', () => {
describe('when the subsection list is not empty', () => { describe('when the subsection list is not empty', () => {
beforeEach(() => { beforeEach(() => {
spyOn(service, 'getMenuSection').and.returnValue(observableOf(visibleSection1)); spyOn(service, 'getMenuSection').and.returnValue(observableOf(visibleSection1 as MenuSection));
selectSpy.and.callFake(() => { selectSpy.and.callFake(() => {
return () => { return () => {
return () => hot('a', { return () => hot('a', {
@@ -225,25 +237,25 @@ describe('MenuService', () => {
}); });
describe('getMenuSection', () => { describe('getMenuSection', () => {
beforeEach(() => { it('should return menu section', () => {
selectSpy.and.callFake(() => {
return () => {
return () => hot('a', {
a: hiddenSection3
}
);
};
});
});
it('should return false', () => {
const result = service.getMenuSection(MenuID.ADMIN, 'fakeId'); const result = service.getMenuSection(MenuID.ADMIN, 'section_3');
const expected = cold('b', { const expected = cold('b', {
b: hiddenSection3 b: hiddenSection3
}); });
expect(result).toBeObservable(expected); expect(result).toBeObservable(expected);
}); });
it('should return undefined', () => {
const result = service.getMenuSection(MenuID.ADMIN, 'fake');
const expected = cold('b', {
b: undefined
});
expect(result).toBeObservable(expected);
});
}); });
describe('isMenuCollapsed', () => { describe('isMenuCollapsed', () => {
@@ -294,7 +306,7 @@ describe('MenuService', () => {
describe('isSectionActive', () => { describe('isSectionActive', () => {
beforeEach(() => { beforeEach(() => {
spyOn(service, 'getMenuSection').and.returnValue(observableOf(visibleSection1)); spyOn(service, 'getMenuSection').and.returnValue(observableOf(visibleSection1 as MenuSection));
}); });
it('should return false when the section is not active', () => { it('should return false when the section is not active', () => {
@@ -309,7 +321,7 @@ describe('MenuService', () => {
describe('isSectionVisible', () => { describe('isSectionVisible', () => {
beforeEach(() => { beforeEach(() => {
spyOn(service, 'getMenuSection').and.returnValue(observableOf(hiddenSection3)); spyOn(service, 'getMenuSection').and.returnValue(observableOf(hiddenSection3 as MenuSection));
}); });
it('should return false when the section is hidden', () => { it('should return false when the section is hidden', () => {

View File

@@ -1,24 +1,35 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { MemoizedSelector, select, Store } from '@ngrx/store'; import { createSelector, MemoizedSelector, select, Store } from '@ngrx/store';
import { MenuSection, MenuSectionIndex, MenuSections, MenusState, MenuState } from './menu.reducer'; import { MenuSection, MenuSections, MenuState } from './menu.reducer';
import { AppState, keySelector } from '../../app.reducer'; import { AppState, keySelector } from '../../app.reducer';
import { MenuID } from './initial-menus-state'; import { MenuID } from './initial-menus-state';
import { Observable } from 'rxjs'; import { combineLatest as observableCombineLatest, Observable } from 'rxjs';
import { map, switchMap } from 'rxjs/operators'; import { map, switchMap } from 'rxjs/operators';
import { import {
ActivateMenuSectionAction, ActivateMenuSectionAction,
AddMenuSectionAction, AddMenuSectionAction,
CollapseMenuAction, CollapseMenuPreviewAction, CollapseMenuAction,
CollapseMenuPreviewAction,
DeactivateMenuSectionAction, DeactivateMenuSectionAction,
ExpandMenuAction, ExpandMenuPreviewAction, ExpandMenuAction,
ExpandMenuPreviewAction,
HideMenuAction, HideMenuAction,
RemoveMenuSectionAction, RemoveMenuSectionAction,
ShowMenuAction, ShowMenuAction,
ToggleActiveMenuSectionAction, ToggleActiveMenuSectionAction,
ToggleMenuAction, ToggleMenuAction,
} from './menu.actions'; } from './menu.actions';
import { hasNoValue, isNotEmpty } from '../empty.util'; import { hasNoValue, hasValue, isNotEmpty } from '../empty.util';
import { combineLatest as observableCombineLatest } from 'rxjs';
export function menuKeySelector<T>(key: string, selector): MemoizedSelector<MenuState, T> {
return createSelector(selector, (state) => {
if (hasValue(state)) {
return state[key];
} else {
return undefined;
}
});
}
const menusStateSelector = (state) => state.menus; const menusStateSelector = (state) => state.menus;
@@ -28,20 +39,20 @@ const menuByIDSelector = (menuID: MenuID): MemoizedSelector<AppState, MenuState>
const menuSectionStateSelector = (state: MenuState) => state.sections; const menuSectionStateSelector = (state: MenuState) => state.sections;
const menuSectionByIDSelector = (id: string): MemoizedSelector<AppState, MenuSection> => { const menuSectionByIDSelector = (id: string): MemoizedSelector<MenuState, MenuSection> => {
return keySelector<MenuSection>(id, menuSectionStateSelector); return menuKeySelector<MenuSection>(id, menuSectionStateSelector);
}; };
const menuSectionIndexStateSelector = (state: MenuState) => state.sectionToSubsectionIndex; const menuSectionIndexStateSelector = (state: MenuState) => state.sectionToSubsectionIndex;
const getSubSectionsFromSectionSelector = (id: string): MemoizedSelector<AppState, MenuSectionIndex> => { const getSubSectionsFromSectionSelector = (id: string): MemoizedSelector<MenuState, string[]> => {
return keySelector<MenuSectionIndex>(id, menuSectionIndexStateSelector); return menuKeySelector<string[]>(id, menuSectionIndexStateSelector);
}; };
@Injectable() @Injectable()
export class MenuService { export class MenuService {
constructor(private store: Store<MenusState>) { constructor(private store: Store<AppState>) {
} }
/** /**

View File

@@ -88,7 +88,7 @@ describe('ItemDetailPreviewComponent', () => {
component.object = { hitHighlights: {} } as any; component.object = { hitHighlights: {} } as any;
component.item = mockItem; component.item = mockItem;
component.separator = ', '; component.separator = ', ';
spyOn(component.item, 'getFiles').and.returnValue(mockItem.bundles); spyOn(component.item, 'getFiles').and.returnValue(mockItem.bundles as any);
fixture.detectChanges(); fixture.detectChanges();
})); }));

View File

@@ -13,7 +13,7 @@ import { DSpaceObject } from '../../core/shared/dspace-object.model';
describe('ObjectDetailComponent', () => { describe('ObjectDetailComponent', () => {
let comp: ObjectDetailComponent; let comp: ObjectDetailComponent;
let fixture: ComponentFixture<ObjectDetailComponent>; let fixture: ComponentFixture<ObjectDetailComponent>;
const testEvent = {test: 'test'}; const testEvent: any = {test: 'test'};
const testObjects = [ const testObjects = [
Object.assign (new DSpaceObject(), { one: 1 }), Object.assign (new DSpaceObject(), { one: 1 }),
@@ -27,7 +27,7 @@ describe('ObjectDetailComponent', () => {
Object.assign (new DSpaceObject(), { nine: 9 }), Object.assign (new DSpaceObject(), { nine: 9 }),
Object.assign (new DSpaceObject(), { ten: 10 }), Object.assign (new DSpaceObject(), { ten: 10 }),
]; ];
const pageInfo = Object.assign(new PageInfo(), {elementsPerPage: 1, totalElements: 10, totalPages: 10, currentPage: 1}) const pageInfo = Object.assign(new PageInfo(), {elementsPerPage: 1, totalElements: 10, totalPages: 10, currentPage: 1});
const mockRD = createSuccessfulRemoteDataObject(new PaginatedList(pageInfo, testObjects)); const mockRD = createSuccessfulRemoteDataObject(new PaginatedList(pageInfo, testObjects));
beforeEach(async(() => { beforeEach(async(() => {

View File

@@ -7,7 +7,7 @@ import { SelectableListService } from './selectable-list/selectable-list.service
describe('ObjectListComponent', () => { describe('ObjectListComponent', () => {
let comp: ObjectListComponent; let comp: ObjectListComponent;
let fixture: ComponentFixture<ObjectListComponent>; let fixture: ComponentFixture<ObjectListComponent>;
const testEvent = { test: 'test' }; const testEvent: any = { test: 'test' };
beforeEach(async(() => { beforeEach(async(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({

View File

@@ -1,10 +1,15 @@
import { Store } from '@ngrx/store'; import { Store } from '@ngrx/store';
import { async, TestBed } from '@angular/core/testing'; import { async, TestBed } from '@angular/core/testing';
import { SelectableListService } from './selectable-list.service'; import { SelectableListService } from './selectable-list.service';
import { SelectableListsState } from './selectable-list.reducer';
import { ListableObject } from '../../object-collection/shared/listable-object.model'; import { ListableObject } from '../../object-collection/shared/listable-object.model';
import { hasValue } from '../../empty.util'; import { hasValue } from '../../empty.util';
import { SelectableListDeselectAction, SelectableListDeselectSingleAction, SelectableListSelectAction, SelectableListSelectSingleAction } from './selectable-list.actions'; import {
SelectableListDeselectAction,
SelectableListDeselectSingleAction,
SelectableListSelectAction,
SelectableListSelectSingleAction
} from './selectable-list.actions';
import { AppState } from '../../../app.reducer';
class SelectableObject extends ListableObject { class SelectableObject extends ListableObject {
constructor(private value: string) { constructor(private value: string) {
@@ -33,7 +38,7 @@ describe('SelectableListService', () => {
const selected4 = new SelectableObject(value4); const selected4 = new SelectableObject(value4);
let service: SelectableListService; let service: SelectableListService;
const store: Store<SelectableListsState> = jasmine.createSpyObj('store', { const store: Store<AppState> = jasmine.createSpyObj('store', {
/* tslint:disable:no-empty */ /* tslint:disable:no-empty */
dispatch: {}, dispatch: {},
/* tslint:enable:no-empty */ /* tslint:enable:no-empty */

View File

@@ -1,18 +1,20 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { MemoizedSelector, select, Store } from '@ngrx/store'; import { MemoizedSelector, select, Store } from '@ngrx/store';
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
import { distinctUntilChanged, filter, map, startWith, tap } from 'rxjs/operators'; import { distinctUntilChanged, map } from 'rxjs/operators';
import { SelectableListsState, SelectableListState } from './selectable-list.reducer'; import { SelectableListState } from './selectable-list.reducer';
import { AppState, keySelector } from '../../../app.reducer'; import { AppState, keySelector } from '../../../app.reducer';
import { ListableObject } from '../../object-collection/shared/listable-object.model'; import { ListableObject } from '../../object-collection/shared/listable-object.model';
import { import {
SelectableListDeselectAction, SelectableListDeselectAllAction, SelectableListDeselectAction,
SelectableListDeselectSingleAction, SelectableListSelectAction, SelectableListDeselectAllAction,
SelectableListDeselectSingleAction,
SelectableListSelectAction,
SelectableListSelectSingleAction SelectableListSelectSingleAction
} from './selectable-list.actions'; } from './selectable-list.actions';
import { hasNoValue, hasValue, isNotEmpty } from '../../empty.util'; import { hasValue, isNotEmpty } from '../../empty.util';
const selectableListsStateSelector = (state) => state.selectableLists; const selectableListsStateSelector = (state: AppState) => state.selectableLists;
const menuByIDSelector = (id: string): MemoizedSelector<AppState, SelectableListState> => { const menuByIDSelector = (id: string): MemoizedSelector<AppState, SelectableListState> => {
return keySelector<SelectableListState>(id, selectableListsStateSelector); return keySelector<SelectableListState>(id, selectableListsStateSelector);
@@ -21,7 +23,7 @@ const menuByIDSelector = (id: string): MemoizedSelector<AppState, SelectableList
@Injectable() @Injectable()
export class SelectableListService { export class SelectableListService {
constructor(private store: Store<SelectableListsState>) { constructor(private store: Store<AppState>) {
} }
/** /**

View File

@@ -0,0 +1,109 @@
import { async, TestBed } from '@angular/core/testing';
import * as ngrx from '@ngrx/store';
import { Store, StoreModule } from '@ngrx/store';
import { provideMockStore } from '@ngrx/store/testing';
import { cold } from 'jasmine-marbles';
import { sidebarFilterReducer } from './sidebar-filter.reducer';
import { SidebarFilterService } from './sidebar-filter.service';
import {
FilterCollapseAction,
FilterExpandAction,
FilterInitializeAction,
FilterToggleAction
} from './sidebar-filter.actions';
describe('SidebarFilterService', () => {
let service: SidebarFilterService;
let selectSpy;
let store: any;
let initialState;
function init() {
initialState = {
sidebarFilter: {
filter_1 : {
filterCollapsed: true
},
filter_2 : {
filterCollapsed: false
},
filter_3 : {
filterCollapsed: true
}
}
};
}
beforeEach(async(() => {
init();
TestBed.configureTestingModule({
imports: [
StoreModule.forRoot({ sidebarFilter: sidebarFilterReducer })
],
providers: [
provideMockStore({ initialState }),
{ provide: SidebarFilterService, useValue: service }
]
}).compileComponents();
}));
beforeEach(() => {
store = TestBed.get(Store);
service = new SidebarFilterService(store);
selectSpy = spyOnProperty(ngrx, 'select').and.callThrough();
spyOn(store, 'dispatch');
});
describe('initializeFilter', () => {
it('should dispatch an FilterInitializeAction with the correct arguments', () => {
service.initializeFilter('fakeFilter', true);
expect(store.dispatch).toHaveBeenCalledWith(new FilterInitializeAction('fakeFilter', true));
});
});
describe('collapse', () => {
it('should dispatch an FilterInitializeAction with the correct arguments', () => {
service.collapse('fakeFilter');
expect(store.dispatch).toHaveBeenCalledWith(new FilterCollapseAction('fakeFilter'));
});
});
describe('expand', () => {
it('should dispatch an FilterInitializeAction with the correct arguments', () => {
service.expand('fakeFilter');
expect(store.dispatch).toHaveBeenCalledWith(new FilterExpandAction('fakeFilter'));
});
});
describe('toggle', () => {
it('should dispatch an FilterInitializeAction with the correct arguments', () => {
service.toggle('fakeFilter');
expect(store.dispatch).toHaveBeenCalledWith(new FilterToggleAction('fakeFilter'));
});
});
describe('isCollapsed', () => {
it('should return true', () => {
const result = service.isCollapsed('filter_1');
const expected = cold('b', {
b: true
});
expect(result).toBeObservable(expected);
});
it('should return false', () => {
const result = service.isCollapsed('filter_2');
const expected = cold('b', {
b: false
});
expect(result).toBeObservable(expected);
});
});
});

View File

@@ -16,7 +16,7 @@ import { hasValue } from '../../empty.util';
@Injectable() @Injectable()
export class SidebarFilterService { export class SidebarFilterService {
constructor(private store:Store<SidebarFilterState>) { constructor(private store:Store<SidebarFiltersState>) {
} }
/** /**

View File

@@ -3,8 +3,8 @@ import { CommonModule } from '@angular/common';
import { RouterTestingModule } from '@angular/router/testing'; import { RouterTestingModule } from '@angular/router/testing';
import { TranslateModule } from '@ngx-translate/core'; import { TranslateModule } from '@ngx-translate/core';
import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
import { ActivatedRoute, Router } from '@angular/router'; import { ActivatedRoute, NavigationExtras, Router } from '@angular/router';
import { DebugElement, NO_ERRORS_SCHEMA } from '@angular/core'; import { NO_ERRORS_SCHEMA } from '@angular/core';
import { of as observableOf } from 'rxjs/internal/observable/of'; import { of as observableOf } from 'rxjs/internal/observable/of';
import { By } from '@angular/platform-browser'; import { By } from '@angular/platform-browser';
import { StartsWithDateComponent } from './starts-with-date.component'; import { StartsWithDateComponent } from './starts-with-date.component';
@@ -159,7 +159,7 @@ describe('StartsWithDateComponent', () => {
describe('when filling in the input form', () => { describe('when filling in the input form', () => {
let form; let form;
const expectedValue = '2015'; const expectedValue = '2015';
const extras = { const extras: NavigationExtras = {
queryParams: Object.assign({ startsWith: expectedValue }), queryParams: Object.assign({ startsWith: expectedValue }),
queryParamsHandling: 'merge' queryParamsHandling: 'merge'
}; };

View File

@@ -1,5 +1,5 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ActivatedRoute, Router } from '@angular/router'; import { ActivatedRoute, NavigationExtras, Router } from '@angular/router';
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';
import { RouterTestingModule } from '@angular/router/testing'; import { RouterTestingModule } from '@angular/router/testing';
import { TranslateModule } from '@ngx-translate/core'; import { TranslateModule } from '@ngx-translate/core';
@@ -66,7 +66,7 @@ describe('StartsWithTextComponent', () => {
let select; let select;
let input; let input;
const expectedValue = '0'; const expectedValue = '0';
const extras = { const extras: NavigationExtras = {
queryParams: Object.assign({ startsWith: expectedValue }), queryParams: Object.assign({ startsWith: expectedValue }),
queryParamsHandling: 'merge' queryParamsHandling: 'merge'
}; };
@@ -96,7 +96,7 @@ describe('StartsWithTextComponent', () => {
let select; let select;
let input; let input;
const expectedValue = options[1]; const expectedValue = options[1];
const extras = { const extras: NavigationExtras = {
queryParams: Object.assign({ startsWith: expectedValue }), queryParams: Object.assign({ startsWith: expectedValue }),
queryParamsHandling: 'merge' queryParamsHandling: 'merge'
}; };
@@ -126,7 +126,7 @@ describe('StartsWithTextComponent', () => {
let optionLink; let optionLink;
let input; let input;
const expectedValue = options[1]; const expectedValue = options[1];
const extras = { const extras: NavigationExtras = {
queryParams: Object.assign({ startsWith: expectedValue }), queryParams: Object.assign({ startsWith: expectedValue }),
queryParamsHandling: 'merge' queryParamsHandling: 'merge'
}; };
@@ -154,7 +154,7 @@ describe('StartsWithTextComponent', () => {
describe('when filling in the input form', () => { describe('when filling in the input form', () => {
let form; let form;
const expectedValue = 'A'; const expectedValue = 'A';
const extras = { const extras: NavigationExtras = {
queryParams: Object.assign({ startsWith: expectedValue }), queryParams: Object.assign({ startsWith: expectedValue }),
queryParamsHandling: 'merge' queryParamsHandling: 'merge'
}; };

View File

@@ -20,7 +20,7 @@ describe('Angulartics2DSpace', () => {
it('should use the statisticsService', () => { it('should use the statisticsService', () => {
provider.startTracking(); provider.startTracking();
expect(statisticsService.trackViewEvent).toHaveBeenCalledWith('mock-object'); expect(statisticsService.trackViewEvent).toHaveBeenCalledWith('mock-object' as any);
}); });
}); });

View File

@@ -342,7 +342,7 @@ describe('SubmissionFormCollectionComponent Component', () => {
fixture.detectChanges(); fixture.detectChanges();
expect(comp.searchField.reset).toHaveBeenCalled(); expect(comp.searchField.reset).toHaveBeenCalled();
expect(comp.collectionChange.emit).toHaveBeenCalledWith(submissionRestResponse[0]); expect(comp.collectionChange.emit).toHaveBeenCalledWith(submissionRestResponse[0] as any);
expect(submissionServiceStub.changeSubmissionCollection).toHaveBeenCalled(); expect(submissionServiceStub.changeSubmissionCollection).toHaveBeenCalled();
expect(comp.selectedCollectionId).toBe(mockCollectionList[1].collection.id); expect(comp.selectedCollectionId).toBe(mockCollectionList[1].collection.id);
expect(comp.selectedCollectionName$).toBeObservable(cold('(a|)', { expect(comp.selectedCollectionName$).toBeObservable(cold('(a|)', {

View File

@@ -37,6 +37,7 @@ import { getMockSectionUploadService } from '../../../../shared/mocks/mock-secti
import { FormFieldMetadataValueObject } from '../../../../shared/form/builder/models/form-field-metadata-value.model'; import { FormFieldMetadataValueObject } from '../../../../shared/form/builder/models/form-field-metadata-value.model';
import { Group } from '../../../../core/eperson/models/group.model'; import { Group } from '../../../../core/eperson/models/group.model';
import { SubmissionSectionUploadFileEditComponent } from './edit/section-upload-file-edit.component'; import { SubmissionSectionUploadFileEditComponent } from './edit/section-upload-file-edit.component';
import { FormBuilderService } from '../../../../shared/form/builder/form-builder.service';
function getMockFileService(): FileService { function getMockFileService(): FileService {
return jasmine.createSpyObj('FileService', { return jasmine.createSpyObj('FileService', {
@@ -104,7 +105,8 @@ describe('SubmissionSectionUploadFileComponent test suite', () => {
ChangeDetectorRef, ChangeDetectorRef,
NgbModal, NgbModal,
SubmissionSectionUploadFileComponent, SubmissionSectionUploadFileComponent,
SubmissionSectionUploadFileEditComponent SubmissionSectionUploadFileEditComponent,
FormBuilderService
], ],
schemas: [NO_ERRORS_SCHEMA] schemas: [NO_ERRORS_SCHEMA]
}).compileComponents().then(); }).compileComponents().then();

View File

@@ -3,14 +3,7 @@ import { HttpHeaders } from '@angular/common/http';
import { Router } from '@angular/router'; import { Router } from '@angular/router';
import { Observable, of as observableOf, Subscription, timer as observableTimer } from 'rxjs'; import { Observable, of as observableOf, Subscription, timer as observableTimer } from 'rxjs';
import { import { catchError, concatMap, distinctUntilChanged, filter, find, map, startWith, take, tap } from 'rxjs/operators';
catchError, concatMap,
distinctUntilChanged,
filter,
find,
map,
startWith, take, tap
} from 'rxjs/operators';
import { Store } from '@ngrx/store'; import { Store } from '@ngrx/store';
import { TranslateService } from '@ngx-translate/core'; import { TranslateService } from '@ngx-translate/core';
@@ -28,7 +21,12 @@ import {
SaveSubmissionSectionFormAction, SaveSubmissionSectionFormAction,
SetActiveSectionAction SetActiveSectionAction
} from './objects/submission-objects.actions'; } from './objects/submission-objects.actions';
import { SubmissionObjectEntry, SubmissionSectionEntry, SubmissionSectionError, SubmissionSectionObject } from './objects/submission-objects.reducer'; import {
SubmissionObjectEntry,
SubmissionSectionEntry,
SubmissionSectionError,
SubmissionSectionObject
} from './objects/submission-objects.reducer';
import { submissionObjectFromIdSelector } from './selectors'; import { submissionObjectFromIdSelector } from './selectors';
import { GlobalConfig } from '../../config/global-config.interface'; import { GlobalConfig } from '../../config/global-config.interface';
import { GLOBAL_CONFIG } from '../../config'; import { GLOBAL_CONFIG } from '../../config';
@@ -45,11 +43,7 @@ import { WorkspaceitemSectionsObject } from '../core/submission/models/workspace
import { RemoteData } from '../core/data/remote-data'; import { RemoteData } from '../core/data/remote-data';
import { ErrorResponse } from '../core/cache/response.models'; import { ErrorResponse } from '../core/cache/response.models';
import { RemoteDataError } from '../core/data/remote-data-error'; import { RemoteDataError } from '../core/data/remote-data-error';
import { import { createFailedRemoteDataObject$, createSuccessfulRemoteDataObject } from '../shared/testing/utils';
createFailedRemoteDataObject$,
createSuccessfulRemoteDataObject,
createSuccessfulRemoteDataObject$
} from '../shared/testing/utils';
import { RequestService } from '../core/data/request.service'; import { RequestService } from '../core/data/request.service';
import { SearchService } from '../core/shared/search/search.service'; import { SearchService } from '../core/shared/search/search.service';
@@ -114,8 +108,8 @@ export class SubmissionService {
*/ */
createSubmission(): Observable<SubmissionObject> { createSubmission(): Observable<SubmissionObject> {
return this.restService.postToEndpoint(this.workspaceLinkPath, {}).pipe( return this.restService.postToEndpoint(this.workspaceLinkPath, {}).pipe(
map((workspaceitem: SubmissionObject) => workspaceitem[0]), map((workspaceitem: SubmissionObject[]) => workspaceitem[0] as SubmissionObject),
catchError(() => observableOf({}))) catchError(() => observableOf({} as SubmissionObject)))
} }
/** /**

View File

@@ -19,9 +19,7 @@ import { ClientCookieService } from '../../app/core/services/client-cookie.servi
import { CookieService } from '../../app/core/services/cookie.service'; import { CookieService } from '../../app/core/services/cookie.service';
import { AuthService } from '../../app/core/auth/auth.service'; import { AuthService } from '../../app/core/auth/auth.service';
import { Angulartics2Module } from 'angulartics2'; import { Angulartics2Module } from 'angulartics2';
import { Angulartics2GoogleAnalytics } from 'angulartics2/ga';
import { SubmissionService } from '../../app/submission/submission.service'; import { SubmissionService } from '../../app/submission/submission.service';
import { Angulartics2DSpace } from '../../app/statistics/angulartics/dspace-provider';
import { StatisticsModule } from '../../app/statistics/statistics.module'; import { StatisticsModule } from '../../app/statistics/statistics.module';
export const REQ_KEY = makeStateKey<string>('req'); export const REQ_KEY = makeStateKey<string>('req');
@@ -50,7 +48,7 @@ export function getRequest(transferState: TransferState): any {
IdlePreload IdlePreload
}), }),
StatisticsModule.forRoot(), StatisticsModule.forRoot(),
Angulartics2Module.forRoot([Angulartics2GoogleAnalytics, Angulartics2DSpace]), Angulartics2Module.forRoot(),
BrowserAnimationsModule, BrowserAnimationsModule,
DSpaceBrowserTransferStateModule, DSpaceBrowserTransferStateModule,
TranslateModule.forRoot({ TranslateModule.forRoot({

View File

@@ -47,7 +47,7 @@ export function createTranslateLoader() {
deps: [] deps: []
} }
}), }),
Angulartics2Module.forRoot([Angulartics2GoogleAnalytics, Angulartics2DSpace]), Angulartics2Module.forRoot(),
ServerModule, ServerModule,
AppModule AppModule
], ],

View File

@@ -126,12 +126,6 @@ module.exports = (env) => {
includePaths: [projectRoot('./'), path.join(themePath, 'styles')] includePaths: [projectRoot('./'), path.join(themePath, 'styles')]
} }
}, },
{
loader: 'resolve-url-loader',
options: {
sourceMap: true
}
},
{ {
loader: 'sass-resources-loader', loader: 'sass-resources-loader',
options: { options: {
@@ -163,13 +157,7 @@ module.exports = (env) => {
sourceMap: true, sourceMap: true,
includePaths: [projectRoot('./'), path.join(themePath, 'styles')] includePaths: [projectRoot('./'), path.join(themePath, 'styles')]
} }
}, }
{
loader: 'resolve-url-loader',
options: {
sourceMap: true
}
},
] ]
}, },
{ {

View File

@@ -1,7 +1,7 @@
const webpack = require('webpack'); const webpack = require('webpack');
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin; const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
const CompressionPlugin = require("compression-webpack-plugin"); const CompressionPlugin = require("compression-webpack-plugin");
const UglifyJsPlugin = require('uglifyjs-webpack-plugin'); const TerserPlugin = require('terser-webpack-plugin');
const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin"); const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin");
const cssnano = require("cssnano"); const cssnano = require("cssnano");
@@ -29,7 +29,7 @@ module.exports = {
new CompressionPlugin({ new CompressionPlugin({
asset: "[path].gz[query]", filename: "[path].gz[query]",
algorithm: "gzip", algorithm: "gzip",
test: /\.js$|\.css$|\.html$/, test: /\.js$|\.css$|\.html$/,
threshold: 10240, threshold: 10240,
@@ -39,15 +39,14 @@ module.exports = {
], ],
optimization: { optimization: {
minimizer: [ minimizer: [
new UglifyJsPlugin({ new TerserPlugin({
uglifyOptions: { terserOptions: {
beautify: false, beautify: false,
mangle: false, mangle: false,
output: { output: {
comments: false comments: false
}, },
compress: { compress: {
warnings: false,
conditionals: false, conditionals: false,
unused: true, unused: true,
comparisons: true, comparisons: true,
@@ -58,7 +57,8 @@ module.exports = {
join_vars: true, join_vars: true,
negate_iife: true negate_iife: true
}, },
sourceMap: true sourceMap: true,
warnings: false
} }
}), }),
new OptimizeCSSAssetsPlugin({ new OptimizeCSSAssetsPlugin({

View File

@@ -167,12 +167,6 @@ module.exports = function (env) {
includePaths: [projectRoot('./'), path.join(themePath, 'styles')] includePaths: [projectRoot('./'), path.join(themePath, 'styles')]
} }
}, },
{
loader: 'resolve-url-loader',
options: {
sourceMap: true
}
},
{ {
loader: 'sass-resources-loader', loader: 'sass-resources-loader',
options: { options: {
@@ -204,13 +198,7 @@ module.exports = function (env) {
sourceMap: true, sourceMap: true,
includePaths: [projectRoot('./'), path.join(themePath, 'styles')] includePaths: [projectRoot('./'), path.join(themePath, 'styles')]
} }
}, }
{
loader: 'resolve-url-loader',
options: {
sourceMap: true
}
},
] ]
}, },

4131
yarn.lock

File diff suppressed because it is too large Load Diff