diff --git a/server.ts b/server.ts
index 8ff45ac2cd..8ba8272976 100644
--- a/server.ts
+++ b/server.ts
@@ -170,6 +170,7 @@ export function app() {
UserAgent: '*',
Disallow: [
'/error',
+ '/maintenance',
'/account',
'/compare',
'/recently',
diff --git a/src/app/core/guards/error-status.guard.ts b/src/app/core/guards/error-status.guard.ts
new file mode 100644
index 0000000000..ccbecfef33
--- /dev/null
+++ b/src/app/core/guards/error-status.guard.ts
@@ -0,0 +1,13 @@
+import { Injectable } from '@angular/core';
+import { CanActivate, Router } from '@angular/router';
+import { map } from 'rxjs';
+
+import { AppFacade } from 'ish-core/facades/app.facade';
+
+@Injectable({ providedIn: 'root' })
+export class ErrorStatusGuard implements CanActivate {
+ constructor(private appFacade: AppFacade, private router: Router) {}
+ canActivate() {
+ return this.appFacade.generalError$.pipe(map(error => (!error ? this.router.parseUrl('/home') : true)));
+ }
+}
diff --git a/src/app/core/utils/http-status-code/http-status-code.service.spec.ts b/src/app/core/utils/http-status-code/http-status-code.service.spec.ts
index aec50657f9..9d9cfec811 100644
--- a/src/app/core/utils/http-status-code/http-status-code.service.spec.ts
+++ b/src/app/core/utils/http-status-code/http-status-code.service.spec.ts
@@ -25,7 +25,12 @@ describe('Http Status Code Service', () => {
describe('on browser', () => {
beforeEach(() => {
TestBed.configureTestingModule({
- imports: [RouterTestingModule.withRoutes([{ path: 'error', children: [] }])],
+ imports: [
+ RouterTestingModule.withRoutes([
+ { path: 'error', children: [] },
+ { path: 'maintenance', children: [] },
+ ]),
+ ],
});
httpStatusCodeService = TestBed.inject(HttpStatusCodeService);
location = TestBed.inject(Location);
@@ -56,13 +61,25 @@ describe('Http Status Code Service', () => {
verify(resSpy.status(anyNumber())).never();
expect(location.path()).toEqual('/error');
}));
+
+ it('should redirect to maintenance page for server 503 errors (Unavailable)', fakeAsync(() => {
+ httpStatusCodeService.setStatus(503);
+ tick(500);
+ verify(resSpy.status(anyNumber())).never();
+ expect(location.path()).toEqual('/maintenance');
+ }));
});
});
describe.onSSREnvironment('on server', () => {
beforeEach(() => {
TestBed.configureTestingModule({
- imports: [RouterTestingModule.withRoutes([{ path: 'error', children: [] }])],
+ imports: [
+ RouterTestingModule.withRoutes([
+ { path: 'error', children: [] },
+ { path: 'maintenance', children: [] },
+ ]),
+ ],
providers: [{ provide: RESPONSE, useValue: RES }],
});
httpStatusCodeService = TestBed.inject(HttpStatusCodeService);
@@ -94,6 +111,13 @@ describe('Http Status Code Service', () => {
verify(resSpy.status(500)).once();
expect(location.path()).toEqual('/error');
}));
+
+ it('should redirect to maintenance page for server 503 errors (Unavailable)', fakeAsync(() => {
+ httpStatusCodeService.setStatus(503);
+ tick(500);
+ verify(resSpy.status(503)).once();
+ expect(location.path()).toEqual('/maintenance');
+ }));
});
});
});
diff --git a/src/app/core/utils/http-status-code/http-status-code.service.ts b/src/app/core/utils/http-status-code/http-status-code.service.ts
index 309046d07a..c2d884fe6b 100644
--- a/src/app/core/utils/http-status-code/http-status-code.service.ts
+++ b/src/app/core/utils/http-status-code/http-status-code.service.ts
@@ -19,10 +19,13 @@ export class HttpStatusCodeService {
this.response.status(status);
}
if (redirect && status >= 400) {
+ // 503: server is unavailable
+ const route = status === 503 ? '/maintenance' : '/error';
+
if (SSR) {
- return this.router.navigateByUrl('/error');
+ return this.router.navigateByUrl(route);
} else {
- return this.router.navigateByUrl('/error', { skipLocationChange: status < 500 });
+ return this.router.navigateByUrl(route, { skipLocationChange: status < 500 });
}
}
return Promise.resolve(true);
diff --git a/src/app/pages/app-routing.module.ts b/src/app/pages/app-routing.module.ts
index 9dab7036ea..d13e6a687c 100644
--- a/src/app/pages/app-routing.module.ts
+++ b/src/app/pages/app-routing.module.ts
@@ -2,6 +2,7 @@ import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { AuthGuard } from 'ish-core/guards/auth.guard';
+import { ErrorStatusGuard } from 'ish-core/guards/error-status.guard';
import { IdentityProviderInviteGuard } from 'ish-core/guards/identity-provider-invite.guard';
import { IdentityProviderLoginGuard } from 'ish-core/guards/identity-provider-login.guard';
import { IdentityProviderLogoutGuard } from 'ish-core/guards/identity-provider-logout.guard';
@@ -30,6 +31,17 @@ const routes: Routes = [
},
},
},
+ {
+ path: 'maintenance',
+ loadChildren: () => import('./maintenance/maintenance-page.module').then(m => m.MaintenancePageModule),
+ canActivate: [ErrorStatusGuard],
+ data: {
+ meta: {
+ title: 'seo.title.maintenance',
+ robots: 'noindex, nofollow',
+ },
+ },
+ },
{
path: 'account',
loadChildren: () => import('./account/account-page.module').then(m => m.AccountPageModule),
diff --git a/src/app/pages/maintenance/maintenance-page.component.html b/src/app/pages/maintenance/maintenance-page.component.html
new file mode 100644
index 0000000000..5c2c05e753
--- /dev/null
+++ b/src/app/pages/maintenance/maintenance-page.component.html
@@ -0,0 +1,21 @@
+
+
{{ 'server.maintenance.page.title' | translate }}
+
+
+
{{ 'server.maintenance.page.contact.label' | translate }}
+
+
+
+
diff --git a/src/app/pages/maintenance/maintenance-page.component.spec.ts b/src/app/pages/maintenance/maintenance-page.component.spec.ts
new file mode 100644
index 0000000000..05e462b175
--- /dev/null
+++ b/src/app/pages/maintenance/maintenance-page.component.spec.ts
@@ -0,0 +1,33 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { FaIconComponent } from '@fortawesome/angular-fontawesome';
+import { TranslateModule } from '@ngx-translate/core';
+import { MockComponent, MockDirective } from 'ng-mocks';
+
+import { ServerHtmlDirective } from 'ish-core/directives/server-html.directive';
+
+import { MaintenancePageComponent } from './maintenance-page.component';
+
+describe('Maintenance Page Component', () => {
+ let component: MaintenancePageComponent;
+ let fixture: ComponentFixture;
+ let element: HTMLElement;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ imports: [TranslateModule.forRoot()],
+ declarations: [MaintenancePageComponent, MockComponent(FaIconComponent), MockDirective(ServerHtmlDirective)],
+ }).compileComponents();
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(MaintenancePageComponent);
+ component = fixture.componentInstance;
+ element = fixture.nativeElement;
+ });
+
+ it('should be created', () => {
+ expect(component).toBeTruthy();
+ expect(element).toBeTruthy();
+ expect(() => fixture.detectChanges()).not.toThrow();
+ });
+});
diff --git a/src/app/pages/maintenance/maintenance-page.component.ts b/src/app/pages/maintenance/maintenance-page.component.ts
new file mode 100644
index 0000000000..86c89b1de2
--- /dev/null
+++ b/src/app/pages/maintenance/maintenance-page.component.ts
@@ -0,0 +1,8 @@
+import { ChangeDetectionStrategy, Component } from '@angular/core';
+
+@Component({
+ selector: 'ish-maintenance-page',
+ templateUrl: './maintenance-page.component.html',
+ changeDetection: ChangeDetectionStrategy.OnPush,
+})
+export class MaintenancePageComponent {}
diff --git a/src/app/pages/maintenance/maintenance-page.module.ts b/src/app/pages/maintenance/maintenance-page.module.ts
new file mode 100644
index 0000000000..ff5fef7f41
--- /dev/null
+++ b/src/app/pages/maintenance/maintenance-page.module.ts
@@ -0,0 +1,16 @@
+import { NgModule } from '@angular/core';
+import { RouterModule, Routes } from '@angular/router';
+
+import { SharedModule } from 'ish-shared/shared.module';
+
+import { MaintenancePageComponent } from './maintenance-page.component';
+
+const maintenancePageRoutes: Routes = [
+ { path: '', component: MaintenancePageComponent, data: { wrapperClass: 'errorpage', headerType: 'error' } },
+];
+
+@NgModule({
+ imports: [RouterModule.forChild(maintenancePageRoutes), SharedModule],
+ declarations: [MaintenancePageComponent],
+})
+export class MaintenancePageModule {}
diff --git a/src/assets/i18n/de_DE.json b/src/assets/i18n/de_DE.json
index cbdae6338d..98ee895788 100644
--- a/src/assets/i18n/de_DE.json
+++ b/src/assets/i18n/de_DE.json
@@ -1043,7 +1043,13 @@
"seo.title.checkout": "Kasse",
"seo.title.error": "Fehler",
"seo.title.home": "inTRONICS Startseite",
+ "seo.title.maintenance": "Wartung",
"seo.title.search": "Suchergebnis für '{{0}}'",
+ "server.maintenance.page.contact.email": "info@test.intershop.de",
+ "server.maintenance.page.contact.label": "Sie können uns kontaktieren:",
+ "server.maintenance.page.contact.phone": "1-800-xxx-xxxx",
+ "server.maintenance.page.text": "Es tut uns leid ...
Unsere Webseite ist auf Grund von Wartungsarbeiten kurzzeitig nicht verfügbar. Bitte kommen Sie später wieder.
",
+ "server.maintenance.page.title": "Wir sind bald zurück",
"servererror.mailServer.error": "Ihre E-Mail konnte leider nicht versandt werden. Wir bitten um Entschuldigung. Bitte versuchen Sie es später erneut.",
"servererror.page.text": "Es tut uns leid ...
Gehen Sie zurück zur Startseite und versuchen Sie es erneut.
",
"servererror.page.title": "Etwas ist schiefgegangen.",
diff --git a/src/assets/i18n/en_US.json b/src/assets/i18n/en_US.json
index 9340615ba9..4430eddc4f 100644
--- a/src/assets/i18n/en_US.json
+++ b/src/assets/i18n/en_US.json
@@ -1043,7 +1043,13 @@
"seo.title.checkout": "Checkout",
"seo.title.error": "Error",
"seo.title.home": "inTRONICS Home",
+ "seo.title.maintenance": "Maintenance",
"seo.title.search": "Search Result for '{{0}}'",
+ "server.maintenance.page.contact.email": "info@test.intershop.de",
+ "server.maintenance.page.contact.label": "You can contact us:",
+ "server.maintenance.page.contact.phone": "1-800-xxx-xxxx",
+ "server.maintenance.page.text": "We are sorry ...
Our website is briefly unavailable for a scheduled maintenance. Please come back again later.
",
+ "server.maintenance.page.title": "We will be back soon",
"servererror.mailServer.error": "Your mail couldn't be sent. We apologize for the inconvenience. Please try again later.",
"servererror.page.text": "We are sorry ...
Please go back to the Home Page and try again.
",
"servererror.page.title": "Something Went Wrong",
diff --git a/src/assets/i18n/fr_FR.json b/src/assets/i18n/fr_FR.json
index efa2efa091..7d6032a238 100644
--- a/src/assets/i18n/fr_FR.json
+++ b/src/assets/i18n/fr_FR.json
@@ -1043,7 +1043,13 @@
"seo.title.checkout": "Passer la commande",
"seo.title.error": "Erreur",
"seo.title.home": "Page d’accueil InTRONICS",
+ "seo.title.maintenance": "Maintenance",
"seo.title.search": "Résultat de recherche pour '{{0}}'.",
+ "server.maintenance.page.contact.email": "info@test.intershop.de",
+ "server.maintenance.page.contact.label": "Vous pouvez nou contacter:",
+ "server.maintenance.page.contact.phone": "1-800-xxx-xxxx",
+ "server.maintenance.page.text": "Nous sommes désolés ...
",
+ "server.maintenance.page.title": "Arrêt de maintenance",
"servererror.mailServer.error": "Votre courriel n’a pas pu être envoyé. Nous nous excusons pour les inconvénients. Veuillez réessayer plus tard.",
"servererror.page.text": "Nous sommes désolés ...
Retournez à la Page d’accueil, puis réessayez.
",
"servererror.page.title": "Quelque chose s’est mal passé",