diff --git a/package.json b/package.json index f69cb9d89c..f540576294 100644 --- a/package.json +++ b/package.json @@ -80,9 +80,9 @@ "@angularclass/bootloader": "1.0.1", "@angularclass/idle-preload": "1.0.4", "@ng-bootstrap/ng-bootstrap": "1.0.0-alpha.28", - "@ngrx/effects": "^4.0.1", - "@ngrx/router-store": "^4.0.0", - "@ngrx/store": "^4.0.0", + "@ngrx/effects": "^4.0.5", + "@ngrx/router-store": "^4.0.4", + "@ngrx/store": "^4.0.3", "@nguniversal/express-engine": "1.0.0-beta.2", "@ngx-translate/core": "7.1.0", "@ngx-translate/http-loader": "0.1.0", diff --git a/src/app/app.component.spec.ts b/src/app/app.component.spec.ts index 96037effc1..cc8e28535a 100644 --- a/src/app/app.component.spec.ts +++ b/src/app/app.component.spec.ts @@ -45,7 +45,7 @@ describe('App component', () => { return TestBed.configureTestingModule({ imports: [ CommonModule, - StoreModule.provideStore({}), + StoreModule.forRoot({}), TranslateModule.forRoot({ loader: { provide: TranslateLoader, diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 476d260a8f..45ac39c4db 100755 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -45,7 +45,7 @@ export function getConfig() { CommunityPageModule, AppRoutingModule, StoreModule.forRoot(appReducers, { metaReducers: appMetaReducers }), - // !getConfig().production ? StoreDevtoolsModule.instrument({ maxAge: 50 }) : [], + StoreDevtoolsModule.instrument({ maxAge: 50 }), EffectsModule.forRoot(appEffects) ], providers: [ diff --git a/src/app/browser-app.module.ts b/src/app/browser-app.module.ts index 7cccce5068..5a896d0e5e 100644 --- a/src/app/browser-app.module.ts +++ b/src/app/browser-app.module.ts @@ -25,7 +25,8 @@ import { CoreModule } from './core/core.module'; import { AppModule } from './app.module'; import { AppComponent } from './app.component'; -import { StoreRouterConnectingModule } from '@ngrx/router-store'; +import { RouterStateSerializer, StoreRouterConnectingModule } from '@ngrx/router-store'; +import { DSpaceRouterStateSerializer } from './shared/ngrx/dspace-router-state-serializer'; export function init(cache: TransferState) { return () => { @@ -70,6 +71,10 @@ export function HttpLoaderFactory(http: Http) { deps: [ TransferState ] + }, + { + provide: RouterStateSerializer, + useClass: DSpaceRouterStateSerializer } ] }) diff --git a/src/app/core/cache/builders/remote-data-build.service.ts b/src/app/core/cache/builders/remote-data-build.service.ts index eb0ea9bfeb..d01959d3dd 100644 --- a/src/app/core/cache/builders/remote-data-build.service.ts +++ b/src/app/core/cache/builders/remote-data-build.service.ts @@ -90,7 +90,7 @@ export class RemoteDataBuildService { ).filter((normalized) => hasValue(normalized)) .map((normalized: TNormalized) => { return this.build(normalized); - }); + }).distinctUntilChanged(); return new RemoteData( href, diff --git a/src/app/core/cache/object-cache.service.spec.ts b/src/app/core/cache/object-cache.service.spec.ts index 09d28605e2..54b49d3cf6 100644 --- a/src/app/core/cache/object-cache.service.spec.ts +++ b/src/app/core/cache/object-cache.service.spec.ts @@ -2,8 +2,9 @@ import { Store } from '@ngrx/store'; import { Observable } from 'rxjs/Observable'; import { ObjectCacheService } from './object-cache.service'; -import { ObjectCacheState, CacheableObject } from './object-cache.reducer'; +import { CacheableObject } from './object-cache.reducer'; import { AddToObjectCacheAction, RemoveFromObjectCacheAction } from './object-cache.actions'; +import { CoreState } from '../core.reducers'; class TestClass implements CacheableObject { constructor( @@ -18,7 +19,7 @@ class TestClass implements CacheableObject { describe('ObjectCacheService', () => { let service: ObjectCacheService; - let store: Store; + let store: Store; const uuid = '1698f1d3-be98-4c51-9fd8-6bfedcbd59b7'; const requestHref = 'https://rest.api/endpoint/1698f1d3-be98-4c51-9fd8-6bfedcbd59b7'; @@ -36,7 +37,7 @@ describe('ObjectCacheService', () => { const invalidCacheEntry = Object.assign({}, cacheEntry, { msToLive: -1 }); beforeEach(() => { - store = new Store(undefined, undefined, undefined); + store = new Store(undefined, undefined, undefined); spyOn(store, 'dispatch'); service = new ObjectCacheService(store); diff --git a/src/app/core/cache/object-cache.service.ts b/src/app/core/cache/object-cache.service.ts index 48a43a5f2f..0755b268cf 100644 --- a/src/app/core/cache/object-cache.service.ts +++ b/src/app/core/cache/object-cache.service.ts @@ -92,7 +92,7 @@ export class ObjectCacheService { } getRequestHrefBySelfLink(self: string): Observable { - return this.store.select('index/href', self) + return this.store.select(uuidFromHrefSelector(self)) .flatMap((uuid: string) => this.getRequestHref(uuid)); } diff --git a/src/app/core/cache/response-cache.service.ts b/src/app/core/cache/response-cache.service.ts index 66f6b40a04..ed1291e67a 100644 --- a/src/app/core/cache/response-cache.service.ts +++ b/src/app/core/cache/response-cache.service.ts @@ -11,7 +11,7 @@ import { CoreState } from '../core.reducers'; import { keySelector } from '../shared/selectors'; function entryFromKeySelector(key: string): MemoizedSelector { - return keySelector('data/reponse', key); + return keySelector('data/response', key); } /** diff --git a/src/app/core/data/request.service.ts b/src/app/core/data/request.service.ts index bd88a07ea0..f9f296a666 100644 --- a/src/app/core/data/request.service.ts +++ b/src/app/core/data/request.service.ts @@ -4,7 +4,7 @@ import { MemoizedSelector, Store } from '@ngrx/store'; import { Observable } from 'rxjs/Observable'; -import { RequestEntry, RequestState } from './request.reducer'; +import { RequestEntry } from './request.reducer'; import { Request } from './request.models'; import { hasValue } from '../../shared/empty.util'; import { RequestConfigureAction, RequestExecuteAction } from './request.actions'; diff --git a/src/app/core/footer/footer.component.spec.ts b/src/app/core/footer/footer.component.spec.ts index 13debf504b..693b5ec537 100644 --- a/src/app/core/footer/footer.component.spec.ts +++ b/src/app/core/footer/footer.component.spec.ts @@ -33,7 +33,7 @@ describe('Footer component', () => { // async beforeEach beforeEach(async(() => { return TestBed.configureTestingModule({ - imports: [CommonModule, StoreModule.provideStore({}), TranslateModule.forRoot({ + imports: [CommonModule, StoreModule.forRoot({}), TranslateModule.forRoot({ loader: { provide: TranslateLoader, useClass: MockTranslateLoader diff --git a/src/app/header/header.component.spec.ts b/src/app/header/header.component.spec.ts index cd77385363..4a66e1d9f1 100644 --- a/src/app/header/header.component.spec.ts +++ b/src/app/header/header.component.spec.ts @@ -21,7 +21,7 @@ describe('HeaderComponent', () => { // async beforeEach beforeEach(async(() => { TestBed.configureTestingModule({ - imports: [StoreModule.provideStore({}), TranslateModule.forRoot(), NgbCollapseModule.forRoot()], + imports: [StoreModule.forRoot({}), TranslateModule.forRoot(), NgbCollapseModule.forRoot()], declarations: [HeaderComponent] }) .compileComponents(); // compile template and css @@ -70,7 +70,7 @@ describe('HeaderComponent', () => { beforeEach(() => { menu = fixture.debugElement.query(By.css('#collapsingNav')).nativeElement; - spyOn(store, 'select').and.returnValue(Observable.of({ navCollapsed: false })); + spyOn(store, 'select').and.returnValue(Observable.of(false)); fixture.detectChanges(); }); diff --git a/src/app/server-app.module.ts b/src/app/server-app.module.ts index 904efa2dfd..cd5c24034d 100644 --- a/src/app/server-app.module.ts +++ b/src/app/server-app.module.ts @@ -37,7 +37,8 @@ import { AppModule } from './app.module'; import { AppComponent } from './app.component'; import { GLOBAL_CONFIG, GlobalConfig } from '../config'; -import { StoreRouterConnectingModule } from '@ngrx/router-store'; +import { RouterStateSerializer, StoreRouterConnectingModule } from '@ngrx/router-store'; +import { DSpaceRouterStateSerializer } from './shared/ngrx/dspace-router-state-serializer'; export function boot(cache: TransferState, appRef: ApplicationRef, store: Store, request: Request, config: GlobalConfig) { // authentication mechanism goes here @@ -88,6 +89,10 @@ export function UniversalLoaderFactory() { REQUEST, GLOBAL_CONFIG ] + }, + { + provide: RouterStateSerializer, + useClass: DSpaceRouterStateSerializer } ] }) diff --git a/src/app/shared/host-window.service.spec.ts b/src/app/shared/host-window.service.spec.ts index b48d094a1e..674d0e1332 100644 --- a/src/app/shared/host-window.service.spec.ts +++ b/src/app/shared/host-window.service.spec.ts @@ -1,17 +1,18 @@ import { Store } from '@ngrx/store'; import { Observable } from 'rxjs/Observable'; +import { AppState } from '../app.reducer'; +import { HostWindowState } from './host-window.reducer'; import { HostWindowService } from './host-window.service'; -import { HostWindowState } from './host-window.reducer'; describe('HostWindowService', () => { let service: HostWindowService; - let store: Store; + let store: Store; describe('', () => { beforeEach(() => { - const _initialState = { width: 1600, height: 770 }; - store = new Store(undefined, undefined, Observable.of(_initialState)); + const _initialState = { hostWindow: { width: 1600, height: 770 } }; + store = new Store(Observable.of(_initialState), undefined, undefined); service = new HostWindowService(store); }); @@ -46,8 +47,8 @@ describe('HostWindowService', () => { describe('', () => { beforeEach(() => { - const _initialState = { width: 1100, height: 770 }; - store = new Store(undefined, undefined, Observable.of(_initialState)); + const _initialState = { hostWindow: { width: 1100, height: 770 } }; + store = new Store(Observable.of(_initialState), undefined, undefined); service = new HostWindowService(store); }); @@ -82,8 +83,8 @@ describe('HostWindowService', () => { describe('', () => { beforeEach(() => { - const _initialState = { width: 800, height: 770 }; - store = new Store(undefined, undefined, Observable.of(_initialState)); + const _initialState = { hostWindow: { width: 800, height: 770 } }; + store = new Store(Observable.of(_initialState), undefined, undefined); service = new HostWindowService(store); }); @@ -118,8 +119,8 @@ describe('HostWindowService', () => { describe('', () => { beforeEach(() => { - const _initialState = { width: 600, height: 770 }; - store = new Store(undefined, undefined, Observable.of(_initialState)); + const _initialState = { hostWindow: { width: 600, height: 770 } }; + store = new Store(Observable.of(_initialState), undefined, undefined); service = new HostWindowService(store); }); @@ -154,8 +155,8 @@ describe('HostWindowService', () => { describe('', () => { beforeEach(() => { - const _initialState = { width: 400, height: 770 }; - store = new Store(undefined, undefined, Observable.of(_initialState)); + const _initialState = { hostWindow: { width: 400, height: 770 } }; + store = new Store(Observable.of(_initialState), undefined, undefined); service = new HostWindowService(store); }); diff --git a/src/app/shared/ngrx/dspace-router-state-serializer.ts b/src/app/shared/ngrx/dspace-router-state-serializer.ts new file mode 100644 index 0000000000..2ddd37ca43 --- /dev/null +++ b/src/app/shared/ngrx/dspace-router-state-serializer.ts @@ -0,0 +1,18 @@ +import { RouterStateSerializer } from '@ngrx/router-store'; +import { Params, RouterStateSnapshot } from '@angular/router'; + +export interface RouterStateUrl { + url: string; + queryParams: Params; +} + +export class DSpaceRouterStateSerializer implements RouterStateSerializer { + serialize(routerState: RouterStateSnapshot): RouterStateUrl { + const { url } = routerState; + const queryParams = routerState.root.queryParams; + + // Only return an object including the URL and query params + // instead of the entire snapshot + return { url, queryParams }; + } +} diff --git a/src/app/shared/pagination/pagination.component.spec.ts b/src/app/shared/pagination/pagination.component.spec.ts index 7892456498..c2e6a8956d 100644 --- a/src/app/shared/pagination/pagination.component.spec.ts +++ b/src/app/shared/pagination/pagination.component.spec.ts @@ -140,7 +140,7 @@ describe('Pagination component', () => { TestBed.configureTestingModule({ imports: [ CommonModule, - StoreModule.provideStore({}), + StoreModule.forRoot({}), TranslateModule.forRoot({ loader: { provide: TranslateLoader, diff --git a/yarn.lock b/yarn.lock index 0df381cd24..654e5afe3b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -90,21 +90,21 @@ version "1.0.0-alpha.28" resolved "https://registry.yarnpkg.com/@ng-bootstrap/ng-bootstrap/-/ng-bootstrap-1.0.0-alpha.28.tgz#30a6503bf7f94f9d3187591fb3267b59cc0cdaad" -"@ngrx/effects@^4.0.1": - version "4.0.1" - resolved "https://registry.yarnpkg.com/@ngrx/effects/-/effects-4.0.1.tgz#9403d5668c70217eb5c84ba7a5ffebbbcf507b34" +"@ngrx/effects@^4.0.5": + version "4.0.5" + resolved "https://registry.yarnpkg.com/@ngrx/effects/-/effects-4.0.5.tgz#1224763800621b7305f9b18bc17ee09b25c861d1" -"@ngrx/router-store@^4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@ngrx/router-store/-/router-store-4.0.0.tgz#22b50297395669834df09c46b5a15a8eb56b871d" +"@ngrx/router-store@^4.0.4": + version "4.0.4" + resolved "https://registry.yarnpkg.com/@ngrx/router-store/-/router-store-4.0.4.tgz#ab59f35aae93465088384faf009e21b22edd456a" "@ngrx/store-devtools@^4.0.0": version "4.0.0" resolved "https://registry.yarnpkg.com/@ngrx/store-devtools/-/store-devtools-4.0.0.tgz#b79c24773217df7fd9735ad21f9cbf2533c96e04" -"@ngrx/store@^4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@ngrx/store/-/store-4.0.0.tgz#714d82056f0eb31518ca85a68a5cfecfc12cc50b" +"@ngrx/store@^4.0.3": + version "4.0.3" + resolved "https://registry.yarnpkg.com/@ngrx/store/-/store-4.0.3.tgz#36abacdfa19bfb8506e40de80bae06050a1e15e9" "@ngtools/webpack@1.5.1": version "1.5.1"