Merge branch 'DEVELOP' of ssh://git.eclipse.org:29418/openk-usermodules/org.eclipse.openk-usermodules.contactBaseData.frontend into KON-438 + KON 642 unit tests + KON-668 suche - paging

Signed-off-by: Peter Buschmann <peter.buschmann@pta.de>
diff --git a/i18n/contacts.de.json b/i18n/contacts.de.json
index d9d7013..78fd4f0 100644
--- a/i18n/contacts.de.json
+++ b/i18n/contacts.de.json
@@ -11,8 +11,8 @@
     "Street": "Straße",
     "Community": "Ort",
     "CreateNewContact": "Neuen Kontakt anlegen",
-    "InternalContact": "Interner Kontakt",
-    "ExternalContact": "Externer Kontakt",
+    "InternalContact": "Interne Person",
+    "ExternalContact": "Externe Person",
     "Company": "Unternehmen",
     "AddressList": "Adressen",
     "AllContactTypes": "Alle Kontakttypen",
diff --git a/i18n/general.de.json b/i18n/general.de.json
index b4f5024..3856877 100644
--- a/i18n/general.de.json
+++ b/i18n/general.de.json
@@ -31,10 +31,12 @@
     "SubmitBtn": "Ja",
     "CancelBtn": "Nein",
     "Anonymization": "Wollen Sie diesen Kontakt wirklich anonymisieren? Dieser Vorgang kann nicht rückgängig gemacht werden. Sämtliche zu diesem Kontakt gehörenden Daten werden anonymisiert. Diese Daten können nicht wiederhergestellt werden.",
+    "MainAddressModification": "Es existiert schon eine Hauptadresse. Wollen Sie sie wirklich ändern?",
     "Action": {
       "delete": "Datensatz löschen",
       "edit": "Änderung verwerfen",
-      "anonymize": "Kontakt anonymisieren"
+      "anonymize": "Kontakt anonymisieren",
+      "changeMainAddress": "Hauptadresse ändern"
     }
   },
   "Tools": "Tools",
diff --git a/package.json b/package.json
index 67da642..f2edf8c 100644
--- a/package.json
+++ b/package.json
@@ -8,6 +8,7 @@
   "scripts": {
     "start": "npm run sy-pre-start && ng serve --proxy-config proxy.conf.json",
     "start-integration": "npm run sy-pre-start && ng serve --proxy-config proxy.conf-integration.json",
+    "start-local": "npm run sy-pre-start && ng serve --proxy-config proxy.conf-local.json",
     "test": "npm run sy-pre-test && ng test",
     "pree2e": "webdriver-manager update --standalone false --gecko false",
     "e2e": "ng e2e",
diff --git a/proxy.conf-integration.json b/proxy.conf-integration.json
index 27430d8..bc0c49b 100644
--- a/proxy.conf-integration.json
+++ b/proxy.conf-integration.json
@@ -1,6 +1,6 @@
 {
   "/api": {
-    "target": "http://entdockergss:9155",
+    "target": "http://localhost:9155",
     "secure": false,
     "pathRewrite": {
       "^/api": ""
diff --git a/proxy.conf-local.json b/proxy.conf-local.json
new file mode 100644
index 0000000..bc0c49b
--- /dev/null
+++ b/proxy.conf-local.json
@@ -0,0 +1,9 @@
+{
+  "/api": {
+    "target": "http://localhost:9155",
+    "secure": false,
+    "pathRewrite": {
+      "^/api": ""
+    }
+  }
+}
diff --git a/src/app/pages/company/company-details/address-details/address-details.component.html b/src/app/pages/company/company-details/address-details/address-details.component.html
index 2687302..1a6ee13 100644
--- a/src/app/pages/company/company-details/address-details/address-details.component.html
+++ b/src/app/pages/company/company-details/address-details/address-details.component.html
@@ -35,13 +35,11 @@
       <label for="isMainAddress" class="col-sm-5 col-form-label">{{ 'Address.MainAddress' | translate }}</label>
       <div class="col-sm-6" style="align-self: center;">
         <input
-          *ngIf="!companyDetailsSandbox.existMainAddress || companyDetailsSandbox.isCurrentAddressMainAddress"
           type="checkbox"
           class="form-check-input"
           id="isMainAddress"
           [ngrxFormControlState]="((companyDetailsSandbox.addressDetailsFormState$ | async)?.controls)['isMainAddress']"
         />
-        <span *ngIf="companyDetailsSandbox.existMainAddress && !companyDetailsSandbox.isCurrentAddressMainAddress">(vorhanden)</span>
       </div>
     </div>
 
@@ -196,7 +194,7 @@
     </div>
 
     <!-- buttons -->
-    <button *visibleByRight type="button" class="btn btn-primary btn-sm btn-success" (click)="companyDetailsSandbox.persistAddress()">
+    <button *visibleByRight type="button" class="btn btn-primary btn-sm btn-success" (click)="showDialog()">
       {{ 'SaveBtn' | translate }}
     </button>
 
diff --git a/src/app/pages/company/company-details/address-details/address-details.component.spec.ts b/src/app/pages/company/company-details/address-details/address-details.component.spec.ts
index fa953c9..a1f940f 100644
--- a/src/app/pages/company/company-details/address-details/address-details.component.spec.ts
+++ b/src/app/pages/company/company-details/address-details/address-details.component.spec.ts
@@ -12,11 +12,14 @@
  ********************************************************************************/
 import { async } from '@angular/core/testing';
 import { CompanyAddressDetailsComponent } from '@pages/company/company-details/address-details/address-details.component';
+import { of } from 'rxjs';
 
 describe('AddressDetailsComponent', () => {
   let component: CompanyAddressDetailsComponent;
   let companySandbox: any;
   let addressTypesSandbox: any;
+  let modalService: any;
+  let actionsSubject: any;
 
   beforeEach(async(() => {
     companySandbox = {
@@ -24,13 +27,21 @@
       registerCompanyEvents() {},
       endSubscriptions() {},
       clearAddressData() {},
+      persistAddress() {},
+      addressDetailsCurrentFormState: { value: {} },
+      existMainAddress: null,
+      isCurrentAddressMainAddress: null,
+    } as any;
+
+    modalService = {
+      open() {},
     } as any;
   }));
 
-  addressTypesSandbox= {};
+  addressTypesSandbox = {};
 
   beforeEach(() => {
-    component = new CompanyAddressDetailsComponent(companySandbox, addressTypesSandbox);
+    component = new CompanyAddressDetailsComponent(companySandbox, addressTypesSandbox, modalService, actionsSubject);
   });
 
   it('should create', () => {
@@ -44,4 +55,27 @@
     expect(spy1).toHaveBeenCalled();
     expect(spy2).toHaveBeenCalled();
   });
+
+  it('check if showDialog() works', () => {
+    const spy1 = spyOn(component['modalService'], 'open').and.returnValue({ componentInstance: { title: '' }, result: { then: () => of(true) } } as any);
+    companySandbox.addressDetailsCurrentFormState = { value: { isMainAddress: true } };
+    companySandbox.existMainAddress = true;
+    companySandbox.isCurrentAddressMainAddress = true;
+    component.showDialog();
+    expect(spy1).not.toHaveBeenCalled();
+
+    companySandbox.isCurrentAddressMainAddress = false;
+    component.showDialog();
+    expect(spy1).toHaveBeenCalled();
+  });
+
+  it('should open modal before persist an address', () => {
+    spyOn(component['modalService'], 'open').and.returnValue({ componentInstance: { title: '' }, result: { then: () => of(true) } } as any);
+    component.companyDetailsSandbox.addressDetailsCurrentFormState.value.isMainAddress = true;
+    component.companyDetailsSandbox.existMainAddress = true;
+    component.companyDetailsSandbox.isCurrentAddressMainAddress = false;
+
+    component.showDialog();
+    expect(modalService.open).toHaveBeenCalled();
+  });
 });
diff --git a/src/app/pages/company/company-details/address-details/address-details.component.ts b/src/app/pages/company/company-details/address-details/address-details.component.ts
index 0389161..b5ce881 100644
--- a/src/app/pages/company/company-details/address-details/address-details.component.ts
+++ b/src/app/pages/company/company-details/address-details/address-details.component.ts
@@ -13,24 +13,53 @@
 import { CompanyDetailsSandBox } from '@pages/company/company-details/company-details.sandbox';
 import { Component, OnInit, Input } from '@angular/core';
 import { AddressTypesSandbox } from '@pages/admin/address-types/address-types.sandbox';
+import { SafetyQueryDialogComponent } from '@shared/components/dialogs/safety-query-dialog/safety-query-dialog.component';
+import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
+import { ActionsSubject } from '@ngrx/store';
+import * as companyActions from '@shared/store/actions/company/company.action';
+import { ofType } from '@ngrx/effects';
+import { take } from 'rxjs/operators';
 
 @Component({
   selector: 'app-company-address-details',
   templateUrl: './address-details.component.html',
-  styleUrls: ['./address-details.component.scss']
+  styleUrls: ['./address-details.component.scss'],
 })
 export class CompanyAddressDetailsComponent implements OnInit {
-
-  @Input() createOrEditAddressData: string;
+  @Input() public createOrEditAddressData: string;
 
   constructor(
     public companyDetailsSandbox: CompanyDetailsSandBox,
-    public addressTypesSandbox: AddressTypesSandbox
-  ) { }
+    public addressTypesSandbox: AddressTypesSandbox,
+    private modalService: NgbModal,
+    private actionsSubject: ActionsSubject
+  ) {}
 
   ngOnInit() {
     this.companyDetailsSandbox.registerAddressEvents();
     this.companyDetailsSandbox.clearAddressData();
   }
 
+  showDialog(): void {
+    if (
+      this.companyDetailsSandbox.addressDetailsCurrentFormState.value.isMainAddress &&
+      this.companyDetailsSandbox.existMainAddress &&
+      !this.companyDetailsSandbox.isCurrentAddressMainAddress
+    ) {
+      const modalRef = this.modalService.open(SafetyQueryDialogComponent);
+      modalRef.componentInstance.title = 'ConfirmDialog.Action.changeMainAddress';
+      modalRef.componentInstance.body = 'ConfirmDialog.MainAddressModification';
+      modalRef.result.then(
+        () => {
+          this.actionsSubject.pipe(ofType(companyActions.persistAddressDetailSuccess), take(1)).subscribe(() => {
+            this.companyDetailsSandbox.persistAddress();
+          });
+          this.companyDetailsSandbox.removeCurrentMainAddress();
+        },
+        () => {}
+      );
+    } else {
+      this.companyDetailsSandbox.persistAddress();
+    }
+  }
 }
diff --git a/src/app/pages/company/company-details/company-details.sandbox.ts b/src/app/pages/company/company-details/company-details.sandbox.ts
index e0af2ed..c2367ff 100644
--- a/src/app/pages/company/company-details/company-details.sandbox.ts
+++ b/src/app/pages/company/company-details/company-details.sandbox.ts
@@ -54,6 +54,7 @@
   public contactPersonsListLoading$: Observable<boolean> = this.appState$.select(store.getCompanyContactPersonsLoading);
 
   private _communicationTypes: Array<CommunicationType> = new Array<CommunicationType>();
+  private _mainAddress: Address;
 
   /**
    *  Company Sandbox constructor
@@ -290,18 +291,25 @@
     );
   }
 
-  private _checkIfMainAddressExist(addresses: Array<Address>) {
+  removeCurrentMainAddress(): void {
+    this._mainAddress.isMainAddress = false;
+    this.appState$.dispatch(companyActions.persistAddressDetail({ payload: this._mainAddress }));
+  }
+
+  private _checkIfMainAddressExist(addresses: Array<Address>): void {
     for (let i = 0; i < addresses.length; i++) {
       const address = addresses[i];
       if (address.isMainAddress) {
+        this._mainAddress = address;
         this.existMainAddress = true;
         break;
       }
+      this._mainAddress = null;
       this.existMainAddress = false;
     }
   }
 
-  private _checkIfCurrentAddressIsMainAddress(address: Address) {
-    this.isCurrentAddressMainAddress = address.isMainAddress ? true : false;
+  private _checkIfCurrentAddressIsMainAddress(address: Address): void {
+    this.isCurrentAddressMainAddress = address.isMainAddress;
   }
 }
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 6a44871..29c22a3 100644
--- a/src/app/pages/contacts/contacts-list/contacts-list.component.html
+++ b/src/app/pages/contacts/contacts-list/contacts-list.component.html
@@ -136,7 +136,7 @@
 
       <div class="select-type-of-new-contact item" *visibleByRight>
         <select type="text" class="form-control" id="newContactDropDown" (change)="navigateTo($event.target.value)">
-          <option value="" disabled selected>{{ 'Contacts.CreateNewContact' | translate }}</option>
+          <option value="" disabled>{{ 'Contacts.CreateNewContact' | translate }}</option>
           <option [value]="NEW_INTERNAL_PERSON_PATH">{{ 'Contacts.InternalContact' | translate }}</option>
           <option [value]="NEW_EXTERNAL_PERSON_PATH">{{ 'Contacts.ExternalContact' | translate }}</option>
           <option [value]="NEW_COMPANY_PATH">{{ 'Contacts.Company' | translate }}</option>
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 003b9a0..5177a30 100644
--- a/src/app/pages/contacts/contacts-list/contacts-list.component.scss
+++ b/src/app/pages/contacts/contacts-list/contacts-list.component.scss
@@ -120,6 +120,9 @@
 .dsgvo-filter-item {
   margin: 4px 0px 0px 12px;
 }
+option:disabled {
+  display: none;
+}
 
 #newContactDropDown {
   background-color: #003a5f;
diff --git a/src/app/pages/contacts/contacts-list/contacts-list.component.spec.ts b/src/app/pages/contacts/contacts-list/contacts-list.component.spec.ts
index 222b05f..c13d2ee 100644
--- a/src/app/pages/contacts/contacts-list/contacts-list.component.spec.ts
+++ b/src/app/pages/contacts/contacts-list/contacts-list.component.spec.ts
@@ -1,3 +1,4 @@
+import { ColumnApi } from 'ag-grid-community';
 /********************************************************************************
  * Copyright (c) 2020 Contributors to the Eclipse Foundation
  *
@@ -36,6 +37,30 @@
     expect(component.gridOptions.context).toBeDefined();
   });
 
+  it('should set sessionStorage via _saveColumnPositions for ColumnMovedEvent', () => {
+    const spy = spyOn(sessionStorage as any, 'setItem');
+    const event: any = { columnApi: { getColumnState() {} } };
+    (component as any)._saveColumnPositions(event);
+
+    expect(spy).toHaveBeenCalled();
+  });
+
+  it('should set columnState via _restorColumnPositions ', () => {
+    const event: any = {
+      columnApi: {
+        getColumnState() {
+          return 'x';
+        },
+        setColumnState() {},
+      },
+    };
+    const spy = spyOn(event.columnApi as any, 'setColumnState');
+    (component as any)._saveColumnPositions(event);
+    (component as any)._restoreColumnPositions(event);
+
+    expect(spy).toHaveBeenCalled();
+  });
+
   it('should _navigateToDetails if BusEvents is edit ', () => {
     const spy = spyOn(component as any, '_navigateToDetails');
     const event: any = { type: 'edit' };
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 daefb2f..11ce7b8 100644
--- a/src/app/pages/contacts/contacts-list/contacts-list.component.ts
+++ b/src/app/pages/contacts/contacts-list/contacts-list.component.ts
@@ -201,7 +201,6 @@
   public sortContacts() {
     this._setModifiedContactsSort();
     this.modifiedContacts = { ...this.modifiedContacts };
-    console.log(this.modifiedContacts);
     sessionStorage.setItem(Globals.SESSSION_STORAGE_KEYS.contactListSearchFilterKey, JSON.stringify(this.modifiedContacts));
   }
 
diff --git a/src/app/pages/persons/external-person/external-person-details/address-details/address-details.component.html b/src/app/pages/persons/external-person/external-person-details/address-details/address-details.component.html
index 9643472..4fdd5a0 100644
--- a/src/app/pages/persons/external-person/external-person-details/address-details/address-details.component.html
+++ b/src/app/pages/persons/external-person/external-person-details/address-details/address-details.component.html
@@ -35,13 +35,11 @@
       <label for="isMainAddress" class="col-sm-5 col-form-label">{{ 'Address.MainAddress' | translate }}</label>
       <div class="col-sm-6" style="align-self: center;">
         <input
-          *ngIf="!externalPersonDetailsSandbox.existMainAddress || externalPersonDetailsSandbox.isCurrentAddressMainAddress"
           type="checkbox"
           class="form-check-input"
           id="isMainAddress"
           [ngrxFormControlState]="((externalPersonDetailsSandbox.addressDetailsFormState$ | async)?.controls)['isMainAddress']"
         />
-        <span *ngIf="externalPersonDetailsSandbox.existMainAddress && !externalPersonDetailsSandbox.isCurrentAddressMainAddress">(vorhanden)</span>
       </div>
     </div>
 
@@ -196,7 +194,7 @@
     </div>
 
     <!-- buttons -->
-    <button *visibleByRight type="button" class="btn btn-primary btn-sm btn-success" (click)="externalPersonDetailsSandbox.persistAddress()">
+    <button *visibleByRight type="button" class="btn btn-primary btn-sm btn-success" (click)="showDialog()">
       {{ 'SaveBtn' | translate }}
     </button>
 
diff --git a/src/app/pages/persons/external-person/external-person-details/address-details/address-details.component.spec.ts b/src/app/pages/persons/external-person/external-person-details/address-details/address-details.component.spec.ts
index b81d79a..f31cd3e 100644
--- a/src/app/pages/persons/external-person/external-person-details/address-details/address-details.component.spec.ts
+++ b/src/app/pages/persons/external-person/external-person-details/address-details/address-details.component.spec.ts
@@ -12,11 +12,14 @@
  ********************************************************************************/
 import { async } from '@angular/core/testing';
 import { ExternalPersonAddressDetailsComponent } from '@pages/persons/external-person/external-person-details/address-details/address-details.component';
+import { of } from 'rxjs';
 
 describe('AddressDetailsComponent', () => {
   let component: ExternalPersonAddressDetailsComponent;
   let externalPersonSandbox: any;
   let addressTypesSandbox: any;
+  let modalService: any;
+  let actionsSubject: any;
 
   beforeEach(async(() => {
     externalPersonSandbox = {
@@ -24,13 +27,19 @@
       registerExternalPersonEvents() {},
       endSubscriptions() {},
       newAddressData() {},
+      persistAddress() {},
+      addressDetailsCurrentFormState: { value: {} },
+      existMainAddress: null,
+      isCurrentAddressMainAddress: null,
     } as any;
 
+    modalService = { open() {} } as any;
+
     addressTypesSandbox = {};
   }));
 
   beforeEach(() => {
-    component = new ExternalPersonAddressDetailsComponent(externalPersonSandbox, addressTypesSandbox);
+    component = new ExternalPersonAddressDetailsComponent(externalPersonSandbox, addressTypesSandbox, modalService, actionsSubject);
   });
 
   it('should create', () => {
@@ -44,4 +53,28 @@
     expect(spy1).toHaveBeenCalled();
     expect(spy2).toHaveBeenCalled();
   });
+
+  it('check if showDialog() works', () => {
+    const spy1 = spyOn(component['modalService'], 'open').and.returnValue({ componentInstance: { title: '' }, result: { then: () => of(true) } } as any);
+    externalPersonSandbox.addressDetailsCurrentFormState = { value: { isMainAddress: true } };
+    externalPersonSandbox.existMainAddress = true;
+    externalPersonSandbox.isCurrentAddressMainAddress = true;
+    component.showDialog();
+    expect(spy1).not.toHaveBeenCalled();
+
+    externalPersonSandbox.isCurrentAddressMainAddress = false;
+    component.showDialog();
+    expect(spy1).toHaveBeenCalled();
+  });
+
+  it('should open modal before persist an address', () => {
+    const spy1 = spyOn(externalPersonSandbox, 'persistAddress');
+    spyOn(component['modalService'], 'open').and.returnValue({ componentInstance: { title: '' }, result: { then: () => of(true) } } as any);
+    externalPersonSandbox.addressDetailsCurrentFormState.value.isMainAddress = true;
+    externalPersonSandbox.existMainAddress = true;
+    externalPersonSandbox.isCurrentAddressMainAddress = false;
+
+    component.showDialog();
+    expect(modalService.open).toHaveBeenCalled();
+  });
 });
diff --git a/src/app/pages/persons/external-person/external-person-details/address-details/address-details.component.ts b/src/app/pages/persons/external-person/external-person-details/address-details/address-details.component.ts
index 5f20d5c..54a24e4 100644
--- a/src/app/pages/persons/external-person/external-person-details/address-details/address-details.component.ts
+++ b/src/app/pages/persons/external-person/external-person-details/address-details/address-details.component.ts
@@ -13,6 +13,12 @@
 import { ExternalPersonDetailsSandBox } from '@pages/persons/external-person/external-person-details/external-person-details.sandbox';
 import { Component, OnInit, Input } from '@angular/core';
 import { AddressTypesSandbox } from '@pages/admin/address-types/address-types.sandbox';
+import { SafetyQueryDialogComponent } from '@shared/components/dialogs/safety-query-dialog/safety-query-dialog.component';
+import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
+import { ActionsSubject } from '@ngrx/store';
+import * as externalPersonActions from '@shared/store/actions/persons/external-person.action';
+import { ofType } from '@ngrx/effects';
+import { take } from 'rxjs/operators';
 
 @Component({
   selector: 'app-external-person-address-details',
@@ -22,10 +28,38 @@
 export class ExternalPersonAddressDetailsComponent implements OnInit {
   @Input() createOrEditAddressData: string;
 
-  constructor(public externalPersonDetailsSandbox: ExternalPersonDetailsSandBox, public addressTypesSandbox: AddressTypesSandbox) {}
+  constructor(
+    public externalPersonDetailsSandbox: ExternalPersonDetailsSandBox,
+    public addressTypesSandbox: AddressTypesSandbox,
+    private modalService: NgbModal,
+    private actionsSubject: ActionsSubject
+  ) {}
 
   ngOnInit() {
     this.externalPersonDetailsSandbox.registerAddressEvents();
     this.externalPersonDetailsSandbox.newAddressData();
   }
+
+  showDialog(): void {
+    if (
+      this.externalPersonDetailsSandbox.addressDetailsCurrentFormState.value.isMainAddress &&
+      this.externalPersonDetailsSandbox.existMainAddress &&
+      !this.externalPersonDetailsSandbox.isCurrentAddressMainAddress
+    ) {
+      const modalRef = this.modalService.open(SafetyQueryDialogComponent);
+      modalRef.componentInstance.title = 'ConfirmDialog.Action.changeMainAddress';
+      modalRef.componentInstance.body = 'ConfirmDialog.MainAddressModification';
+      modalRef.result.then(
+        () => {
+          this.actionsSubject.pipe(ofType(externalPersonActions.persistAddressDetailSuccess), take(1)).subscribe(() => {
+            this.externalPersonDetailsSandbox.persistAddress();
+          });
+          this.externalPersonDetailsSandbox.removeCurrentMainAddress();
+        },
+        () => {}
+      );
+    } else {
+      this.externalPersonDetailsSandbox.persistAddress();
+    }
+  }
 }
diff --git a/src/app/pages/persons/external-person/external-person-details/external-person-details.sandbox.ts b/src/app/pages/persons/external-person/external-person-details/external-person-details.sandbox.ts
index da01572..835f733 100644
--- a/src/app/pages/persons/external-person/external-person-details/external-person-details.sandbox.ts
+++ b/src/app/pages/persons/external-person/external-person-details/external-person-details.sandbox.ts
@@ -50,6 +50,7 @@
   public externalPersonContactId: string;
   public isCommunicationsDataDetailViewVisible: boolean = false;
   private _communicationTypes: Array<CommunicationType> = new Array<CommunicationType>();
+  private _mainAddress: Address;
 
   /**
    *  ExternalPerson Sandbox constructor
@@ -271,18 +272,25 @@
       .subscribe((formState: FormGroupState<CommunicationsData>) => (this.communicationsDataDetailsCurrentFormState = formState));
   }
 
+  removeCurrentMainAddress(): void {
+    this._mainAddress.isMainAddress = false;
+    this.appState$.dispatch(externalPersonActions.persistAddressDetail({ payload: this._mainAddress }));
+  }
+
   private _checkIfMainAddressExist(addresses: Array<Address>) {
     for (let i = 0; i < addresses.length; i++) {
       const address = addresses[i];
       if (address.isMainAddress) {
+        this._mainAddress = address;
         this.existMainAddress = true;
         break;
       }
+      this._mainAddress = address;
       this.existMainAddress = false;
     }
   }
 
-  private _checkIfCurrentAddressIsMainAddress(address: Address) {
-    this.isCurrentAddressMainAddress = address.isMainAddress ? true : false;
+  private _checkIfCurrentAddressIsMainAddress(address: Address): void {
+    this.isCurrentAddressMainAddress = address.isMainAddress;
   }
 }
diff --git a/src/app/pages/persons/internal-person/internal-person-details/address-details/address-details.component.html b/src/app/pages/persons/internal-person/internal-person-details/address-details/address-details.component.html
index 9841004..32e09f3 100644
--- a/src/app/pages/persons/internal-person/internal-person-details/address-details/address-details.component.html
+++ b/src/app/pages/persons/internal-person/internal-person-details/address-details/address-details.component.html
@@ -35,13 +35,11 @@
       <label for="isMainAddress" class="col-sm-5 col-form-label">{{ 'Address.MainAddress' | translate }}</label>
       <div class="col-sm-6" style="align-self: center;">
         <input
-          *ngIf="!internalPersonDetailsSandbox.existMainAddress || internalPersonDetailsSandbox.isCurrentAddressMainAddress"
           type="checkbox"
           class="form-check-input"
           id="isMainAddress"
           [ngrxFormControlState]="((internalPersonDetailsSandbox.addressDetailsFormState$ | async)?.controls)['isMainAddress']"
         />
-        <span *ngIf="internalPersonDetailsSandbox.existMainAddress && !internalPersonDetailsSandbox.isCurrentAddressMainAddress">(vorhanden)</span>
       </div>
     </div>
 
@@ -196,7 +194,7 @@
     </div>
 
     <!-- buttons -->
-    <button *visibleByRight type="button" class="btn btn-primary btn-sm btn-success" (click)="internalPersonDetailsSandbox.persistAddress()">
+    <button *visibleByRight type="button" class="btn btn-primary btn-sm btn-success" (click)="showDialog()">
       {{ 'SaveBtn' | translate }}
     </button>
 
diff --git a/src/app/pages/persons/internal-person/internal-person-details/address-details/address-details.component.spec.ts b/src/app/pages/persons/internal-person/internal-person-details/address-details/address-details.component.spec.ts
index 625bd41..4a470d6 100644
--- a/src/app/pages/persons/internal-person/internal-person-details/address-details/address-details.component.spec.ts
+++ b/src/app/pages/persons/internal-person/internal-person-details/address-details/address-details.component.spec.ts
@@ -12,11 +12,14 @@
  ********************************************************************************/
 import { async } from '@angular/core/testing';
 import { InternalPersonAddressDetailsComponent } from '@pages/persons/internal-person/internal-person-details/address-details/address-details.component';
+import { of } from 'rxjs';
 
 describe('AddressDetailsComponent', () => {
   let component: InternalPersonAddressDetailsComponent;
   let internalPersonSandbox: any;
   let addressTypesSandbox: any;
+  let modalService: any;
+  let actionsSubject: any;
 
   beforeEach(async(() => {
     internalPersonSandbox = {
@@ -24,13 +27,19 @@
       registerExternalPersonEvents() {},
       endSubscriptions() {},
       newAddressData() {},
+      persistAddress() {},
+      addressDetailsCurrentFormState: { value: {} },
+      existMainAddress: null,
+      isCurrentAddressMainAddress: null,
     } as any;
 
+    modalService = { open() {} } as any;
+
     addressTypesSandbox = {};
   }));
 
   beforeEach(() => {
-    component = new InternalPersonAddressDetailsComponent(internalPersonSandbox, addressTypesSandbox);
+    component = new InternalPersonAddressDetailsComponent(internalPersonSandbox, addressTypesSandbox, modalService, actionsSubject);
   });
 
   it('should create', () => {
@@ -44,4 +53,27 @@
     expect(spy1).toHaveBeenCalled();
     expect(spy2).toHaveBeenCalled();
   });
+
+  it('check if showDialog() works', () => {
+    const spy1 = spyOn(component['modalService'], 'open').and.returnValue({ componentInstance: { title: '' }, result: { then: () => of(true) } } as any);
+    internalPersonSandbox.addressDetailsCurrentFormState = { value: { isMainAddress: true } };
+    internalPersonSandbox.existMainAddress = true;
+    internalPersonSandbox.isCurrentAddressMainAddress = true;
+    component.showDialog();
+    expect(spy1).not.toHaveBeenCalled();
+
+    internalPersonSandbox.isCurrentAddressMainAddress = false;
+    component.showDialog();
+    expect(spy1).toHaveBeenCalled();
+  });
+
+  it('should open modal before persist an address', () => {
+    spyOn(component['modalService'], 'open').and.returnValue({ componentInstance: { title: '' }, result: { then: () => of(true) } } as any);
+    internalPersonSandbox.addressDetailsCurrentFormState.value.isMainAddress = true;
+    internalPersonSandbox.existMainAddress = true;
+    internalPersonSandbox.isCurrentAddressMainAddress = false;
+
+    component.showDialog();
+    expect(modalService.open).toHaveBeenCalled();
+  });
 });
diff --git a/src/app/pages/persons/internal-person/internal-person-details/address-details/address-details.component.ts b/src/app/pages/persons/internal-person/internal-person-details/address-details/address-details.component.ts
index f8baa61..bed4e05 100644
--- a/src/app/pages/persons/internal-person/internal-person-details/address-details/address-details.component.ts
+++ b/src/app/pages/persons/internal-person/internal-person-details/address-details/address-details.component.ts
@@ -13,6 +13,12 @@
 import { InternalPersonDetailsSandBox } from '@pages/persons/internal-person/internal-person-details/internal-person-details.sandbox';
 import { Component, OnInit, Input } from '@angular/core';
 import { AddressTypesSandbox } from '@pages/admin/address-types/address-types.sandbox';
+import { SafetyQueryDialogComponent } from '@shared/components/dialogs/safety-query-dialog/safety-query-dialog.component';
+import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
+import { ActionsSubject } from '@ngrx/store';
+import * as internalPersonActions from '@shared/store/actions/persons/internal-person.action';
+import { ofType } from '@ngrx/effects';
+import { take } from 'rxjs/operators';
 
 @Component({
   selector: 'app-internal-person-address-details',
@@ -22,10 +28,38 @@
 export class InternalPersonAddressDetailsComponent implements OnInit {
   @Input() createOrEditAddressData: string;
 
-  constructor(public internalPersonDetailsSandbox: InternalPersonDetailsSandBox, public addressTypesSandbox: AddressTypesSandbox) {}
+  constructor(
+    public internalPersonDetailsSandbox: InternalPersonDetailsSandBox,
+    public addressTypesSandbox: AddressTypesSandbox,
+    private modalService: NgbModal,
+    private actionsSubject: ActionsSubject
+  ) {}
 
   ngOnInit() {
     this.internalPersonDetailsSandbox.registerAddressEvents();
     this.internalPersonDetailsSandbox.newAddressData();
   }
+
+  showDialog(): void {
+    if (
+      this.internalPersonDetailsSandbox.addressDetailsCurrentFormState.value.isMainAddress &&
+      this.internalPersonDetailsSandbox.existMainAddress &&
+      !this.internalPersonDetailsSandbox.isCurrentAddressMainAddress
+    ) {
+      const modalRef = this.modalService.open(SafetyQueryDialogComponent);
+      modalRef.componentInstance.title = 'ConfirmDialog.Action.changeMainAddress';
+      modalRef.componentInstance.body = 'ConfirmDialog.MainAddressModification';
+      modalRef.result.then(
+        () => {
+          this.actionsSubject.pipe(ofType(internalPersonActions.persistAddressDetailSuccess), take(1)).subscribe(() => {
+            this.internalPersonDetailsSandbox.persistAddress();
+          });
+          this.internalPersonDetailsSandbox.removeCurrentMainAddress();
+        },
+        () => {}
+      );
+    } else {
+      this.internalPersonDetailsSandbox.persistAddress();
+    }
+  }
 }
diff --git a/src/app/pages/persons/internal-person/internal-person-details/internal-person-details.component.html b/src/app/pages/persons/internal-person/internal-person-details/internal-person-details.component.html
index 1fae53a..7865c91 100644
--- a/src/app/pages/persons/internal-person/internal-person-details/internal-person-details.component.html
+++ b/src/app/pages/persons/internal-person/internal-person-details/internal-person-details.component.html
@@ -108,6 +108,8 @@
               [editable]="false"
               (selectItem)="internalPersonSandBox.setLdapUidValue($event)"
               autocomplete="off"
+              [resultFormatter]="internalPersonSandBox.formatter"
+              [inputFormatter]="internalPersonSandBox.formatter"
             />
           </div>
           <div class="col-sm-4">
diff --git a/src/app/pages/persons/internal-person/internal-person-details/internal-person-details.sandbox.spec.ts b/src/app/pages/persons/internal-person/internal-person-details/internal-person-details.sandbox.spec.ts
index 6b57a01..2724a30 100644
--- a/src/app/pages/persons/internal-person/internal-person-details/internal-person-details.sandbox.spec.ts
+++ b/src/app/pages/persons/internal-person/internal-person-details/internal-person-details.sandbox.spec.ts
@@ -14,7 +14,7 @@
 import { InternalPersonDetailsSandBox } from '@pages/persons/internal-person/internal-person-details/internal-person-details.sandbox';
 import { of } from 'rxjs';
 import * as internalPersonActions from '@shared/store/actions/persons/internal-person.action';
-import { InternalPerson, CommunicationsData, Address } from '@shared/models';
+import { InternalPerson, CommunicationsData, Address, LdapUser } from '@shared/models';
 
 describe('InternalPersonDetailsSandBox', () => {
   let component: InternalPersonDetailsSandBox;
@@ -316,21 +316,22 @@
 
   it('should call dispatch and clear the userref if setLdapUidValue called with null', () => {
     component.internalPersonDetailsCurrentFormState = {
-      controls: { uid: { id: 'test' } },
-      value: { uid: 'test1' },
+      controls: { uid: { id: 'test1' }, firstName: { id: 'test2' }, lastName: { id: 'test3' } },
+      value: { uid: 'test1', firstName: 'test2', lastName: 'test3' },
     } as any;
     const spy = spyOn(appState, 'dispatch').and.callThrough();
     component.setLdapUidValue(null);
-    expect(spy).toHaveBeenCalledTimes(1);
+    expect(spy).toHaveBeenCalledTimes(3);
   });
 
   it('should call dispatch and set the userref if setLdapUidValue called with a value', () => {
     component.internalPersonDetailsCurrentFormState = {
-      controls: { uid: { id: 'test' } },
-      value: { uid: 'test1' },
+      controls: { uid: { id: 'test1' }, firstName: { id: 'test2' }, lastName: { id: 'test3' } },
+      value: { uid: 'test1', firstName: 'test2', lastName: 'test3' },
     } as any;
+    let ldapUser = { firstName: 'Muster', lastName: 'Administrator', uid: 'admin' };
     const spy = spyOn(appState, 'dispatch').and.callThrough();
-    component.setLdapUidValue({ item: 'Muster Administrator (admin)' } as any);
-    expect(spy).toHaveBeenCalledTimes(1);
+    component.setLdapUidValue({ item: ldapUser });
+    expect(spy).toHaveBeenCalledTimes(3);
   });
 });
diff --git a/src/app/pages/persons/internal-person/internal-person-details/internal-person-details.sandbox.ts b/src/app/pages/persons/internal-person/internal-person-details/internal-person-details.sandbox.ts
index 45611ab..707545e 100644
--- a/src/app/pages/persons/internal-person/internal-person-details/internal-person-details.sandbox.ts
+++ b/src/app/pages/persons/internal-person/internal-person-details/internal-person-details.sandbox.ts
@@ -49,12 +49,14 @@
   public isCommunicationsDataDetailViewVisible: boolean = false;
   public isAddressDataDetailViewVisible: boolean = false;
   public existMainAddress = false;
+  public showSynchAlertMessage = false;
   public isCurrentAddressMainAddress = false;
   public internalPersonContactId: string;
   private _currentInternalPerson: InternalPerson = null;
   private _communicationTypes: Array<CommunicationType> = new Array<CommunicationType>();
   private _keycloakUsers: Array<KeycloakUser> = new Array<KeycloakUser>();
   private _ldapUsers: Array<LdapUser> = new Array<LdapUser>();
+  private _mainAddress: Address;
 
   constructor(
     public appState$: Store<store.State>,
@@ -251,9 +253,9 @@
 
   public registerInternalPersonEvents(): void {
     // subscribes to formState
-    this.internalPersonDetailsFormState$
-      .pipe(takeUntil(this._endSubscriptions$))
-      .subscribe((formState: FormGroupState<InternalPerson>) => (this.internalPersonDetailsCurrentFormState = formState));
+    this.internalPersonDetailsFormState$.pipe(takeUntil(this._endSubscriptions$)).subscribe((formState: FormGroupState<InternalPerson>) => {
+      this.internalPersonDetailsCurrentFormState = formState;
+    });
   }
 
   public loadCommunicationsData(internalPersonId: string): void {
@@ -389,32 +391,37 @@
     text$.pipe(
       debounceTime(200),
       distinctUntilChanged(),
-      map(term =>
-        term.length < 2
-          ? []
-          : this._ldapUsers.map((user: LdapUser) => `${user.fullName} (${user.uid})`).filter(v => v.toLowerCase().indexOf(term.toLowerCase()) > -1)
-      )
+      map(term => (term.length < 2 ? [] : this._ldapUsers.filter(v => v.ldapSearchString.toLowerCase().indexOf(term.toLowerCase()) > -1)))
     );
 
+  public formatter = (x: LdapUser) => x.ldapSearchString;
+
   public setLdapUidValue(event: any): void {
     // set the value only if exists - take only the username from the rounded bruckets
-    this.appState$.dispatch(
-      new SetValueAction(this.internalPersonDetailsCurrentFormState.controls.uid.id, event == null ? null : event.item.match(/\(([^)]+)\)/)[1])
-    );
+    this.appState$.dispatch(new SetValueAction(this.internalPersonDetailsCurrentFormState.controls.uid.id, event == null ? null : event.item.uid));
+    this.appState$.dispatch(new SetValueAction(this.internalPersonDetailsCurrentFormState.controls.firstName.id, event == null ? null : event.item.firstName));
+    this.appState$.dispatch(new SetValueAction(this.internalPersonDetailsCurrentFormState.controls.lastName.id, event == null ? null : event.item.lastName));
+  }
+
+  removeCurrentMainAddress(): void {
+    this._mainAddress.isMainAddress = false;
+    this.appState$.dispatch(internalPersonActions.persistAddressDetail({ payload: this._mainAddress }));
   }
 
   private _checkIfMainAddressExist(addresses: Array<Address>) {
     for (let i = 0; i < addresses.length; i++) {
       const address = addresses[i];
       if (address.isMainAddress) {
+        this._mainAddress = address;
         this.existMainAddress = true;
         break;
       }
+      this._mainAddress = address;
       this.existMainAddress = false;
     }
   }
 
-  private _checkIfCurrentAddressIsMainAddress(address: Address) {
-    this.isCurrentAddressMainAddress = address.isMainAddress ? true : false;
+  private _checkIfCurrentAddressIsMainAddress(address: Address): void {
+    this.isCurrentAddressMainAddress = address.isMainAddress;
   }
 }
diff --git a/src/app/pages/persons/persons.routing.module.ts b/src/app/pages/persons/persons.routing.module.ts
index a5eb379..8b1bfd8 100644
--- a/src/app/pages/persons/persons.routing.module.ts
+++ b/src/app/pages/persons/persons.routing.module.ts
@@ -20,7 +20,7 @@
 
 const PATH = Globals.PATH;
 
-const addNewPersonRoutes: Routes = [
+const editPersonRoutes: Routes = [
   {
     path: `${PATH.PERSONS}/${PATH.EXTERNAL}/:contactId`,
     component: ExternalPersonDetailsComponent,
@@ -37,7 +37,7 @@
   }
 ];
 
-const editPersonRoutes: Routes = [
+const addNewPersonRoutes: Routes = [
   {
     path: `${PATH.PERSONS}/${PATH.EXTERNAL}/${PATH.NEW}`,
     component: ExternalPersonDetailsComponent,
@@ -55,7 +55,7 @@
 ];
 
 @NgModule({
-  imports: [RouterModule.forChild([...addNewPersonRoutes,...editPersonRoutes])],
+  imports: [RouterModule.forChild([...editPersonRoutes,...addNewPersonRoutes])],
   exports: [RouterModule]
 })
 export class PersonsRoutingModule { }
diff --git a/src/app/shared/components/cell-renderer/date-cell-renderer/date-cell-renderer.component.spec.ts b/src/app/shared/components/cell-renderer/date-cell-renderer/date-cell-renderer.component.spec.ts
index 666a261..455d80d 100644
--- a/src/app/shared/components/cell-renderer/date-cell-renderer/date-cell-renderer.component.spec.ts
+++ b/src/app/shared/components/cell-renderer/date-cell-renderer/date-cell-renderer.component.spec.ts
@@ -10,39 +10,31 @@
  *
  * SPDX-License-Identifier: EPL-2.0
  ********************************************************************************/
-import { ComponentFixture, TestBed } from '@angular/core/testing';
-
-import { DateCellRendererComponent } from './date-cell-renderer.component';
-import { NO_ERRORS_SCHEMA } from '@angular/core';
+import { DateCellRendererComponent } from '@shared/components/cell-renderer/date-cell-renderer/date-cell-renderer.component';
+import { ICellRendererParams } from 'ag-grid-community';
 
 describe('DateCellRendererComponent', () => {
   let component: DateCellRendererComponent;
-  let fixture: ComponentFixture<DateCellRendererComponent>;
 
   beforeEach(() => {
-    TestBed.configureTestingModule({
-      schemas: [NO_ERRORS_SCHEMA],
-      declarations: [DateCellRendererComponent],
-    });
-
-    fixture = TestBed.createComponent(DateCellRendererComponent);
-    component = fixture.componentInstance;
-    fixture.detectChanges();
+    component = new DateCellRendererComponent();
   });
 
   it('should create', () => {
-    expect(component).toBeDefined();
     expect(component).toBeTruthy();
   });
 
-  it('agInit sets date to value property of its parameter', () => {
-    component.agInit({ value: 'test' });
-    expect(component.date).toEqual('test');
+  it('should set date / isDate when calling agInit with Date param', () => {
+    let p: ICellRendererParams = { value: new Date() } as any;
+    component.agInit(p);
+    expect(component.date).toBe(p.value);
+    expect(component.isDate).toBeTruthy();
   });
 
-  it('refresh sets date to value property of its parameter', () => {
-    const returnValue = component.refresh({ value: 'test' });
-    expect(component.date).toEqual('test');
-    expect(returnValue).toBe(true);
+  it('should set date / isDate when calling refesh with Date param', () => {
+    let p: ICellRendererParams = { value: new Date() } as any;
+    component.refresh(p);
+    expect(component.date).toBe(p.value);
+    expect(component.isDate).toBeTruthy();
   });
 });
diff --git a/src/app/shared/components/expandable/expandable.component.html b/src/app/shared/components/expandable/expandable.component.html
index d952ee5..ce4d641 100644
--- a/src/app/shared/components/expandable/expandable.component.html
+++ b/src/app/shared/components/expandable/expandable.component.html
@@ -12,15 +12,15 @@
 ********************************************************************************/ -->
 <div class="panel panel-default" style="width:100%;">
   <div class="panel-heading">
-    <h4 class="panel-title">
-      <a data-toggle="collapse">
-        <em *ngIf="isExpandedStatus" class="fa fa-chevron-up" aria-hidden="true"></em>
-        <em *ngIf="!isExpandedStatus" class="fa fa-chevron-down" aria-hidden="true"></em>
-      </a>
-      <a data-toggle="collapse" href="#{{ collapseId }}" (click)="isExpandedStatus = !isExpandedStatus">
+    <a data-toggle="collapse" style="width: 100%;" href="#{{ collapseId }}" (click)="isExpandedStatus = !isExpandedStatus">
+      <h4 class="panel-title">
+        <span>
+          <em class="fa" [ngClass]="isExpandedStatus ? 'fa-chevron-up' : 'fa-chevron-down'"></em>
+        </span>
+
         <ng-content select="[header]"></ng-content>
-      </a>
-    </h4>
+      </h4>
+    </a>
   </div>
   <div *ngIf="isExpandedStatus" id="{{ collapseId }}" class="collapse5 panel-collapse collapse in" [ngClass]="{ in: !isStatusCollapsed }">
     <ng-content class="bodyContent" select="[body]"></ng-content>
diff --git a/src/app/shared/constants/globals.ts b/src/app/shared/constants/globals.ts
index 8cd5656..e4ff86c 100644
--- a/src/app/shared/constants/globals.ts
+++ b/src/app/shared/constants/globals.ts
@@ -15,7 +15,7 @@
     static INTERNAL_PERSON = 'interne Person';
     static EXTERNAL_PERSON = 'externe Person';
     static COMPANY = 'Unternehmen';
-    static CONTACT_PERSON = 'Kontaktperson';
+    static CONTACT_PERSON = 'Ansprechpartner';
     static UNKNOWN = 'unbekannter Kontakttyp';
   };
 
diff --git a/src/app/shared/directives/agGrid/server-side.directive.spec.ts b/src/app/shared/directives/agGrid/server-side.directive.spec.ts
index 80ec6da..da7ebd2 100644
--- a/src/app/shared/directives/agGrid/server-side.directive.spec.ts
+++ b/src/app/shared/directives/agGrid/server-side.directive.spec.ts
@@ -10,7 +10,7 @@
  *
  * SPDX-License-Identifier: EPL-2.0
  ********************************************************************************/
-import { ServerSideDirective } from './server-side.directive';
+import { ServerSideDirective } from '@shared/directives/agGrid/server-side.directive';
 
 describe('ServerSideDirective', () => {
   it('should create an instance', () => {
diff --git a/src/app/shared/directives/agGrid/server-side.directive.ts b/src/app/shared/directives/agGrid/server-side.directive.ts
index b8da780..ce44135 100644
--- a/src/app/shared/directives/agGrid/server-side.directive.ts
+++ b/src/app/shared/directives/agGrid/server-side.directive.ts
@@ -13,11 +13,11 @@
  ********************************************************************************/
 import { PaginatorComponent } from '@shared/components/paginator/paginator.component';
 import { PageEvent } from '@shared/models/PageEvent';
-import { PageModel } from './../../models/page/page.model';
+import { PageModel } from '@shared/models/page/page.model';
 import { AgGridAngular } from 'ag-grid-angular';
-import { take, map } from 'rxjs/operators';
+import { map } from 'rxjs/operators';
 import { ServerSideModel } from '@shared/models/server-side.model';
-import { Directive, Input, AfterViewInit, ComponentFactoryResolver, ViewContainerRef, ComponentFactory, OnInit, Output } from '@angular/core';
+import { Directive, Input, ComponentFactoryResolver, ViewContainerRef, ComponentFactory, OnInit, Output } from '@angular/core';
 import { Store, ActionsSubject } from '@ngrx/store';
 
 import * as store from '@shared/store';
@@ -37,6 +37,7 @@
   host: {},
 })
 export class ServerSideDirective implements OnInit {
+  private _currentPageNumber: number;
   private _queryParameter: any;
 
   private _matPaginator: PaginatorComponent;
@@ -50,12 +51,12 @@
   @Input()
   public set queryParameter(query: any) {
     if (!!query) {
+      this._currentPageNumber = 1;
       this.appState$.dispatch(
         this.serverside.loadAction({
           payload: {
             queryParameter: query,
             pageSize: this.serverside.pageSize,
-            pageNumber: this.serverside.pageNumber,
           } as PageRequestInterface,
         })
       );
@@ -85,6 +86,7 @@
    * @memberof ServerSideDirective
    */
   ngOnInit() {
+    this._currentPageNumber = this.serverside.pageNumber;
     this._actionsSubject
       .pipe(
         ofType(this.serverside.successAction.type),
@@ -99,13 +101,13 @@
           this._matPaginator.totalPages = pagedItem.totalPages;
         }
 
+        this._matPaginator.currrentPageNumber = this._currentPageNumber;
         this._matPaginator.length = pagedItem.totalElements;
         this._matPaginator.pageSize = pagedItem.pageable.pageSize || 1;
         this._matPaginator.hidePageSize = false;
         this._matPaginator.page.subscribe((selectedpage: PageEvent) => {
           this._retrievePage(selectedpage);
         });
-        this._matPaginator.currrentPageNumber = this.serverside.pageNumber;
         if (!!this._agGrid.api) {
           this._agGrid.api.setRowData(pagedItem.content);
         } else {
@@ -123,6 +125,7 @@
    * @memberof ServerSideDirective
    */
   private _retrievePage(event?: PageEvent) {
+    this._currentPageNumber = event.pageIndex;
     this.currentPageNumber.emit(event.pageIndex);
     this.appState$.dispatch(
       this.serverside.loadAction({
diff --git a/src/app/shared/models/users/ldap-user.model.ts b/src/app/shared/models/users/ldap-user.model.ts
index 02ffb42..42f1d0a 100644
--- a/src/app/shared/models/users/ldap-user.model.ts
+++ b/src/app/shared/models/users/ldap-user.model.ts
@@ -26,4 +26,8 @@
       .filter(property => this.hasOwnProperty(property))
       .forEach(property => (this[property] = data[property]));
   }
+
+  get ldapSearchString(): string {
+    return this.firstName + ' ' + this.lastName + ' (' + this.uid + ')';
+  }
 }
diff --git a/src/app/shared/sandbox/base-list.sandbox.ts b/src/app/shared/sandbox/base-list.sandbox.ts
index bc4440a..078643b 100644
--- a/src/app/shared/sandbox/base-list.sandbox.ts
+++ b/src/app/shared/sandbox/base-list.sandbox.ts
@@ -14,7 +14,7 @@
 import { ServerSideModel } from '@shared/models/server-side.model';
 
 export abstract class BaseListSandbox extends BaseSandbox {
-  protected pageSize: number = 10;
+  protected pageSize: number = 4;
   public serversideModel: ServerSideModel = new ServerSideModel();
 
   public setCurrentPageNumber(pageNumber: number): void {
diff --git a/src/app/shared/store/effects/admin/address-types.effect.spec.ts b/src/app/shared/store/effects/admin/address-types.effect.spec.ts
index 7731497..28fa85c 100644
--- a/src/app/shared/store/effects/admin/address-types.effect.spec.ts
+++ b/src/app/shared/store/effects/admin/address-types.effect.spec.ts
@@ -19,7 +19,6 @@
 import { Store } from '@ngrx/store';
 
 describe('AddressTypes Effects', () => {
-
   let effects: AddressTypesEffects;
   let actions$: Subject<any>;
   let apiClient: AddressTypesApiClient;
@@ -32,10 +31,10 @@
       getAddressTypeDetails() {},
       putAddressType() {},
       postAddressType() {},
-      deleteAddressType() {}
+      deleteAddressType() {},
     } as any;
     store = {
-      dispatch() {}
+      dispatch() {},
     } as any;
     actions$ = new Subject();
     effects = new AddressTypesEffects(actions$, apiClient, store);
@@ -45,71 +44,69 @@
     expect(effects).toBeTruthy();
   });
 
-  it('should equal loadAddressTypesSuccess after getAddressTypes', (done) => {
-    apiResponse =  [new AddressType({id: "1"})];
+  it('should equal loadAddressTypesSuccess after getAddressTypes', done => {
+    apiResponse = [new AddressType({ id: '1' })];
     spyOn(apiClient, 'getAddressTypes').and.returnValue(of(apiResponse));
     effects.getAddressTypes$.pipe(take(1)).subscribe(result => {
-      expect(result).toEqual(addressTypesActions.loadAddressTypesSuccess({payload: apiResponse}));
+      expect(result).toEqual(addressTypesActions.loadAddressTypesSuccess({ payload: apiResponse }));
     });
     done();
     actions$.next(addressTypesActions.loadAddressTypes());
   });
 
-  it('should equal loadAddressTypesFail after getAddressType Error', (done) => {
+  it('should equal loadAddressTypesFail after getAddressType Error', done => {
     spyOn(apiClient, 'getAddressTypes').and.returnValue(throwError('x'));
     effects.getAddressTypes$.pipe(take(1)).subscribe(result => {
-      expect(result).toEqual(addressTypesActions.loadAddressTypesFail({payload: 'x'}));
+      expect(result).toEqual(addressTypesActions.loadAddressTypesFail({ payload: 'x' }));
     });
     done();
     actions$.next(addressTypesActions.loadAddressTypes());
   });
 
-  it('should equal loadAddressTypeSuccess after getAddressType', (done) => {
-    apiResponse =  new AddressType({id: "1"});
+  it('should equal loadAddressTypeSuccess after getAddressType', done => {
+    apiResponse = new AddressType({ id: '1' });
     spyOn(apiClient, 'getAddressTypeDetails').and.returnValue(of(apiResponse));
     effects.getAddressType$.pipe(take(1)).subscribe(result => {
-      expect(result).toEqual(addressTypesActions.loadAddressTypeSuccess({payload: apiResponse}));
+      expect(result).toEqual(addressTypesActions.loadAddressTypeSuccess({ payload: apiResponse }));
     });
     done();
-    actions$.next(addressTypesActions.loadAddressType({payload: "1"}));
+    actions$.next(addressTypesActions.loadAddressType({ payload: '1' }));
   });
 
-  it('should equal loadAddressTypeFail after getAddressType Error', (done) => {
+  it('should equal loadAddressTypeFail after getAddressType Error', done => {
     spyOn(apiClient, 'getAddressTypeDetails').and.returnValue(throwError('x'));
     effects.getAddressType$.pipe(take(1)).subscribe(result => {
-      expect(result).toEqual(addressTypesActions.loadAddressTypeFail({payload: 'x'}));
+      expect(result).toEqual(addressTypesActions.loadAddressTypeFail({ payload: 'x' }));
     });
     done();
-    actions$.next(addressTypesActions.loadAddressType({payload: "1"}));
+    actions$.next(addressTypesActions.loadAddressType({ payload: '1' }));
   });
 
-  it('should equal saveAddressTypeSuccess after saveAddressType', (done) => {
-    apiResponse =  new AddressType({id: "1"});
+  it('should equal saveAddressTypeSuccess after saveAddressType', done => {
+    apiResponse = new AddressType({ id: '1' });
     spyOn(apiClient, 'putAddressType').and.returnValue(of(apiResponse));
     effects.saveAddressType$.pipe(take(1)).subscribe(result => {
-      expect(result).toEqual(addressTypesActions.saveAddressTypeSuccess({payload: new AddressType({id: "1"})}));
+      expect(result).toEqual(addressTypesActions.saveAddressTypeSuccess({ payload: new AddressType({ id: '1' }) }));
     });
     done();
-    actions$.next(addressTypesActions.saveAddressType({payload: new AddressType({id: "1"})}));
+    actions$.next(addressTypesActions.saveAddressType({ payload: new AddressType({ id: '1' }) }));
   });
 
-  it('should equal saveAddressTypeFail after saveAddressType Error', (done) => {
+  it('should equal saveAddressTypeFail after saveAddressType Error', done => {
     spyOn(apiClient, 'putAddressType').and.returnValue(throwError('x'));
     effects.saveAddressType$.pipe(take(1)).subscribe(result => {
-      expect(result).toEqual(addressTypesActions.saveAddressTypeFail({payload: 'x'}));
+      expect(result).toEqual(addressTypesActions.saveAddressTypeFail({ payload: 'x' }));
     });
     done();
-    actions$.next(addressTypesActions.saveAddressType({payload: new AddressType({id: "1"})}));
+    actions$.next(addressTypesActions.saveAddressType({ payload: new AddressType({ id: '1' }) }));
   });
 
-  it('should equal deleteAddressTypeSuccess after deleteAddressType', (done) => {
-    apiResponse =  new AddressType({id: "1"});
+  it('should equal deleteAddressTypeSuccess after deleteAddressType', done => {
     spyOn(apiClient, 'deleteAddressType').and.returnValue(of(null));
     effects.deleteAddressType$.pipe(take(1)).subscribe(result => {
       expect(result).toEqual(addressTypesActions.deleteAddressTypeSuccess());
     });
     done();
-    actions$.next(addressTypesActions.deleteAddressType({payload: "1"}));
+    actions$.next(addressTypesActions.deleteAddressType({ payload: '1' }));
   });
-
 });
diff --git a/src/app/shared/store/effects/user-module-assignment/user-module-assignment.effect.spec.ts b/src/app/shared/store/effects/user-module-assignment/user-module-assignment.effect.spec.ts
new file mode 100644
index 0000000..1d35bc3
--- /dev/null
+++ b/src/app/shared/store/effects/user-module-assignment/user-module-assignment.effect.spec.ts
@@ -0,0 +1,85 @@
+/********************************************************************************
+ * 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 { Subject, of, throwError } from 'rxjs';
+import { Store } from '@ngrx/store';
+import { take } from 'rxjs/operators';
+import { UserModuleAssignmentEffect } from '@shared/store/effects/user-module-assignment/user-module-assignment.effect';
+import { UserModuleAssignmentApiClient } from '@shared/components/list-details-view/user-module-assignment/user-module-assignment-api-client';
+import { UserModuleAssignment } from '@shared/models';
+import * as userModuleAssignmentActions from '@shared/store/actions/user-module-assignment/user-module-assignment.action';
+
+describe('UserModuleAssignment Effects', () => {
+  let effects: UserModuleAssignmentEffect;
+  let actions$: Subject<any>;
+  let apiClient: UserModuleAssignmentApiClient;
+  let store: Store<any>;
+  let apiResponse: any = null;
+
+  beforeEach(() => {
+    apiClient = {
+      getUserModuleAssignments() {},
+      getUserModuleAssignmentsDetails() {},
+      postUserModuleAssignmentDetails() {},
+      putUserModuleAssignmentDetails() {},
+      deleteUserModuleAssignment() {},
+    } as any;
+    store = {
+      dispatch() {},
+    } as any;
+    actions$ = new Subject();
+    effects = new UserModuleAssignmentEffect(actions$, apiClient, store);
+  });
+
+  it('should be truthy', () => {
+    expect(effects).toBeTruthy();
+  });
+
+  it('should equal loadUserModuleAssignmentsSuccess after getUserModuleAssignments', done => {
+    apiResponse = [new UserModuleAssignment({ id: '1' })];
+    spyOn(apiClient, 'getUserModuleAssignments').and.returnValue(of(apiResponse));
+    effects.getUserModuleAssignments$.pipe(take(1)).subscribe(result => {
+      expect(result).toEqual(userModuleAssignmentActions.loadUserModuleAssignmentsSuccess({ payload: apiResponse }));
+    });
+    done();
+    actions$.next(userModuleAssignmentActions.loadUserModuleAssignments({ payload: '1' }));
+  });
+
+  it('should equal loadUserModuleAssignmentDetailsSuccess after getUserModuleAssignmentsDetails', done => {
+    apiResponse = new UserModuleAssignment({ id: '1' });
+    spyOn(apiClient, 'getUserModuleAssignmentsDetails').and.returnValue(of(apiResponse));
+    effects.getUserModuleAssignmentDetails$.pipe(take(1)).subscribe(result => {
+      expect(result).toEqual(userModuleAssignmentActions.loadUserModuleAssignmentDetailsSuccess({ payload: apiResponse }));
+    });
+    done();
+    actions$.next(userModuleAssignmentActions.loadUserModuleAssignmentDetails({ payload: new UserModuleAssignment() }));
+  });
+
+  it('should equal persistUserModuleAssignmentDetailSuccess after putUserModuleAssignmentDetails', done => {
+    apiResponse = new UserModuleAssignment({ id: '1', contactId: '2' });
+    spyOn(apiClient, 'putUserModuleAssignmentDetails').and.returnValue(of(apiResponse));
+    effects.persistUserModuleAssignment$.pipe(take(1)).subscribe(result => {
+      expect(result).toEqual(userModuleAssignmentActions.persistUserModuleAssignmentDetailSuccess({ payload: apiResponse }));
+    });
+    done();
+    actions$.next(userModuleAssignmentActions.persistUserModuleAssignmentDetail({ payload: new UserModuleAssignment({ id: '1', contactId: '2' }) }));
+  });
+
+  it('should equal deleteUserModuleAssignmentSuccess after postUserModuleAssignmentDetails', done => {
+    spyOn(apiClient, 'deleteUserModuleAssignment').and.returnValue(of(null));
+    effects.deleteUserModuleAssignment$.pipe(take(1)).subscribe(result => {
+      expect(result).toEqual(userModuleAssignmentActions.deleteUserModuleAssignmentSuccess());
+    });
+    done();
+    actions$.next(userModuleAssignmentActions.deleteUserModuleAssignment({ payload: new UserModuleAssignment({ id: '1', contactId: '2' }) }));
+  });
+});
diff --git a/src/app/shared/store/effects/user-module-assignment/user-module-assignment.effect.ts b/src/app/shared/store/effects/user-module-assignment/user-module-assignment.effect.ts
index 389fa75..eeec238 100644
--- a/src/app/shared/store/effects/user-module-assignment/user-module-assignment.effect.ts
+++ b/src/app/shared/store/effects/user-module-assignment/user-module-assignment.effect.ts
@@ -84,7 +84,7 @@
   /**
    * delete user module Assignment
    */
-  deleteAddress$: any = createEffect(() =>
+  deleteUserModuleAssignment$: any = createEffect(() =>
     this._actions$.pipe(
       ofType(userModuleAssignmentActions.deleteUserModuleAssignment),
       map(action => action['payload']),