KON-708 Schalter einbauen bei DSGVO-Suche integrieren
KON-704 admin <-> reader Role
diff --git a/i18n/contacts.de.json b/i18n/contacts.de.json
index 9f0388d..e58575a 100644
--- a/i18n/contacts.de.json
+++ b/i18n/contacts.de.json
@@ -28,6 +28,8 @@
     "DeleteLockExpired": "Löschsperre abgelaufen",
     "ExpieringDateExceed": "Ablaufdatum überschritten",
     "NewContactPersonData": "Neuen Kontaktperson hinzufügen",
-    "EditContactPersonData": "Kontaktperson bearbeiten"
+    "EditContactPersonData": "Kontaktperson bearbeiten",
+    "HasSyncError": "Synchronisation Fehler",
+    "HasSyncErrorTooltip": "Filterung nach Kontakten mit Fehlern bei der Synchronisation mit dem LDAP"
   }
 }
diff --git a/src/app/app.module.ts b/src/app/app.module.ts
index e7f4ea9..cbf7907 100644
--- a/src/app/app.module.ts
+++ b/src/app/app.module.ts
@@ -51,6 +51,7 @@
 import { environment } from 'environments/environment';
 import { ContainersModule } from '@shared/containers';
 import { NgbModalModule } from '@ng-bootstrap/ng-bootstrap';
+import { VersionModule } from './shared/components/version-info/version.module';
 
 /**
  * Get the BaseHref which is defined in the index.html ( <base href="/"> ).
@@ -110,6 +111,7 @@
     AppRoutingModule,
     NgbModalModule,
     LogoutModule,
+    VersionModule
   ],
   providers: [
     AdminGuard,
diff --git a/src/app/pages/contacts/contacts-api-client.ts b/src/app/pages/contacts/contacts-api-client.ts
index 04e95b7..3ba75fe 100644
--- a/src/app/pages/contacts/contacts-api-client.ts
+++ b/src/app/pages/contacts/contacts-api-client.ts
@@ -36,6 +36,7 @@
         modifiedContacts.moduleName,
         modifiedContacts.withoutAssignedModule,
         modifiedContacts.expiringDataInPast,
+        modifiedContacts.withSyncError,
         modifiedContacts.deletionLockExceeded,
         request.pageNumber ? request.pageNumber - 1 : 0,
         request.pageSize
@@ -48,6 +49,7 @@
         modifiedContacts.moduleName,
         modifiedContacts.withoutAssignedModule,
         modifiedContacts.expiringDataInPast,
+        modifiedContacts.withSyncError,
         modifiedContacts.deletionLockExceeded,
         1,
         3
@@ -67,6 +69,7 @@
     @Query('moduleName') moduleName: string,
     @Query('withoutAssignedModule') withoutAssignedModule: boolean,
     @Query('expiringDataInPast') expiringDataInPast: boolean,
+    @Query('withSyncError') withSyncError: boolean,
     @Query('deletionLockExceeded') deletionLockExceeded: boolean,
     @Query('page') pageNumber: number,
     @Query('size') pageSize: number
diff --git a/src/app/pages/contacts/contacts-list/contacts-list.component.html b/src/app/pages/contacts/contacts-list/contacts-list.component.html
index 37eaa60..53ea1d4 100644
--- a/src/app/pages/contacts/contacts-list/contacts-list.component.html
+++ b/src/app/pages/contacts/contacts-list/contacts-list.component.html
@@ -51,12 +51,29 @@
           >
             DSGVO
           </button>
+          <div class="dsgvo-filter-item custom-control custom-switch" style="margin-left: 1rem;" *ngIf="!isDSGVOFilterAdvancedVisible" title="{{ 'Contacts.HasSyncErrorTooltip' | translate }}">
+            <input
+              type="checkbox"
+              class="custom-control-input"
+              style="margin-left: 12px;"
+              id="sync-error"
+              [ngModel]="modifiedContacts.withSyncError"
+              (change)="setModifiedContactsWithSyncErrorFilter(); searchContacts($event)"
+            />
+            <label
+              class="custom-control-label"
+              style="position: 0px;font-size: 13px; white-space: nowrap; line-height:21px; color: #495057;"
+              for="sync-error"
+            >
+              {{ 'Contacts.HasSyncError' | translate }}</label
+            >
+          </div>
           <div class="dsgvo-filter-options" *ngIf="isDSGVOFilterAdvancedVisible">
             <select
               [required]="false"
               type="text"
               class="form-control"
-              style="margin-right: 12px;"
+              style="margin-right: 0.6rem;"
               [ngModel]="moduleDisplayName"
               (change)="setModifiedContactsModuleAssignmentFilter($event.target.value); searchContacts($event)"
             >
@@ -84,7 +101,6 @@
 
             <div
               class="dsgvo-filter-item custom-control custom-switch"
-              style="margin-left:21px; "
               title="{{ 'Contacts.DSGVO-advanced-filter-deletion-lock-exceeded' | translate }}"
             >
               <input
diff --git a/src/app/pages/contacts/contacts-list/contacts-list.component.scss b/src/app/pages/contacts/contacts-list/contacts-list.component.scss
index f71da6d..4180bf6 100644
--- a/src/app/pages/contacts/contacts-list/contacts-list.component.scss
+++ b/src/app/pages/contacts/contacts-list/contacts-list.component.scss
@@ -118,8 +118,17 @@
   flex-grow: 1;
 }
 .dsgvo-filter-item {
-  margin: 4px 0px 0px 12px;
+  margin: 2px 0px 0px 0px;
 }
+
+.custom-control {
+  position: relative;
+  display: inline-flex;
+  padding-left: 1.75rem;
+  margin-right: 0.6rem;
+  margin-left: 0.6rem;
+}
+
 option:disabled {
   display: none;
 }
diff --git a/src/app/pages/contacts/contacts-list/contacts-list.component.ts b/src/app/pages/contacts/contacts-list/contacts-list.component.ts
index 1f957e5..0726ebf 100644
--- a/src/app/pages/contacts/contacts-list/contacts-list.component.ts
+++ b/src/app/pages/contacts/contacts-list/contacts-list.component.ts
@@ -46,6 +46,7 @@
   private _standardSorting = 'name,id';
   private _sortingContactType: string = '';
   private _expiringDataInPast = false;
+  private _withSyncError = false;
   private _deletionLockExceeded = false;
   private _subscription: Subscription;
 
@@ -79,6 +80,7 @@
       }
       this.isDSGVOFilterAdvancedVisible = this.modifiedContacts.isDSGVOFilterAdvancedVisible;
       this._expiringDataInPast = this.modifiedContacts.expiringDataInPast;
+      this._withSyncError = this.modifiedContacts.withSyncError;
       this._deletionLockExceeded = this.modifiedContacts.deletionLockExceeded;
       // modifiedContacts modulWerte zurueckuebersetzen in Display modulWerte
       this.setModifiedContactsModuleAssignmentFilterDisplayValues(this.modifiedContacts.moduleName, this.modifiedContacts.withoutAssignedModule);
@@ -178,6 +180,11 @@
     this.modifiedContacts.expiringDataInPast = this._expiringDataInPast;
   }
 
+  public setModifiedContactsWithSyncErrorFilter() {
+    this._withSyncError = !this._withSyncError;
+    this.modifiedContacts.withSyncError = this._withSyncError;
+  }
+
   public setModifiedContactsDeletionLockExceedFilter() {
     this._deletionLockExceeded = !this._deletionLockExceeded;
     this.modifiedContacts.deletionLockExceeded = this._deletionLockExceeded;
diff --git a/src/app/shared/components/header/header.component.html b/src/app/shared/components/header/header.component.html
index 7bbba7e..5342ac4 100644
--- a/src/app/shared/components/header/header.component.html
+++ b/src/app/shared/components/header/header.component.html
@@ -43,5 +43,5 @@
       </div>
     </div>
   </div>
-  <!-- <app-version-info class="version-info-simple"></app-version-info> -->
+  <app-version-info class="version-info-simple"></app-version-info>
 </nav>
diff --git a/src/app/shared/components/index.ts b/src/app/shared/components/index.ts
index 1834bdf..b67b5b6 100644
--- a/src/app/shared/components/index.ts
+++ b/src/app/shared/components/index.ts
@@ -26,7 +26,6 @@
 import { HeaderComponent } from '@shared/components/header/header.component';
 import { PageNotFoundComponent } from '@shared/components/pageNotFound/pageNotFound.component';
 import { LoadingPlaceholderComponent } from '@shared/components/loadingPlaceholder/loadingPlaceholder.component';
-import { VersionInfo } from '@shared/components/version-info/version-info.component';
 import { AngularFontAwesomeModule } from 'angular-font-awesome';
 import { ExpandableComponent } from '@shared/components/expandable/expandable.component';
 import { UserModuleAssignmentDataDetailsComponent } from '@shared/components/list-details-view/user-module-assignment/details/details.component';
@@ -46,6 +45,7 @@
 import { DateCellRendererComponent } from '@shared/components/cell-renderer/date-cell-renderer/date-cell-renderer.component';
 import { AnonymizerComponent } from '@shared/components/anonymizer/anonymizer.component';
 import { AnonymizerSandbox } from '@shared/components/anonymizer/anonymizer.sandbox';
+import { VersionInfo } from './version-info/version-info.component';
 
 export const COMPONENTS = [
   SpinnerComponent,
diff --git a/src/app/shared/components/version-info/version-api-client.ts b/src/app/shared/components/version-info/version-api-client.ts
new file mode 100644
index 0000000..54530e2
--- /dev/null
+++ b/src/app/shared/components/version-info/version-api-client.ts
@@ -0,0 +1,24 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+import { Injectable } from '@angular/core';
+import { HttpService, GET } from '@shared/asyncServices/http';
+import { Observable } from 'rxjs';
+
+@Injectable()
+export class VersionApiClient extends HttpService {
+
+  @GET('/version')
+  public version(): Observable<any> {
+    return null;
+  }
+}
diff --git a/src/app/shared/components/version-info/version-info.component.css b/src/app/shared/components/version-info/version-info.component.css
index 2e76624..4991b86 100644
--- a/src/app/shared/components/version-info/version-info.component.css
+++ b/src/app/shared/components/version-info/version-info.component.css
@@ -15,5 +15,6 @@
     bottom: 0;
     right: 0;
     font-size: x-small;
+    margin-right: 10px;
 }
 
diff --git a/src/app/shared/components/version-info/version-info.component.html b/src/app/shared/components/version-info/version-info.component.html
index 184b46b..5fc149a 100644
--- a/src/app/shared/components/version-info/version-info.component.html
+++ b/src/app/shared/components/version-info/version-info.component.html
@@ -11,6 +11,6 @@
 * SPDX-License-Identifier: EPL-2.0
 ********************************************************************************/ -->
 
-<div class="version-info">
-        Version: {{currVersion.frontendVersion}}f / {{currVersion.backendVersion}}b / {{currVersion.dbVersion}}d
+<div *ngIf="versionSandbox.version$ | async as version"  class="version-info">
+        Version: {{version.frontendVersion}}/{{version.backendVersion}}/{{version.dbVersion}}
 </div>
diff --git a/src/app/shared/components/version-info/version-info.component.spec.ts b/src/app/shared/components/version-info/version-info.component.spec.ts
index 16f93fe..65e2e5c 100644
--- a/src/app/shared/components/version-info/version-info.component.spec.ts
+++ b/src/app/shared/components/version-info/version-info.component.spec.ts
@@ -15,26 +15,25 @@
 
 describe('VersionInfo', () => {
   let component: VersionInfo;
+  let versionSandbox: any;
 
   beforeEach(async(() => {
   }));
 
   beforeEach(() => {
-    component = new VersionInfo();
+    versionSandbox = {
+      loadVersion(){}
+    } as any;
+    component = new VersionInfo(versionSandbox);
   });
 
-  it('should create', () => {
+  it('should create VersionInfo', () => {
     expect(component).toBeTruthy();
   });
 
-  it('should call back', () => {
-    const currVersion: any = {
-      frontendVersion: '1.0',
-      backendVersion: '1.0',
-      dbVersion: '1.0',
-    };
-    (component as any).setVersionInfo(currVersion);
-    expect(component.currVersion).toBe(currVersion);
+  it('should loadVersion on init', () => {
+    const spy = spyOn(versionSandbox, 'loadVersion');
+    component.ngOnInit();
+    expect(spy).toHaveBeenCalled();
   });
-
 });
diff --git a/src/app/shared/components/version-info/version-info.component.ts b/src/app/shared/components/version-info/version-info.component.ts
index be502ba..fbc5e92 100644
--- a/src/app/shared/components/version-info/version-info.component.ts
+++ b/src/app/shared/components/version-info/version-info.component.ts
@@ -11,11 +11,10 @@
  * SPDX-License-Identifier: EPL-2.0
  ********************************************************************************/
 
+import { HttpClient } from '@angular/common/http';
 import { Component, OnInit } from '@angular/core';
 import { Globals } from '@app/shared/constants/globals';
-// import { VersionInfo } from '../../model/version-info';
-// import { VersionInfoService } from '../../services/version-info.service';
-// import { Globals } from '../../common/globals';
+import { VersionSandbox } from './version-info.sandbox';
 
 @Component({
   selector: 'app-version-info',
@@ -23,21 +22,10 @@
   styleUrls: ['./version-info.component.css'],
 })
 export class VersionInfo implements OnInit {
-  currVersion: any = {
-    frontendVersion: '?',
-    backendVersion: '?',
-    dbVersion: '?',
-  };
 
-  // constructor(private _btbService: VersionInfoService) { }
+  constructor(public versionSandbox: VersionSandbox) { }
 
   ngOnInit() {
-    //   this._btbService.loadBackendServerInfo().subscribe(vinfo => this.setVersionInfo(vinfo),
-    //     error => console.log(error));
-  }
-
-  private setVersionInfo(vinfo: any) {
-    this.currVersion = vinfo;
-    this.currVersion.frontendVersion = Globals.FRONTEND_VERSION;
+    this.versionSandbox.loadVersion();
   }
 }
diff --git a/src/app/shared/components/version-info/version-info.sandbox.spec.ts b/src/app/shared/components/version-info/version-info.sandbox.spec.ts
index 2b3b2a1..6265138 100644
--- a/src/app/shared/components/version-info/version-info.sandbox.spec.ts
+++ b/src/app/shared/components/version-info/version-info.sandbox.spec.ts
@@ -10,20 +10,36 @@
  *
  * SPDX-License-Identifier: EPL-2.0
  ********************************************************************************/
+import { Store, ActionsSubject } from '@ngrx/store';
+import { State } from '@shared/store';
 import { async } from '@angular/core/testing';
-import { VersionInfoSandbox } from '@shared/components/version-info/version-info.sandbox';
+import { VersionSandbox } from './version-info.sandbox';
+import * as versionActions from '@shared/store/actions/version/version.action';
+import { of } from 'rxjs';
 
 describe('VersionInfoSandbox', () => {
-  let component: VersionInfoSandbox;
+  let appState: Store<State>;
+  let actionSubject: ActionsSubject;
+  let component: VersionSandbox;
 
   beforeEach(async(() => {
+    appState = { dispatch: () => {}, pipe: () => of(true), select: () => of(true) } as any;
+    actionSubject = { pipe: () => of(true) } as any;
+    spyOn(appState, 'dispatch').and.callFake(() => {});
+
   }));
 
   beforeEach(() => {
-    component = new VersionInfoSandbox();
+    component = new VersionSandbox(appState, actionSubject);
   });
 
-  it('should create', () => {
+  it('should create VersionInfoSandbox', () => {
     expect(component).toBeTruthy();
   });
+
+  it('should dispatch loadVersion Action via loadVersion()', () => {
+    component.loadVersion();
+    expect(appState.dispatch).toHaveBeenCalledWith(versionActions.version());
+  });
+
 });
diff --git a/src/app/shared/components/version-info/version-info.sandbox.ts b/src/app/shared/components/version-info/version-info.sandbox.ts
index 0a24f85..260ecac 100644
--- a/src/app/shared/components/version-info/version-info.sandbox.ts
+++ b/src/app/shared/components/version-info/version-info.sandbox.ts
@@ -11,21 +11,39 @@
  * SPDX-License-Identifier: EPL-2.0
  ********************************************************************************/
 import { Injectable } from '@angular/core';
+import { BaseSandbox } from '@shared/sandbox/base.sandbox';
+import { Store, ActionsSubject } from '@ngrx/store';
+import * as store from '@shared/store';
+import * as versionActions from '@shared/store/actions/version/version.action';
+import { ofType } from '@ngrx/effects';
+import { map } from 'rxjs/operators';
+import { take } from 'rxjs/operators';
+import { takeUntil } from 'rxjs/operators';
+import { Globals } from '@app/shared/constants/globals';
+import { ReplaySubject } from 'rxjs';
 
-/** Provides all Version infomrations
- *
- *
- * @author Martin Gardyan <martin.gardyan@pta.de>
- * @export
- * @class VersionInfoSandbox
- */
 @Injectable()
-export class VersionInfoSandbox {
-  /**
-   * Creates an instance of VersionInfoSandbox.
-   *
-   * @author Martin Gardyan <martin.gardyan@pta.de>
-   * @memberof VersionInfoSandbox
-   */
-  constructor() {}
+export class VersionSandbox extends BaseSandbox {
+  public version$: ReplaySubject<any> = new ReplaySubject();
+
+  constructor(protected appState$: Store<store.State>, private actionsSubject: ActionsSubject) {
+    super(appState$);
+  }
+
+  public loadVersion(): void {
+    this.appState$.dispatch(versionActions.version());
+    this.actionsSubject
+      .pipe(
+        ofType(versionActions.versionSuccess),
+        map((action: versionActions.IVersionSuccess) => action.payload),
+        take(1),
+        takeUntil(this._endSubscriptions$)
+      )
+      .subscribe((payload: any) => {
+        payload = {...payload, frontendVersion: Globals.FRONTEND_VERSION}
+        this.version$.next(payload);
+      });
+  }
+
+
 }
diff --git a/src/app/shared/components/version-info/version.module.ts b/src/app/shared/components/version-info/version.module.ts
new file mode 100644
index 0000000..c9f2f8b
--- /dev/null
+++ b/src/app/shared/components/version-info/version.module.ts
@@ -0,0 +1,41 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { RouterModule } from '@angular/router';
+import { ComponentsModule } from '@shared/components';
+import { TranslateModule } from '@ngx-translate/core';
+import { FormsModule } from '@angular/forms';
+import { DirectivesModule } from '@shared/directives';
+import { ContainersModule } from '@shared/containers';
+import { EffectsModule } from '@ngrx/effects';
+import { VersionApiClient } from './version-api-client';
+import { VersionEffects } from '@app/shared/store/effects/version/version.effect';
+import { VersionInfo } from './version-info.component';
+import { VersionSandbox } from './version-info.sandbox';
+
+
+@NgModule({
+  imports: [
+    CommonModule,
+    ComponentsModule,
+    TranslateModule,
+    DirectivesModule,
+    RouterModule,
+    FormsModule,
+    ContainersModule,
+    EffectsModule.forFeature([VersionEffects]),
+  ],
+  providers: [VersionSandbox, VersionApiClient],
+})
+export class VersionModule {}
diff --git a/src/app/shared/models/modifiedContacts.model.ts b/src/app/shared/models/modifiedContacts.model.ts
index 233ca62..71e0bcf 100644
--- a/src/app/shared/models/modifiedContacts.model.ts
+++ b/src/app/shared/models/modifiedContacts.model.ts
@@ -19,6 +19,7 @@
   public withoutAssignedModule: boolean = false;
   public expiringDataInPast: boolean = false;
   public deletionLockExceeded: boolean = false;
+  public withSyncError: boolean = false;
 
   public constructor(data: any = null) {
     Object.keys(data || {})
diff --git a/src/app/shared/models/permissions.model.ts b/src/app/shared/models/permissions.model.ts
index 146c1a2..bdf7071 100644
--- a/src/app/shared/models/permissions.model.ts
+++ b/src/app/shared/models/permissions.model.ts
@@ -31,7 +31,9 @@
             this.writer = true;
             break;
           case 'kon-reader':
-            this.reader = true;
+            if (!(this.admin || this.writer)) {
+              this.reader = true;
+            }
             break;
           default:
             break;
diff --git a/src/app/shared/store/actions/version/version.action.ts b/src/app/shared/store/actions/version/version.action.ts
new file mode 100644
index 0000000..167006b
--- /dev/null
+++ b/src/app/shared/store/actions/version/version.action.ts
@@ -0,0 +1,24 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+import { createAction, props } from '@ngrx/store';
+
+export interface IVersionSuccess {
+  payload: string;
+}
+
+export interface IVersionFail {
+  payload: string;
+}
+export const version = createAction('[Version] Version');
+export const versionSuccess = createAction('[Version] Version Success', props<IVersionSuccess>());
+export const versionFail = createAction('[Version] Version Fail', props<IVersionFail>());
diff --git a/src/app/shared/store/effects/version/logout.effects.spec.ts b/src/app/shared/store/effects/version/logout.effects.spec.ts
new file mode 100644
index 0000000..84a2efe
--- /dev/null
+++ b/src/app/shared/store/effects/version/logout.effects.spec.ts
@@ -0,0 +1,54 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+import { take } from 'rxjs/operators';
+import { Subject, of, throwError } from 'rxjs';
+import * as logoutActions from '@shared/store/actions/logout/logout.action';
+import { LogoutEffects } from '@shared/store/effects/logout/logout.effect';
+import { LogoutApiClient } from '@pages/logout/logout-api-client';
+
+describe('Logout Effects', () => {
+  let effects: LogoutEffects;
+  let actions$: Subject<any>;
+  let apiClient: LogoutApiClient;
+
+  beforeEach(() => {
+    apiClient = {
+      logout() {},
+    } as any;
+    actions$ = new Subject();
+    effects = new LogoutEffects(actions$, apiClient);
+  });
+
+  it('should be truthy', () => {
+    expect(effects).toBeTruthy();
+  });
+
+  it('should equal logoutSuccess after logout', done => {
+    let request = 'test';
+    spyOn(apiClient, 'logout').and.returnValue(of(request));
+    effects.logout$.pipe(take(1)).subscribe(result => {
+      expect(result).toEqual(logoutActions.logoutSuccess({ payload: request }));
+    });
+    done();
+    actions$.next(logoutActions.logout());
+  });
+
+  it('should equal logoutFail after logout Error', done => {
+    spyOn(apiClient, 'logout').and.returnValue(throwError('x'));
+    effects.logout$.pipe(take(1)).subscribe(result => {
+      expect(result).toEqual(logoutActions.logoutFail({ payload: 'x' }));
+    });
+    done();
+    actions$.next(logoutActions.logout());
+  });
+});
diff --git a/src/app/shared/store/effects/version/version.effect.ts b/src/app/shared/store/effects/version/version.effect.ts
new file mode 100644
index 0000000..41d9dad
--- /dev/null
+++ b/src/app/shared/store/effects/version/version.effect.ts
@@ -0,0 +1,39 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+import 'rxjs/add/operator/catch';
+import 'rxjs/add/operator/map';
+import 'rxjs/add/operator/switchMap';
+import { Injectable } from '@angular/core';
+import { createEffect, Actions, ofType } from '@ngrx/effects';
+import { of } from 'rxjs/observable/of';
+import * as versionActions from '@shared/store/actions/version/version.action';
+import { catchError, map, switchMap } from 'rxjs/operators';
+import { VersionApiClient } from '@app/shared/components/version-info/version-api-client';
+
+@Injectable()
+export class VersionEffects {
+  version$: any = createEffect(() =>
+    this._actions$.pipe(
+      ofType(versionActions.version),
+      map(action => action['payload']),
+      switchMap(() => {
+        return this._versionApiClient.version().pipe(
+          map(response => versionActions.versionSuccess({ payload: response })),
+          catchError(error => of(versionActions.versionFail({ payload: error })))
+        );
+      })
+    )
+  );
+
+  constructor(private _actions$: Actions, private _versionApiClient: VersionApiClient) {}
+}
diff --git a/src/index.html b/src/index.html
index d23b001..79bfb75 100644
--- a/src/index.html
+++ b/src/index.html
@@ -14,7 +14,7 @@
 <html lang="de">
 <head>
   <meta charset="utf-8">
-  <title>openKONSEQUENZ</title>
+  <title>Kontaktstammdaten - openKONSEQUENZ</title>
   <base href="/">
 
   <meta name="viewport" content="width=device-width, initial-scale=1">