diff --git a/src/app/static-page/static-page.component.html b/src/app/static-page/static-page.component.html index 99b85f71fb9..8f33ff3f714 100644 --- a/src/app/static-page/static-page.component.html +++ b/src/app/static-page/static-page.component.html @@ -1,3 +1,21 @@ -
+ +
+ +
+ + +
+ + +
+

404

+

{{"404.page-not-found" | translate}}

+
+

{{"404.help" | translate}}

+
+

+ {{"404.link.home-page" | translate}} +

+
diff --git a/src/app/static-page/static-page.component.spec.ts b/src/app/static-page/static-page.component.spec.ts index 153675f146c..0d3df7afec0 100644 --- a/src/app/static-page/static-page.component.spec.ts +++ b/src/app/static-page/static-page.component.spec.ts @@ -1,4 +1,6 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { CommonModule } from '@angular/common'; +import { NO_ERRORS_SCHEMA } from '@angular/core'; import { StaticPageComponent } from './static-page.component'; import { HtmlContentService } from '../shared/html-content.service'; @@ -10,13 +12,15 @@ import { of } from 'rxjs'; import { APP_CONFIG } from '../../config/app-config.interface'; import { environment } from '../../environments/environment'; import { ClarinSafeHtmlPipe } from '../shared/utils/clarin-safehtml.pipe'; +import { ServerResponseService } from '../core/services/server-response.service'; describe('StaticPageComponent', () => { let component: StaticPageComponent; let fixture: ComponentFixture; - let htmlContentService: HtmlContentService; + let htmlContentService: jasmine.SpyObj; let localeService: any; + let responseService: jasmine.SpyObj; let appConfig: any; beforeEach(async () => { @@ -26,6 +30,7 @@ describe('StaticPageComponent', () => { localeService = jasmine.createSpyObj('LocaleService', { getCurrentLanguageCode: jasmine.createSpy('getCurrentLanguageCode'), }); + responseService = jasmine.createSpyObj('responseService', ['setNotFound']); // Do not mutate the shared `environment` object - replacing `environment.ui` would // break any later spec that reads e.g. environment.ui.nameSpace @@ -38,14 +43,17 @@ describe('StaticPageComponent', () => { TestBed.configureTestingModule({ declarations: [ StaticPageComponent, ClarinSafeHtmlPipe ], imports: [ + CommonModule, TranslateModule.forRoot() ], providers: [ { provide: HtmlContentService, useValue: htmlContentService }, { provide: Router, useValue: new RouterMock() }, { provide: LocaleService, useValue: localeService }, + { provide: ServerResponseService, useValue: responseService }, { provide: APP_CONFIG, useValue: appConfig } - ] + ], + schemas: [NO_ERRORS_SCHEMA] }); localeService = TestBed.inject(LocaleService); @@ -65,5 +73,14 @@ describe('StaticPageComponent', () => { it('should load html file content', async () => { await component.ngOnInit(); expect(component.htmlContent.value).toBe('
TEST MESSAGE
'); + expect(component.contentState).toBe('found'); + }); + + // When the file is missing, set a 404 status for SSR and switch to the not-found state + it('should set 404 status when content is not found', async () => { + htmlContentService.fetchHtmlContent.and.returnValue(of('')); + await component.ngOnInit(); + expect(responseService.setNotFound).toHaveBeenCalled(); + expect(component.contentState).toBe('not-found'); }); }); diff --git a/src/app/static-page/static-page.component.ts b/src/app/static-page/static-page.component.ts index c44d5fb6ebd..8710fdb3110 100644 --- a/src/app/static-page/static-page.component.ts +++ b/src/app/static-page/static-page.component.ts @@ -1,4 +1,4 @@ -import { Component, Inject, OnInit } from '@angular/core'; +import { ChangeDetectorRef, Component, Inject, OnInit } from '@angular/core'; import { HtmlContentService } from '../shared/html-content.service'; import { BehaviorSubject, firstValueFrom } from 'rxjs'; import { Router } from '@angular/router'; @@ -6,10 +6,10 @@ import { isEmpty, isNotEmpty } from '../shared/empty.util'; import { LocaleService } from '../core/locale/locale.service'; import { HTML_SUFFIX, - STATIC_FILES_DEFAULT_ERROR_PAGE_PATH, STATIC_FILES_PROJECT_PATH, STATIC_PAGE_PATH } from './static-page-routing-paths'; import { APP_CONFIG, AppConfig } from '../../config/app-config.interface'; +import { ServerResponseService } from '../core/services/server-response.service'; /** * Component which load and show static files from the `static-files` folder. @@ -23,10 +23,13 @@ import { APP_CONFIG, AppConfig } from '../../config/app-config.interface'; export class StaticPageComponent implements OnInit { htmlContent: BehaviorSubject = new BehaviorSubject(''); htmlFileName: string; + contentState: 'loading' | 'found' | 'not-found' = 'loading'; constructor(private htmlContentService: HtmlContentService, private router: Router, private localeService: LocaleService, + private responseService: ServerResponseService, + private changeDetector: ChangeDetectorRef, @Inject(APP_CONFIG) protected appConfig?: AppConfig) { } async ngOnInit(): Promise { @@ -48,6 +51,8 @@ export class StaticPageComponent implements OnInit { let potentialContent = await firstValueFrom(this.htmlContentService.fetchHtmlContent(url)); if (isNotEmpty(potentialContent)) { this.htmlContent.next(potentialContent); + this.contentState = 'found'; + this.changeDetector.detectChanges(); return; } @@ -56,11 +61,15 @@ export class StaticPageComponent implements OnInit { potentialContent = await firstValueFrom(this.htmlContentService.fetchHtmlContent(url)); if (isNotEmpty(potentialContent)) { this.htmlContent.next(potentialContent); + this.contentState = 'found'; + this.changeDetector.detectChanges(); return; } - // Show error page - await this.loadErrorPage(); + // Content not found - set 404 status for SSR and show the inline 404 page + this.responseService.setNotFound(); + this.contentState = 'not-found'; + this.changeDetector.detectChanges(); } /** @@ -139,24 +148,10 @@ export class StaticPageComponent implements OnInit { urlInList = urlInList.filter(n => n); // if length is 1 - html file name wasn't defined. if (isEmpty(urlInList) || urlInList.length === 1) { - void this.loadErrorPage(); return null; } // If the url is too long take just the first string after `/static` prefix. return urlInList[1]?.split('#')?.[0]; } - - /** - * Load `static-files/error.html` - * @private - */ - private async loadErrorPage() { - let errorPage = await firstValueFrom(this.htmlContentService.fetchHtmlContent(STATIC_FILES_DEFAULT_ERROR_PAGE_PATH)); - if (isEmpty(errorPage)) { - console.error('Cannot load error page from the path: ' + STATIC_FILES_DEFAULT_ERROR_PAGE_PATH); - return; - } - this.htmlContent.next(errorPage); - } }