diff --git a/src/app/+item-page/field-components/metadata-field-wrapper/metadata-field-wrapper.component.html b/src/app/+item-page/field-components/metadata-field-wrapper/metadata-field-wrapper.component.html index 084232edf4..bbe6d8d95b 100644 --- a/src/app/+item-page/field-components/metadata-field-wrapper/metadata-field-wrapper.component.html +++ b/src/app/+item-page/field-components/metadata-field-wrapper/metadata-field-wrapper.component.html @@ -1,7 +1,5 @@ -
- -
{{ label }}
-
+
+
{{ label }}
diff --git a/src/app/+item-page/field-components/metadata-field-wrapper/metadata-field-wrapper.component.spec.ts b/src/app/+item-page/field-components/metadata-field-wrapper/metadata-field-wrapper.component.spec.ts index 47e7d6c34e..cce54edf64 100644 --- a/src/app/+item-page/field-components/metadata-field-wrapper/metadata-field-wrapper.component.spec.ts +++ b/src/app/+item-page/field-components/metadata-field-wrapper/metadata-field-wrapper.component.spec.ts @@ -7,7 +7,8 @@ import { MetadataFieldWrapperComponent } from './metadata-field-wrapper.componen @Component({ selector: 'ds-component-with-content', template: '\n' + - '
\n' + + '
\n' + + ' \n' + '
\n' + '' }) @@ -30,25 +31,37 @@ describe('MetadataFieldWrapperComponent', () => { const wrapperSelector = '.simple-view-element'; const labelSelector = '.simple-view-element-header'; + const contentSelector = '.my-content'; it('should create', () => { expect(component).toBeDefined(); }); - it('should not show a label when there is no content', () => { + it('should not show the component when there is no content', () => { component.label = 'test label'; fixture.detectChanges(); - const debugLabel = fixture.debugElement.query(By.css(labelSelector)); - expect(debugLabel).toBeNull(); + const parentNative = fixture.nativeElement; + const nativeWrapper = parentNative.querySelector(wrapperSelector); + expect(nativeWrapper.classList.contains('d-none')).toBe(true); }); - it('should show a label when there is content', () => { + it('should not show the component when there is DOM content but no text', () => { const parentFixture = TestBed.createComponent(ContentComponent); parentFixture.detectChanges(); - const parentComponent = parentFixture.componentInstance; const parentNative = parentFixture.nativeElement; - const nativeLabel = parentNative.querySelector(labelSelector); - expect(nativeLabel.textContent).toContain('test label'); + const nativeWrapper = parentNative.querySelector(wrapperSelector); + expect(nativeWrapper.classList.contains('d-none')).toBe(true); + }); + + it('should show the component when there is text content', () => { + const parentFixture = TestBed.createComponent(ContentComponent); + parentFixture.detectChanges(); + const parentNative = parentFixture.nativeElement; + const nativeContent = parentNative.querySelector(contentSelector); + nativeContent.textContent = 'lorem ipsum'; + const nativeWrapper = parentNative.querySelector(wrapperSelector); + parentFixture.detectChanges(); + expect(nativeWrapper.classList.contains('d-none')).toBe(false); }); }); diff --git a/src/app/core/auth/auth.service.spec.ts b/src/app/core/auth/auth.service.spec.ts index 187db93f3c..d39c0a4590 100644 --- a/src/app/core/auth/auth.service.spec.ts +++ b/src/app/core/auth/auth.service.spec.ts @@ -148,7 +148,7 @@ describe('AuthService test', () => { (state as any).core = Object.create({}); (state as any).core.auth = authenticatedState; }); - authService = new AuthService({}, window, authReqService, router, cookieService, store, rdbService); + authService = new AuthService({}, window, undefined, authReqService, router, cookieService, store, rdbService); })); it('should return true when user is logged in', () => { @@ -207,7 +207,7 @@ describe('AuthService test', () => { (state as any).core = Object.create({}); (state as any).core.auth = authenticatedState; }); - authService = new AuthService({}, window, authReqService, router, cookieService, store, rdbService); + authService = new AuthService({}, window, undefined, authReqService, router, cookieService, store, rdbService); storage = (authService as any).storage; spyOn(storage, 'get'); spyOn(storage, 'remove'); diff --git a/src/app/core/auth/auth.service.ts b/src/app/core/auth/auth.service.ts index 5d8d13131a..67f533d4ad 100644 --- a/src/app/core/auth/auth.service.ts +++ b/src/app/core/auth/auth.service.ts @@ -9,10 +9,10 @@ import { take, withLatestFrom } from 'rxjs/operators'; -import { Inject, Injectable } from '@angular/core'; +import { Inject, Injectable, Optional } from '@angular/core'; import { PRIMARY_OUTLET, Router, UrlSegmentGroup, UrlTree } from '@angular/router'; import { HttpHeaders } from '@angular/common/http'; -import { REQUEST } from '@nguniversal/express-engine/tokens'; +import { REQUEST, RESPONSE } from '@nguniversal/express-engine/tokens'; import { RouterReducerState } from '@ngrx/router-store'; import { select, Store } from '@ngrx/store'; @@ -59,6 +59,7 @@ export class AuthService { constructor(@Inject(REQUEST) protected req: any, @Inject(NativeWindowService) protected _window: NativeWindowRef, protected authRequestService: AuthRequestService, + @Optional() @Inject(RESPONSE) private response: any, protected router: Router, protected storage: CookieService, protected store: Store, @@ -345,6 +346,10 @@ export class AuthService { if (this._window.nativeWindow.location) { // Hard redirect to login page, so that all state is definitely lost this._window.nativeWindow.location.href = redirectUrl; + } else if (this.response) { + if (!this.response._headerSent) { + this.response.redirect(302, redirectUrl); + } } else { this.router.navigateByUrl(redirectUrl); } diff --git a/src/app/core/cache/response-cache.models.ts b/src/app/core/cache/response-cache.models.ts index 9566dcdc3c..9b1b5b89eb 100644 --- a/src/app/core/cache/response-cache.models.ts +++ b/src/app/core/cache/response-cache.models.ts @@ -140,7 +140,7 @@ export class ErrorResponse extends RestResponse { constructor(error: RequestError) { super(false, error.statusText); - // console.error(error); + console.error(error); this.errorMessage = error.message; } } diff --git a/src/app/core/data/comcol-data.service.ts b/src/app/core/data/comcol-data.service.ts index c589c5bdc8..95cfce6c70 100644 --- a/src/app/core/data/comcol-data.service.ts +++ b/src/app/core/data/comcol-data.service.ts @@ -37,25 +37,8 @@ export abstract class ComColDataService { const request = new FindByIDRequest(this.requestService.generateRequestId(), href, options.scopeID); this.requestService.configure(request); - }),); + })); - // return scopeCommunityHrefObs.pipe( - // mergeMap((href: string) => this.responseCache.get(href)), - // map((entry: ResponseCacheEntry) => entry.response), - // mergeMap((response) => { - // if (response.isSuccessful) { - // const community$: Observable = this.objectCache.getByUUID(scopeID); - // return community$.pipe( - // map((community) => community._links[this.linkPath]), - // filter((href) => isNotEmpty(href)), - // distinctUntilChanged() - // ); - // } else if (!response.isSuccessful) { - // return observableThrowError(new Error(`The Community with scope ${scopeID} couldn't be retrieved`)) - // } - // }), - // distinctUntilChanged() - // ); const responses = scopeCommunityHrefObs.pipe( mergeMap((href: string) => this.responseCache.get(href)), map((entry: ResponseCacheEntry) => entry.response)); diff --git a/src/server.ts b/src/server.ts index 0e68e4f139..0526f196ba 100644 --- a/src/server.ts +++ b/src/server.ts @@ -17,6 +17,7 @@ import { ngExpressEngine } from '@nguniversal/express-engine'; import { ROUTES } from './routes'; import { ENV_CONFIG } from './config'; +import { REQUEST, RESPONSE } from '@nguniversal/express-engine/tokens'; export function startServer(bootstrap: Type<{}> | NgModuleFactory<{}>) { const app = express(); @@ -31,9 +32,21 @@ export function startServer(bootstrap: Type<{}> | NgModuleFactory<{}>) { app.use(cookieParser()); app.use(bodyParser.json()); - app.engine('html', ngExpressEngine({ - bootstrap: bootstrap - })); + app.engine('html', (_, options, callback) => + ngExpressEngine({ + bootstrap: bootstrap, + providers: [ + { + provide: REQUEST, + useValue: options.req, + }, + { + provide: RESPONSE, + useValue: options.req.res, + }, + ], + })(_, options, callback) + ); app.set('view engine', 'html'); app.set('views', 'src'); @@ -53,8 +66,10 @@ export function startServer(bootstrap: Type<{}> | NgModuleFactory<{}>) { function ngApp(req, res) { function onHandleError(parentZoneDelegate, currentZone, targetZone, error) { - console.warn('Error in SSR, serving for direct CSR'); - res.sendFile('index.csr.html', { root: './src' }); + if (!res._headerSent) { + console.warn('Error in SSR, serving for direct CSR'); + res.sendFile('index.csr.html', { root: './src' }); + } } if (ENV_CONFIG.universal.preboot) { diff --git a/webpack.config.js b/webpack.config.js index eda62445eb..6312cf3605 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -27,7 +27,6 @@ module.exports = function(env, options) { getAotPlugin('client', !!env.aot) ] }); - if (options.mode === 'production') { serverConfig = webpackMerge({}, serverConfig, prodPartial); clientConfig = webpackMerge({}, clientConfig, prodPartial);