Merge branch 'DEVELOP' of ssh://git.eclipse.org:29418/openk-usermodules/org.eclipse.openk-usermodules.contactBaseData.frontend into KON-37-rechte-rollen
diff --git a/i18n/contacts.de.json b/i18n/contacts.de.json
index dbe91b2..2fc1b31 100644
--- a/i18n/contacts.de.json
+++ b/i18n/contacts.de.json
@@ -19,7 +19,11 @@
     "Department": "Abteilung",
     "CommunicationsDataList": "Kommunikationskanäle",
     "ContactPersonList": "Ansprechpartner",
-    "CommunicationsDataList": "Kommunikationskanäle",
-    "ModuleAssignment": "Modulzuordnung"
+    "ModuleAssignment": "Modulzuordnung",
+    "AllModuleAssignments": "Alle Modulzuordnungen",
+    "WithoutModuleAssignment": "Keine Modulzuordnung",
+    "DSGVO-advanced-filter": "DSGVO - Filtererweiterung",
+    "DSGVO-advanced-filter-deletion-lock-exceeded": "Filterung nach Kontakten mit abgelaufener Löschsperre",
+    "DSGVO-advanced-filter-expiring-data-in-past": "Filterung nach Kontakten mit überschrittenem Ablaufdatum"
   }
 }
diff --git a/i18n/general.de.json b/i18n/general.de.json
index 4d1ea25..b4f5024 100644
--- a/i18n/general.de.json
+++ b/i18n/general.de.json
@@ -30,9 +30,11 @@
     "Deletion": "Möchten Sie den Datensatz wirklich löschen?",
     "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.",
     "Action": {
       "delete": "Datensatz löschen",
-      "edit": "Änderung verwerfen"
+      "edit": "Änderung verwerfen",
+      "anonymize": "Kontakt anonymisieren"
     }
   },
   "Tools": "Tools",
diff --git a/package.json b/package.json
index 602c2b6..67da642 100644
--- a/package.json
+++ b/package.json
@@ -17,9 +17,8 @@
     "sy-post-build": "node hooks/post-build.js",
     "sy-build": "npm run sy-pre-build && ng build --base-href /contactdatabase/ --prod --aot && npm run sy-post-build",
     "sy-build-noprod": "npm run sy-pre-build && ng build --base-href /contactdatabase/ && npm run sy-post-build",
-    "start-in-docker": "npm run sy-pre-start && ng serve --optimization=false --vendor-chunk --common-chunk --host=0.0.0.0 --disableHostCheck=true --proxy-config proxy-docker.conf.json",    
-	"start-in-docker-unsecure": "npm run sy-pre-start && ng serve --optimization=false --vendor-chunk --common-chunk --host=0.0.0.0 --disableHostCheck=true --proxy-config proxy-docker-unsecure.conf.json"
-
+    "start-in-docker": "npm run sy-pre-start && ng serve --optimization=false --vendor-chunk --common-chunk --host=0.0.0.0 --disableHostCheck=true --proxy-config proxy-docker.conf.json",
+    "start-in-docker-unsecure": "npm run sy-pre-start && ng serve --optimization=false --vendor-chunk --common-chunk --host=0.0.0.0 --disableHostCheck=true --proxy-config proxy-docker-unsecure.conf.json"
   },
   "private": true,
   "dependencies": {
diff --git a/src/app/pages/company/company-details/company-details.component.html b/src/app/pages/company/company-details/company-details.component.html
index 547ca31..0833496 100644
--- a/src/app/pages/company/company-details/company-details.component.html
+++ b/src/app/pages/company/company-details/company-details.component.html
@@ -79,10 +79,14 @@
         </div>
 
         <!-- buttons -->
-        <button *visibleByRight type="button" class="btn btn-success" (click)="companyDetailsSandBox.persistCompany()">{{ 'SaveBtn' | translate }}</button>
-        <button type="button" class="btn btn-primary cancel-button" routerLink="/overview">
-          {{ 'CancelBtn' | translate }}
-        </button>
+        <div class="row justify-content-between">
+          <div>
+            <button *visibleByRight type="button" class="btn btn-success company-buttons" (click)="companyDetailsSandBox.persistCompany()">{{ 'SaveBtn' | translate }}</button>
+            <button type="button" class="btn btn-primary cancel-button company-buttons" routerLink="/overview">
+              {{ 'CancelBtn' | translate }}
+            </button>
+          </div>
+        </div>
       </div>
     </form>
 
diff --git a/src/app/pages/company/company-details/company-details.component.scss b/src/app/pages/company/company-details/company-details.component.scss
index 7f6bfc9..35a3e5c 100644
--- a/src/app/pages/company/company-details/company-details.component.scss
+++ b/src/app/pages/company/company-details/company-details.component.scss
@@ -10,8 +10,8 @@
  *
  * SPDX-License-Identifier: EPL-2.0
  ********************************************************************************/
-.btn-success {
-  margin-right: 16px;
+.company-buttons {
+  margin: 16px;
 }
 .expandable-body-container {
   display: flex;
diff --git a/src/app/pages/company/company-details/contact-person-details/communications-data-details/communications-data-details.component.spec.ts b/src/app/pages/company/company-details/contact-person-details/communications-data-details/communications-data-details.component.spec.ts
index f4c15c2..f27366b 100644
--- a/src/app/pages/company/company-details/contact-person-details/communications-data-details/communications-data-details.component.spec.ts
+++ b/src/app/pages/company/company-details/contact-person-details/communications-data-details/communications-data-details.component.spec.ts
@@ -11,27 +11,26 @@
  * SPDX-License-Identifier: EPL-2.0
  ********************************************************************************/
 import { async } from '@angular/core/testing';
-import { CompanyCommunicationsDataDetailsComponent } from '@pages/company/company-details/communications-data-details/communications-data-details.component';
+import { ContactPersonCommunicationsDataDetailsComponent } from '@pages/company/company-details/contact-person-details/communications-data-details/communications-data-details.component';
 
-describe('CompanyCommunicationsDataDetailsComponent', () => {
-  let component: CompanyCommunicationsDataDetailsComponent;
-  let companySandbox: any;
+describe('ContactPersonCommunicationsDataDetailsComponent', () => {
+  let component: ContactPersonCommunicationsDataDetailsComponent;
+  let sandbox: any;
   let communicationTypesSandbox: any;
 
   beforeEach(async(() => {
-    companySandbox = {
+    sandbox = {
       registerCommunicationsDataEvents() {},
       registerCompanyEvents() {},
       endSubscriptions() {},
       clearCommunicationsData() {},
     } as any;
 
-    communicationTypesSandbox = {
-    } as any;
+    communicationTypesSandbox = {} as any;
   }));
 
   beforeEach(() => {
-    component = new CompanyCommunicationsDataDetailsComponent(companySandbox, communicationTypesSandbox);
+    component = new ContactPersonCommunicationsDataDetailsComponent(sandbox, communicationTypesSandbox);
   });
 
   it('should create', () => {
@@ -39,8 +38,8 @@
   });
 
   it('should call registerCommunicationsDataEvents and clearCommunicationsData onInit', () => {
-    const spy1 = spyOn(companySandbox, 'registerCommunicationsDataEvents');
-    const spy2 = spyOn(companySandbox, 'clearCommunicationsData');
+    const spy1 = spyOn(sandbox, 'registerCommunicationsDataEvents');
+    const spy2 = spyOn(sandbox, 'clearCommunicationsData');
     component.ngOnInit();
     expect(spy1).toHaveBeenCalled();
     expect(spy2).toHaveBeenCalled();
diff --git a/src/app/pages/company/company-details/contact-person-details/communications-data-list/communications-data-list.component.spec.ts b/src/app/pages/company/company-details/contact-person-details/communications-data-list/communications-data-list.component.spec.ts
index 61ecbba..abb265b 100644
--- a/src/app/pages/company/company-details/contact-person-details/communications-data-list/communications-data-list.component.spec.ts
+++ b/src/app/pages/company/company-details/contact-person-details/communications-data-list/communications-data-list.component.spec.ts
@@ -11,15 +11,15 @@
  * SPDX-License-Identifier: EPL-2.0
  ********************************************************************************/
 import { async } from '@angular/core/testing';
-import { CompanyCommunicationsDataListComponent } from '@pages/company/company-details/communications-data-list/communications-data-list.component';
+import { ContactPersonCommunicationsDataListComponent } from '@pages/company/company-details/contact-person-details/communications-data-list/communications-data-list.component';
 import { of } from 'rxjs/observable/of';
 
-describe('CompanyCommunicationsDataListComponent', () => {
-  let component: CompanyCommunicationsDataListComponent;
-  let companySandbox: any;
+describe('ContactPersonCommunicationsDataListComponent', () => {
+  let component: ContactPersonCommunicationsDataListComponent;
+  let contactPersonDetailsSandbox: any;
 
   beforeEach(async(() => {
-    companySandbox = {
+    contactPersonDetailsSandbox = {
       registerCommunicationsDataEvents() {},
       registerCompanyEvents() {},
       endSubscriptions() {},
@@ -29,7 +29,7 @@
   }));
 
   beforeEach(() => {
-    component = new CompanyCommunicationsDataListComponent(companySandbox);
+    component = new ContactPersonCommunicationsDataListComponent(contactPersonDetailsSandbox);
   });
 
   it('should create', () => {
@@ -53,7 +53,7 @@
   });
 
   it('should deleteCommunicationsData if BusEvents is delete', () => {
-    const spy = spyOn(companySandbox, 'deleteCommunicationsData');
+    const spy = spyOn(contactPersonDetailsSandbox, 'deleteCommunicationsData');
     const event: any = { type: 'delete', data: { id: 'id' } };
     component.gridOptions.context.eventSubject = of(event);
     component.ngOnInit();
@@ -62,7 +62,7 @@
   });
 
   it('should call newCommunicationsData in response to createNewCommunicationsDataForm', () => {
-    const spy = spyOn(companySandbox, 'newCommunicationsData');
+    const spy = spyOn(contactPersonDetailsSandbox, 'newCommunicationsData');
     const spyEmit = spyOn(component.createNewCompany, 'emit');
     component.createNewCommunicationsDataForm();
 
diff --git a/src/app/pages/company/company-details/contact-person-details/contact-person-details.component.html b/src/app/pages/company/company-details/contact-person-details/contact-person-details.component.html
index 57c0d23..a8ed1a0 100644
--- a/src/app/pages/company/company-details/contact-person-details/contact-person-details.component.html
+++ b/src/app/pages/company/company-details/contact-person-details/contact-person-details.component.html
@@ -106,17 +106,24 @@
         </div>
 
         <!-- buttons -->
-        <button *visibleByRight type="button" class="btn btn-success" (click)="contactPersonDetailSandbox.saveContactPersonDetails()">
-          {{ 'SaveBtn' | translate }}
-        </button>
+        <div class="row justify-content-between">
+          <div>
+            <button *visibleByRight type="button" class="btn btn-success person-buttons" (click)="contactPersonDetailSandbox.saveContactPersonDetails()">
+              {{ 'SaveBtn' | translate }}
+            </button>
 
-        <button type="button" class="btn btn-primary cancel-button" (click)="contactPersonDetailSandbox.navigateBackToCompany()">
-          {{ 'ContactPerson.CompanyBtn' | translate }}
-        </button>
+            <button type="button" class="btn btn-primary person-buttons" (click)="contactPersonDetailSandbox.navigateBackToCompany()">
+              {{ 'ContactPerson.CompanyBtn' | translate }}
+            </button>
 
-        <button type="button" class="btn btn-primary cancel-button" routerLink="/overview">
-          {{ 'ContactPerson.ContactOverviewBtn' | translate }}
-        </button>
+            <button type="button" class="btn btn-primary person-buttons" routerLink="/overview">
+              {{ 'ContactPerson.ContactOverviewBtn' | translate }}
+            </button>
+          </div>
+          <div class="person-buttons" *ngIf="contactPersonDetailSandbox.contactPersonContactId">
+            <app-anonymizer [contactId]="contactPersonDetailSandbox.contactPersonContactId"></app-anonymizer>
+          </div>
+        </div>
       </div>
     </form>
 
diff --git a/src/app/pages/company/company-details/contact-person-details/contact-person-details.component.scss b/src/app/pages/company/company-details/contact-person-details/contact-person-details.component.scss
index 4cdef80..9de3904 100644
--- a/src/app/pages/company/company-details/contact-person-details/contact-person-details.component.scss
+++ b/src/app/pages/company/company-details/contact-person-details/contact-person-details.component.scss
@@ -10,8 +10,8 @@
  *
  * SPDX-License-Identifier: EPL-2.0
  ********************************************************************************/
-.cancel-button {
-  margin-right: 16px;
+.person-buttons {
+  margin: 16px;
 }
 .expandable-body-container {
   display: flex;
diff --git a/src/app/pages/company/company-details/contact-person-details/contact-person-details.resolver.spec.ts b/src/app/pages/company/company-details/contact-person-details/contact-person-details.resolver.spec.ts
new file mode 100644
index 0000000..a503008
--- /dev/null
+++ b/src/app/pages/company/company-details/contact-person-details/contact-person-details.resolver.spec.ts
@@ -0,0 +1,81 @@
+/********************************************************************************
+ * 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 { ContactPersonDetailsResolver } from '@pages/company/company-details/contact-person-details/contact-person-details.resolver';
+
+describe('CompanyDetailsResolver', () => {
+  let component: ContactPersonDetailsResolver;
+  let contactPersonDetailsSandbox: any;
+  let salutationsSandbox: any;
+  let personTypesSandbox: any;
+  let communicationTypesSandbox: any;
+  let addressTypesSandbox: any;
+  let userModuleAssignmentSandbox: any;
+
+  beforeEach(() => {
+    contactPersonDetailsSandbox = {
+      companyContactId: null,
+      loadContactPersonDetails() {},
+      loadContactPersonAddresses() {},
+      newContactPerson() {},
+    } as any;
+
+    communicationTypesSandbox = {
+      loadCommunicationTypes() {},
+    } as any;
+
+    userModuleAssignmentSandbox = {
+      loadFilteredUserModuleTypes() {},
+      loadUserModuleAssignments() {},
+    } as any;
+
+    addressTypesSandbox = {
+      loadAddressTypes() {},
+    } as any;
+
+    salutationsSandbox = {
+      loadSalutations() {},
+    } as any;
+
+    personTypesSandbox = {
+      loadPersonTypes() {},
+    } as any;
+  });
+
+  beforeEach(() => {
+    component = new ContactPersonDetailsResolver(
+      contactPersonDetailsSandbox,
+      salutationsSandbox,
+      personTypesSandbox,
+      communicationTypesSandbox,
+      addressTypesSandbox,
+      userModuleAssignmentSandbox
+    );
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+
+  it('should ccc', () => {
+    let ar: any = { params: { contactId: 'ID' } };
+    component.resolve(ar);
+    expect(contactPersonDetailsSandbox.companyContactId).toBe(ar.params.contactId);
+  });
+
+  it('should call clear if create a new contact-person', () => {
+    const spy = spyOn(contactPersonDetailsSandbox, 'newContactPerson');
+    let ar: any = { params: { contactPersonId: undefined } };
+    component.resolve(ar);
+    expect(spy).toHaveBeenCalled();
+  });
+});
diff --git a/src/app/pages/contacts/contacts-api-client.ts b/src/app/pages/contacts/contacts-api-client.ts
index e431d36..f1eb052 100644
--- a/src/app/pages/contacts/contacts-api-client.ts
+++ b/src/app/pages/contacts/contacts-api-client.ts
@@ -1,4 +1,4 @@
- /********************************************************************************
+/********************************************************************************
  * Copyright (c) 2020 Contributors to the Eclipse Foundation
  *
  * See the NOTICE file(s) distributed with this work for additional
@@ -22,19 +22,38 @@
 
 @Injectable()
 @DefaultHeaders({
-  'Accept': 'application/json',
+  Accept: 'application/json',
   'Content-Type': 'application/json',
 })
 export class ContactsApiClient extends HttpService {
   public getContacts(request: PageRequestInterface = null): Observable<PageModel<Contact>> {
     let modifiedContacts: ModifiedContacts = null;
-    if(request != null){
+    if (request != null) {
       modifiedContacts = request.queryParameter || {};
-      return this._getContactsPage(modifiedContacts.searchText, modifiedContacts.contactTypeId, modifiedContacts.sort, request.pageNumber ? (request.pageNumber - 1) : 0, request.pageSize);
+      return this._getContactsPage(
+        modifiedContacts.searchText,
+        modifiedContacts.contactTypeId,
+        modifiedContacts.sort,
+        modifiedContacts.moduleName,
+        modifiedContacts.withoutAssignedModule,
+        modifiedContacts.expiringDataInPast,
+        modifiedContacts.deletionLockExceeded,
+        request.pageNumber ? request.pageNumber - 1 : 0,
+        request.pageSize
+      );
     } else {
-      return this._getContactsPage(modifiedContacts.searchText, modifiedContacts.contactTypeId, modifiedContacts.sort, 1, 3);
+      return this._getContactsPage(
+        modifiedContacts.searchText,
+        modifiedContacts.contactTypeId,
+        modifiedContacts.sort,
+        modifiedContacts.moduleName,
+        modifiedContacts.withoutAssignedModule,
+        modifiedContacts.expiringDataInPast,
+        modifiedContacts.deletionLockExceeded,
+        1,
+        3
+      );
     }
-    
   }
 
   /**
@@ -42,7 +61,17 @@
    */
   @GET('/contacts')
   @Adapter(ContactsService.gridPageAdapter)
-  private _getContactsPage(@Query('searchText') searchtext: string, @Query('contactType') contactTypeId: string, @Query('sort') sort: string, @Query('page') pageNumber: number, @Query('size') pageSize: number): Observable<any> {
+  private _getContactsPage(
+    @Query('searchText') searchtext: string,
+    @Query('contactType') contactTypeId: string,
+    @Query('sort') sort: string,
+    @Query('moduleName') moduleName: string,
+    @Query('withoutAssignedModule') withoutAssignedModule: boolean,
+    @Query('expiringDataInPast') expiringDataInPast: boolean,
+    @Query('deletionLockExceeded') deletionLockExceeded: boolean,
+    @Query('page') pageNumber: number,
+    @Query('size') pageSize: number
+  ): Observable<any> {
     return null;
   }
 
@@ -62,4 +91,9 @@
   public putContactDetails(@Path('id') id: number, @Body() editedContact: Contact): Observable<Contact> {
     return null;
   }
+
+  @PUT('/contacts/{id}/anonymize')
+  public anonymizeContact(@Path('id') id: string): Observable<void> {
+    return null;
+  }
 }
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 ba03537..2524723 100644
--- a/src/app/pages/contacts/contacts-list/contacts-list.component.html
+++ b/src/app/pages/contacts/contacts-list/contacts-list.component.html
@@ -16,34 +16,72 @@
   </div>
   <div class="contacts-grid-wrapper" body>
     <div class="diverse-options">
-      <div class="searching diverse-options-item">
-        <div class="search-options">
-          <input
-            type="text"
-            class="item"
-            id="searchText"
-            placeholder="Suche"
-            (keyup)="setModifiedContactsSearchText($event.target.value); searchContacts($event)"
-          />
+      <div class="search-options diverse-options-item">
+        <input
+          type="text"
+          class="item"
+          id="search-text"
+          placeholder="Suche"
+          (keyup)="setModifiedContactsSearchText($event.target.value); searchContacts($event)"
+        />
 
-          <select
-            [required]="false"
-            type="text"
-            class="form-control item"
-            (change)="setModifiedContactsContactTypeId($event.target.value); searchContacts($event)"
+        <select
+          [required]="false"
+          type="text"
+          class="form-control item"
+          (change)="setModifiedContactsContactTypeId($event.target.value); searchContacts($event)"
+        >
+          <option value="{{ INTERNAL_PERSON }}">{{ 'Contacts.InternalContact' | translate }}</option>
+          <option value="{{ EXTERNAL_PERSON }}">{{ 'Contacts.ExternalContact' | translate }}</option>
+          <option value="{{ COMPANY }}">{{ 'Contacts.Company' | translate }}</option>
+          <option value="{{ CONTACT_PERSON }}">{{ 'Contacts.ContactPersonList' | translate }}</option>
+          <option value="" selected>{{ 'Contacts.AllContactTypes' | translate }}</option>
+        </select>
+
+        <div class="dsgvo-filter-container search-btn">
+          <button
+            type="button"
+            class="btn btn-default btn-sm"
+            (click)="isDSGVOFilterAdvancedVisible = !isDSGVOFilterAdvancedVisible"
+            title="{{ 'Contacts.DSGVO-advanced-filter' | translate }}"
           >
-            <option value="{{ INTERNAL_PERSON }}">{{ 'Contacts.InternalContact' | translate }}</option>
-            <option value="{{ EXTERNAL_PERSON }}">{{ 'Contacts.ExternalContact' | translate }}</option>
-            <option value="{{ COMPANY }}">{{ 'Contacts.Company' | translate }}</option>
-            <option value="" selected>{{ 'Contacts.AllContactTypes' | translate }}</option>
-          </select>
+            DSGVO
+          </button>
+          <div class="dsgvo-filter-options" *ngIf="isDSGVOFilterAdvancedVisible">
+            <select
+              [required]="false"
+              type="text"
+              class="form-control"
+              style="margin-right: 12px;"
+              (change)="setModifiedContactsModuleAssignmentFilter($event.target.value); searchContacts($event)"
+            >
+              <option *ngFor="let moduleType of userModuleAssignmentSandbox.userModuleTypes$ | async" [value]="moduleType.id">{{ moduleType.id }}</option>
+              <option [value]="'-1'">{{ 'Contacts.WithoutModuleAssignment' | translate }}</option>
+              <option [value]="''" selected>{{ 'Contacts.AllModuleAssignments' | translate }}</option>
+            </select>
 
-          <div class="search-btn">
-            <button type="button" class="btn btn-default btn-sm" (click)="searchContacts($event)" title="suchen">
-              <em class="fa fa-search fa-lg " aria-hidden="true "></em>
-            </button>
+            <div class="dsgvo-filter-item custom-control custom-switch" title="{{ 'Contacts.DSGVO-advanced-filter-expiring-data-in-past' | translate }}">
+              <input type="checkbox" class="custom-control-input" id="expiry-date" (change)="setModifiedContactsExpiryDateFilter(); searchContacts($event)" />
+              <label class="custom-control-label" style="position: 0px;" for="expiry-date"></label>
+            </div>
+
+            <div class="dsgvo-filter-item custom-control custom-switch" title="{{ 'Contacts.DSGVO-advanced-filter-deletion-lock-exceeded' | translate }}">
+              <input
+                type="checkbox"
+                class="custom-control-input"
+                id="deletion-lock-until"
+                (change)="setModifiedContactsDeletionLockExceedFilter(); searchContacts($event)"
+              />
+              <label class="custom-control-label" for="deletion-lock-until"></label>
+            </div>
           </div>
         </div>
+
+        <div class="search-btn">
+          <button type="button" class="btn btn-default btn-sm" (click)="searchContacts($event)" title="suchen">
+            <em class="fa fa-search fa-lg " aria-hidden="true "></em>
+          </button>
+        </div>
       </div>
 
       <div class="sorting-options diverse-options-item">
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 83462b7..7b3ad89 100644
--- a/src/app/pages/contacts/contacts-list/contacts-list.component.scss
+++ b/src/app/pages/contacts/contacts-list/contacts-list.component.scss
@@ -46,24 +46,23 @@
   margin-right: 2px;
 }
 
-.searching {
-  display: flex;
-  flex-wrap: nowrap;
-  justify-content: flex-start;
-}
-
 .search-options {
   display: flex;
   flex-wrap: nowrap;
   justify-content: flex-start;
   align-items: center;
+  flex-grow: 1;
 }
 
 .item {
-  min-width: 170px;
+  flex-basis: 185px;
   margin: 5px;
 }
 
+#search-text {
+  max-width: 160px;
+}
+
 .search-btn {
   display: flex;
   align-items: center;
@@ -80,6 +79,7 @@
   flex-wrap: nowrap;
   justify-content: flex-start;
   align-items: center;
+  min-width: 380px;
 }
 
 .diverse-btn {
@@ -102,3 +102,21 @@
   margin-right: 2px;
   margin-bottom: 2px;
 }
+.dsgvo-filter-container {
+  display: flex;
+  flex-direction: row;
+  flex-wrap: nowrap;
+  justify-content: flex-start;
+  justify-self: center;
+}
+.dsgvo-filter-options {
+  display: flex;
+  flex-direction: row;
+  flex-wrap: nowrap;
+  justify-content: flex-start;
+  align-items: center;
+  flex-grow: 1;
+}
+.dsgvo-filter-item {
+  margin: 4px 0px 0px 12px;
+}
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 295e22f..222b05f 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
@@ -17,11 +17,12 @@
 describe('ContactsListComponent', () => {
   let component: ContactsListComponent;
   let contactsSandbox: any = {};
+  let userModuleAssignmentSandbox: any = {};
   let router: any = {};
 
   beforeEach(() => {
     router = { navigateByUrl() {}, navigate() {} } as any;
-    component = new ContactsListComponent(contactsSandbox, router);
+    component = new ContactsListComponent(contactsSandbox, userModuleAssignmentSandbox, router);
   });
 
   it('should create', () => {
@@ -170,7 +171,7 @@
     expect((component as any)._sortingOrder).toBe('asc');
   });
 
-  it('checks if function _setModifiedContactsSortProperty() works', () => {
+  it('checks if function _setModifiedContactsSort() works', () => {
     component.setSortingContactType('name');
     (component as any)._setModifiedContactsSort();
     expect(component.modifiedContacts.sort).toBe('name,asc');
@@ -183,4 +184,31 @@
     (component as any)._setModifiedContactsSort();
     expect(component.modifiedContacts.sort).toBe(null);
   });
+
+  it('checks if function setModifiedContactsExpiryDateFilter() works', () => {
+    expect(component.modifiedContacts.expiringDataInPast).toBeFalsy();
+    component.setModifiedContactsExpiryDateFilter();
+    expect(component.modifiedContacts.expiringDataInPast).toBeTruthy();
+  });
+
+  it('checks if function setModifiedContactsDeletionLockExceedFilter() works', () => {
+    expect(component.modifiedContacts.deletionLockExceeded).toBeFalsy();
+    component.setModifiedContactsDeletionLockExceedFilter();
+    expect(component.modifiedContacts.deletionLockExceeded).toBeTruthy();
+  });
+
+  it('checks if function setModifiedContactsModuleAssignmentFilter() works', () => {
+    let moduleName = '-1';
+    component.setModifiedContactsModuleAssignmentFilter(moduleName);
+    expect(component.modifiedContacts.moduleName).toBe(null);
+    expect(component.modifiedContacts.withoutAssignedModule).toBeTruthy();
+    moduleName = '';
+    component.setModifiedContactsModuleAssignmentFilter(moduleName);
+    expect(component.modifiedContacts.moduleName).toBe(null);
+    expect(component.modifiedContacts.withoutAssignedModule).toBeFalsy();
+    moduleName = 'Betriebstagebuch';
+    component.setModifiedContactsModuleAssignmentFilter(moduleName);
+    expect(component.modifiedContacts.moduleName).toBe(moduleName);
+    expect(component.modifiedContacts.withoutAssignedModule).toBeFalsy();
+  });
 });
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 99b8d8d..8576d49 100644
--- a/src/app/pages/contacts/contacts-list/contacts-list.component.ts
+++ b/src/app/pages/contacts/contacts-list/contacts-list.component.ts
@@ -17,6 +17,7 @@
 import { Router } from '@angular/router';
 import { Globals } from '@shared/constants/globals';
 import { ModifiedContacts } from '@shared/models/modifiedContacts.model';
+import { UserModuleAssignmentSandBox } from '@shared/components/list-details-view/user-module-assignment/user-module-assignment.sandbox';
 
 @Component({
   selector: 'app-contacts-list',
@@ -31,14 +32,18 @@
   public readonly INTERNAL_PERSON = Globals.CONTACT_TYPE_ID.INTERNAL_PERSON;
   public readonly EXTERNAL_PERSON = Globals.CONTACT_TYPE_ID.EXTERNAL_PERSON;
   public readonly COMPANY = Globals.CONTACT_TYPE_ID.COMPANY;
+  public readonly CONTACT_PERSON = Globals.CONTACT_TYPE_ID.CONTACT_PERSON;
 
   public columnDefinition: any = CONTACTS_COLDEF;
   public modifiedContacts: ModifiedContacts = new ModifiedContacts();
+  public isDSGVOFilterAdvancedVisible = false;
 
   private _sortingOrder: string = 'asc';
   private _sortingContactType: string = '';
+  private _expiringDataInPast = false;
+  private _deletionLockExceeded = false;
 
-  constructor(public contactsSandbox: ContactsSandbox, private router: Router) {
+  constructor(public contactsSandbox: ContactsSandbox, public userModuleAssignmentSandbox: UserModuleAssignmentSandBox, private router: Router) {
     super();
   }
 
@@ -104,6 +109,32 @@
     this.modifiedContacts.contactTypeId = contactTypeId;
   }
 
+  public setModifiedContactsModuleAssignmentFilter(moduleName: string) {
+    if (moduleName === '-1') {
+      //show contacts without module assignments
+      this.modifiedContacts.moduleName = null;
+      this.modifiedContacts.withoutAssignedModule = true;
+    } else if (moduleName == '') {
+      //show contacts with all module assignments
+      this.modifiedContacts.moduleName = null;
+      this.modifiedContacts.withoutAssignedModule = false;
+    } else {
+      //show contacts with specific module assignments
+      this.modifiedContacts.moduleName = moduleName;
+      this.modifiedContacts.withoutAssignedModule = false;
+    }
+  }
+
+  public setModifiedContactsExpiryDateFilter() {
+    this._expiringDataInPast = !this._expiringDataInPast;
+    this.modifiedContacts.expiringDataInPast = this._expiringDataInPast;
+  }
+
+  public setModifiedContactsDeletionLockExceedFilter() {
+    this._deletionLockExceeded = !this._deletionLockExceeded;
+    this.modifiedContacts.deletionLockExceeded = this._deletionLockExceeded;
+  }
+
   public setSortingContactType(sortingContactType: string) {
     this._sortingContactType = sortingContactType;
   }
diff --git a/src/app/pages/persons/external-person/external-person-details/external-person-details.component.html b/src/app/pages/persons/external-person/external-person-details/external-person-details.component.html
index c7687e6..d03ec35 100644
--- a/src/app/pages/persons/external-person/external-person-details/external-person-details.component.html
+++ b/src/app/pages/persons/external-person/external-person-details/external-person-details.component.html
@@ -109,12 +109,19 @@
         </div>
 
         <!-- buttons -->
-        <button *visibleByRight type="button" class="btn btn-success" (click)="externalPersonSandBox.persistExternalPerson()">
-          {{ 'SaveBtn' | translate }}
-        </button>
-        <button type="button" class="btn btn-primary cancel-button" routerLink="/overview">
-          {{ 'CancelBtn' | translate }}
-        </button>
+        <div class="row justify-content-between">
+          <div>
+            <button *visibleByRight type="button" class="btn btn-success person-buttons" (click)="externalPersonSandBox.persistExternalPerson()">
+              {{ 'SaveBtn' | translate }}
+            </button>
+            <button type="button" class="btn btn-primary person-buttons cancel-button" routerLink="/overview">
+              {{ 'CancelBtn' | translate }}
+            </button>
+          </div>
+          <div class="person-buttons" *ngIf="externalPersonSandBox.externalPersonContactId">
+            <app-anonymizer [contactId]="externalPersonSandBox.externalPersonContactId"></app-anonymizer>
+          </div>
+        </div>
       </div>
     </form>
 
diff --git a/src/app/pages/persons/external-person/external-person-details/external-person-details.component.scss b/src/app/pages/persons/external-person/external-person-details/external-person-details.component.scss
index b78a7c2..d73298c 100644
--- a/src/app/pages/persons/external-person/external-person-details/external-person-details.component.scss
+++ b/src/app/pages/persons/external-person/external-person-details/external-person-details.component.scss
@@ -10,42 +10,42 @@
  *
  * SPDX-License-Identifier: EPL-2.0
  ********************************************************************************/
-.cancel-button {
-	margin-left: 16px;
+.person-buttons {
+  margin: 16px;
 }
 .expandable-body-container {
-	display: flex;
-	flex-direction: row;
-	height: 100%;
+  display: flex;
+  flex-direction: row;
+  height: 100%;
 }
 .table-detail-view-address {
-	height: 756px;
-	width: 461px;
+  height: 756px;
+  width: 461px;
 }
 .table-view-address {
-	height: 711px;
-	flex-grow: 1;
+  height: 711px;
+  flex-grow: 1;
 }
 .expandable-address .collapse5 {
-	height: 758px;
+  height: 758px;
 }
 .table-detail-view-communication {
-	height: 296px;
-	width: 461px;
+  height: 296px;
+  width: 461px;
 }
 .table-view-communication {
-	height: 263px;
+  height: 263px;
   flex-grow: 1;
 }
 .expandable-communication .collapse5 {
-	height: 310px;
+  height: 310px;
 }
-.table-detail-view-module-assignment{
-	height: 336px;
+.table-detail-view-module-assignment {
+  height: 336px;
   width: 461px;
   min-width: 461px;
 }
-.table-view-module-assignment{
+.table-view-module-assignment {
   height: 290px;
   flex-grow: 1;
 }
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 5f50a27..29a9637 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
@@ -189,12 +189,19 @@
         </div>
 
         <!-- buttons -->
-        <button *visibleByRight type="button" class="btn btn-success" (click)="internalPersonSandBox.persistInternalPerson()">
-          {{ 'SaveBtn' | translate }}
-        </button>
-        <button type="button" class="btn btn-primary cancel-button" routerLink="/overview">
-          {{ 'CancelBtn' | translate }}
-        </button>
+        <div class="row justify-content-between">
+          <div>
+            <button *visibleByRight type="button" class="btn btn-success person-buttons" (click)="internalPersonSandBox.persistInternalPerson()">
+              {{ 'SaveBtn' | translate }}
+            </button>
+            <button type="button" class="btn btn-primary person-buttons cancel-button" routerLink="/overview">
+              {{ 'CancelBtn' | translate }}
+            </button>
+          </div>
+          <div class="person-buttons" *ngIf="internalPersonSandBox.internalPersonContactId">
+            <app-anonymizer [contactId]="internalPersonSandBox.internalPersonContactId"></app-anonymizer>
+          </div>
+        </div>
       </div>
     </form>
 
diff --git a/src/app/pages/persons/internal-person/internal-person-details/internal-person-details.component.scss b/src/app/pages/persons/internal-person/internal-person-details/internal-person-details.component.scss
index 0615b03..d73298c 100644
--- a/src/app/pages/persons/internal-person/internal-person-details/internal-person-details.component.scss
+++ b/src/app/pages/persons/internal-person/internal-person-details/internal-person-details.component.scss
@@ -10,8 +10,8 @@
  *
  * SPDX-License-Identifier: EPL-2.0
  ********************************************************************************/
-.btn-success {
-  margin-right: 16px;
+.person-buttons {
+  margin: 16px;
 }
 .expandable-body-container {
   display: flex;
diff --git a/src/app/shared/components/anonymizer/anonymizer.component.html b/src/app/shared/components/anonymizer/anonymizer.component.html
new file mode 100644
index 0000000..a8ab33b
--- /dev/null
+++ b/src/app/shared/components/anonymizer/anonymizer.component.html
@@ -0,0 +1,15 @@
+<!-- /********************************************************************************
+* 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
+********************************************************************************/ -->
+<p>
+  <button type="button" class="btn btn-warning" (click)="anonymizeContact()">Anonymisieren</button>
+</p>
diff --git a/src/app/shared/components/anonymizer/anonymizer.component.scss b/src/app/shared/components/anonymizer/anonymizer.component.scss
new file mode 100644
index 0000000..c37e40b
--- /dev/null
+++ b/src/app/shared/components/anonymizer/anonymizer.component.scss
@@ -0,0 +1,12 @@
+/********************************************************************************
+ * 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
+ ********************************************************************************/
diff --git a/src/app/shared/components/anonymizer/anonymizer.component.spec.ts b/src/app/shared/components/anonymizer/anonymizer.component.spec.ts
new file mode 100644
index 0000000..07642e4
--- /dev/null
+++ b/src/app/shared/components/anonymizer/anonymizer.component.spec.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 { AnonymizerComponent } from '@shared/components/anonymizer/anonymizer.component';
+
+describe('AnonymizerComponent', () => {
+  let component: AnonymizerComponent;
+  const sandbox: any = {
+    anonymizeContact: () => {},
+    endSubscriptions: () => {},
+  };
+
+  beforeEach(() => {
+    component = new AnonymizerComponent(sandbox);
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+
+  it('should transfer anonymizeContact call to sandbox', () => {
+    const spy: any = spyOn(sandbox, 'anonymizeContact');
+    component.anonymizeContact();
+    expect(spy).toHaveBeenCalled();
+  });
+
+  it('should reset component', () => {
+    component.contactId = 'x';
+    component.ngOnDestroy();
+    expect(component.contactId).toBe(null);
+  });
+});
diff --git a/src/app/shared/components/anonymizer/anonymizer.component.ts b/src/app/shared/components/anonymizer/anonymizer.component.ts
new file mode 100644
index 0000000..b843de9
--- /dev/null
+++ b/src/app/shared/components/anonymizer/anonymizer.component.ts
@@ -0,0 +1,34 @@
+/********************************************************************************
+ * 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 { AnonymizerSandbox } from '@shared/components/anonymizer/anonymizer.sandbox';
+import { Component, Input } from '@angular/core';
+
+@Component({
+  selector: 'app-anonymizer',
+  templateUrl: './anonymizer.component.html',
+  styleUrls: ['./anonymizer.component.scss'],
+})
+export class AnonymizerComponent {
+  @Input() contactId: string;
+
+  constructor(private _sandbox: AnonymizerSandbox) {}
+
+  public anonymizeContact() {
+    this._sandbox.anonymizeContact(this.contactId);
+  }
+
+  ngOnDestroy() {
+    this._sandbox.endSubscriptions();
+    this.contactId = null;
+  }
+}
diff --git a/src/app/shared/components/anonymizer/anonymizer.sandbox.spec.ts b/src/app/shared/components/anonymizer/anonymizer.sandbox.spec.ts
new file mode 100644
index 0000000..f40b89f
--- /dev/null
+++ b/src/app/shared/components/anonymizer/anonymizer.sandbox.spec.ts
@@ -0,0 +1,46 @@
+/********************************************************************************
+ * 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 { NgbModal } from '@ng-bootstrap/ng-bootstrap';
+import { AnonymizerSandbox } from '@shared/components/anonymizer/anonymizer.sandbox';
+import { Store, ActionsSubject } from '@ngrx/store';
+import { State } from '@shared/store';
+import { of } from 'rxjs';
+import { Router } from '@angular/router';
+
+describe('AnonymizerSandbox', () => {
+  let service: AnonymizerSandbox;
+  let appState: Store<State>;
+  let actionSubject: ActionsSubject;
+  let router: Router;
+  let modalService: NgbModal;
+
+  beforeEach(() => {
+    appState = { dispatch: () => {}, pipe: () => of(true), select: () => of(true) } as any;
+    actionSubject = { pipe: () => of(true) } as any;
+    router = { navigateByUrl() {} } as any;
+    modalService = { open() {} } as any;
+    spyOn(appState, 'dispatch').and.callFake(() => {});
+
+    service = new AnonymizerSandbox(appState, actionSubject, router, modalService);
+  });
+
+  it('should create SalutationsSandbox service', () => {
+    expect(service).toBeTruthy();
+  });
+
+  it('should open modal before anonymizing an contact', () => {
+    spyOn(service['modalService'], 'open').and.returnValue({ componentInstance: { title: '' }, result: { then: () => of(true) } } as any);
+    service.anonymizeContact('x');
+    expect(modalService.open).toHaveBeenCalled();
+  });
+});
diff --git a/src/app/shared/components/anonymizer/anonymizer.sandbox.ts b/src/app/shared/components/anonymizer/anonymizer.sandbox.ts
new file mode 100644
index 0000000..15084e4
--- /dev/null
+++ b/src/app/shared/components/anonymizer/anonymizer.sandbox.ts
@@ -0,0 +1,44 @@
+/********************************************************************************
+ * 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 { BaseSandbox } from '@shared/sandbox/base.sandbox';
+import { Store, ActionsSubject } from '@ngrx/store';
+import * as store from '@shared/store';
+import * as contactsActions from '@shared/store/actions/contacts.action';
+import { ofType } from '@ngrx/effects';
+import { takeUntil } from 'rxjs/operators';
+import { Router } from '@angular/router';
+import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
+import { SafetyQueryDialogComponent } from '@shared/components/dialogs/safety-query-dialog/safety-query-dialog.component';
+
+@Injectable()
+export class AnonymizerSandbox extends BaseSandbox {
+  constructor(protected appState$: Store<store.State>, protected actionsSubject: ActionsSubject, protected router: Router, protected modalService: NgbModal) {
+    super(appState$);
+    this.actionsSubject.pipe(ofType(contactsActions.anonymizeContactSuccess), takeUntil(this._endSubscriptions$)).subscribe(() => {
+      this.router.navigateByUrl(`/overview`);
+    });
+  }
+
+  public anonymizeContact(contactId: string): void {
+    const modalRef = this.modalService.open(SafetyQueryDialogComponent);
+    modalRef.componentInstance.title = 'ConfirmDialog.Action.anonymize';
+    modalRef.componentInstance.body = 'ConfirmDialog.Anonymization';
+    modalRef.result.then(
+      () => {
+        this.appState$.dispatch(contactsActions.anonymizeContact({ payload: contactId }));
+      },
+      () => {}
+    );
+  }
+}
diff --git a/src/app/shared/components/expandable/expandable.component.html b/src/app/shared/components/expandable/expandable.component.html
index bf2c334..d952ee5 100644
--- a/src/app/shared/components/expandable/expandable.component.html
+++ b/src/app/shared/components/expandable/expandable.component.html
@@ -11,19 +11,18 @@
 * SPDX-License-Identifier: EPL-2.0
 ********************************************************************************/ -->
 <div class="panel panel-default" style="width:100%;">
-    <div class="panel-heading">
-        <h4 class="panel-title">
-        <a data-toggle="collapse">
-            <i *ngIf="isExpandedStatus" class="fa fa-chevron-up" aria-hidden="true"></i>
-            <i *ngIf="!isExpandedStatus" class="fa fa-chevron-down" aria-hidden="true"></i>
-        </a>
-        <a data-toggle="collapse" href="#{{collapseId}}" (click)="isExpandedStatus = !isExpandedStatus">
-            <ng-content select="[header]"></ng-content>
-        </a>
-
-        </h4>
-    </div>
-    <div *ngIf="isExpandedStatus" id="{{collapseId}}" class="collapse5 panel-collapse collapse in" [ngClass]="{'in': !isStatusCollapsed }">
-        <ng-content class="bodyContent" select="[body]"></ng-content>
-    </div>
+  <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">
+        <ng-content select="[header]"></ng-content>
+      </a>
+    </h4>
+  </div>
+  <div *ngIf="isExpandedStatus" id="{{ collapseId }}" class="collapse5 panel-collapse collapse in" [ngClass]="{ in: !isStatusCollapsed }">
+    <ng-content class="bodyContent" select="[body]"></ng-content>
+  </div>
 </div>
diff --git a/src/app/shared/components/index.ts b/src/app/shared/components/index.ts
index dd0c87a..1834bdf 100644
--- a/src/app/shared/components/index.ts
+++ b/src/app/shared/components/index.ts
@@ -44,6 +44,8 @@
 import { NgbDatepickerModule, NgbDateParserFormatter } from '@ng-bootstrap/ng-bootstrap';
 import { NgbDateCustomParserFormatter } from '@shared/pipes/ngb-date-custom-parser-formatter';
 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';
 
 export const COMPONENTS = [
   SpinnerComponent,
@@ -62,6 +64,7 @@
   UserModuleAssignmentDataDetailsComponent,
   UserModuleAssignmentDataListComponent,
   DateCellRendererComponent,
+  AnonymizerComponent,
 ];
 
 @NgModule({
@@ -97,6 +100,7 @@
     UserModuleAssignmentsService,
     DatePipe,
     { provide: NgbDateParserFormatter, useClass: NgbDateCustomParserFormatter },
+    AnonymizerSandbox,
   ],
 })
 export class ComponentsModule {}
diff --git a/src/app/shared/components/list-details-view/user-module-assignment/details/details.component.html b/src/app/shared/components/list-details-view/user-module-assignment/details/details.component.html
index 69931c7..013a253 100644
--- a/src/app/shared/components/list-details-view/user-module-assignment/details/details.component.html
+++ b/src/app/shared/components/list-details-view/user-module-assignment/details/details.component.html
@@ -31,7 +31,7 @@
       <div class="input-group col-sm-7">
         <div class="input-group-prepend">
           <button class="btn btn-outline-primary calendar" (click)="expiringDateCalendar.toggle()" type="button">
-            <i class="fa fa-calendar"></i>
+            <em class="fa fa-calendar"></em>
           </button>
         </div>
         <input
@@ -49,7 +49,7 @@
         />
         <div class="input-group-append">
           <button class="btn btn-outline-primary calendar" (click)="reset('expiringDate')" type="button">
-            <i class="fa fa-times-circle" aria-hidden="true"></i>
+            <em class="fa fa-times-circle" aria-hidden="true"></em>
           </button>
         </div>
       </div>
@@ -61,7 +61,7 @@
       <div class="input-group col-sm-7">
         <div class="input-group-prepend">
           <button class="btn btn-outline-primary calendar" (click)="deletionLockUntilCalendar.toggle()" type="button">
-            <i class="fa fa-calendar"></i>
+            <em class="fa fa-calendar"></em>
           </button>
         </div>
         <input
@@ -79,7 +79,7 @@
         />
         <div class="input-group-append">
           <button class="btn btn-outline-primary calendar" (click)="reset('deletionLockUntil')" type="button">
-            <i class="fa fa-times-circle" aria-hidden="true"></i>
+            <em class="fa fa-times-circle" aria-hidden="true"></em>
           </button>
         </div>
       </div>
diff --git a/src/app/shared/models/modifiedContacts.model.ts b/src/app/shared/models/modifiedContacts.model.ts
index 886e071..e7817a9 100644
--- a/src/app/shared/models/modifiedContacts.model.ts
+++ b/src/app/shared/models/modifiedContacts.model.ts
@@ -1,15 +1,17 @@
 import { Contact } from '@shared/models';
 
 export class ModifiedContacts {
+  public searchText: string = null;
+  public contactTypeId: string = '';
+  public sort: string = null;
+  public moduleName: string = null;
+  public withoutAssignedModule: boolean = null;
+  public expiringDataInPast: boolean = null;
+  public deletionLockExceeded: boolean = null;
 
-    public searchText: string = null;
-    public contactTypeId: string = '';
-    public sort: string = null;
-  
-    public constructor(data: any = null) {
-      Object.keys(data || {})
-        .filter(property => this.hasOwnProperty(property))
-        .forEach(property => (this[property] = data[property]));
-    }
+  public constructor(data: any = null) {
+    Object.keys(data || {})
+      .filter(property => this.hasOwnProperty(property))
+      .forEach(property => (this[property] = data[property]));
   }
-  
\ No newline at end of file
+}
diff --git a/src/app/shared/store/actions/contacts.action.ts b/src/app/shared/store/actions/contacts.action.ts
index bcf6753..826eef0 100644
--- a/src/app/shared/store/actions/contacts.action.ts
+++ b/src/app/shared/store/actions/contacts.action.ts
@@ -28,3 +28,7 @@
 export const loadContactsPage = createAction('[Contacts] Load Page', props<ILoadContactsPage>());
 export const loadContactsPageSuccess = createAction('[Contacts] Load Page Success', props<ILoadContactsPageSuccess>());
 export const loadContactsPageFail = createAction('[Contacts] Load Page Fail', props<ILoadContactsPageFail>());
+
+export const anonymizeContact = createAction('[Contact] Anonymize', props<{ payload: string }>());
+export const anonymizeContactSuccess = createAction('[Contact] Anonymize Success');
+export const anonymizeContactFail = createAction('[Contact] Anonymize Fail', props<{ payload: string }>());
diff --git a/src/app/shared/store/effects/contacts.effect.ts b/src/app/shared/store/effects/contacts.effect.ts
index c0021c5..a273757 100644
--- a/src/app/shared/store/effects/contacts.effect.ts
+++ b/src/app/shared/store/effects/contacts.effect.ts
@@ -1,4 +1,4 @@
- /********************************************************************************
+/********************************************************************************
  * Copyright (c) 2020 Contributors to the Eclipse Foundation
  *
  * See the NOTICE file(s) distributed with this work for additional
@@ -25,11 +25,11 @@
 export class ContactsEffects {
   /* paged list */
   getContactsPage$: any = createEffect(() =>
-    this.actions$.pipe(
+    this._actions$.pipe(
       ofType(contactsActions.loadContactsPage),
       map(action => action['payload']),
       switchMap((request: PageRequestInterface) => {
-        return this.contactsApiClient.getContacts(request).pipe(
+        return this._contactsApiClient.getContacts(request).pipe(
           map(contacts => contactsActions.loadContactsPageSuccess({ payload: contacts })),
           catchError(error => of(contactsActions.loadContactsPageFail({ payload: error })))
         );
@@ -37,5 +37,18 @@
     )
   );
 
-  constructor(private actions$: Actions, private contactsApiClient: ContactsApiClient) {}
+  anonymizeContact$: any = createEffect(() =>
+    this._actions$.pipe(
+      ofType(contactsActions.anonymizeContact),
+      map(action => action['payload']),
+      switchMap((id: string) => {
+        return this._contactsApiClient.anonymizeContact(id).pipe(
+          map(() => contactsActions.anonymizeContactSuccess()),
+          catchError(error => of(contactsActions.anonymizeContactFail({ payload: error })))
+        );
+      })
+    )
+  );
+
+  constructor(private _actions$: Actions, private _contactsApiClient: ContactsApiClient) {}
 }
diff --git a/src/app/shared/store/effects/contacts.effects.spec.ts b/src/app/shared/store/effects/contacts.effects.spec.ts
index 681a430..9d4c8ec 100644
--- a/src/app/shared/store/effects/contacts.effects.spec.ts
+++ b/src/app/shared/store/effects/contacts.effects.spec.ts
@@ -1,4 +1,4 @@
- /********************************************************************************
+/********************************************************************************
  * Copyright (c) 2020 Contributors to the Eclipse Foundation
  *
  * See the NOTICE file(s) distributed with this work for additional
@@ -13,27 +13,24 @@
 import { PageRequestInterface } from '@shared/models/page/page-request.interface';
 import { take } from 'rxjs/operators';
 import { ContactsEffects } from '@shared/store/effects/contacts.effect';
-import { Subject, of, throwError } from 'rxjs';
+import { Subject, of, throwError, Observable } from 'rxjs';
 import { Contact } from '@shared/models';
 import * as contactsActions from '@shared/store/actions/contacts.action';
 import { ContactsApiClient } from '@pages/contacts/contacts-api-client';
 import { PageModel } from '@shared/models/page/page.model';
 
-
 describe('Contacts Effects', () => {
-
   let effects: ContactsEffects;
   let actions$: Subject<any>;
   let apiClient: ContactsApiClient;
-  let apiResponse = new PageModel<Contact>(
-    {
-      content: [new Contact({id: "1"})]
-    }
-  ) as any;
+  let apiResponse = new PageModel<Contact>({
+    content: [new Contact({ id: '1' })],
+  }) as any;
 
   beforeEach(() => {
     apiClient = {
-      getContacts() {}
+      getContacts() {},
+      anonymizeContact() {},
     } as any;
     actions$ = new Subject();
     effects = new ContactsEffects(actions$, apiClient);
@@ -43,36 +40,47 @@
     expect(effects).toBeTruthy();
   });
 
-  it('should equal loadContactsPageSuccess after getContactsPage', (done) => {
-    let request = {payload: {
+  it('should equal loadContactsPageSuccess after getContactsPage', done => {
+    let request = {
+      payload: {
         pageNumber: 1,
         pageSize: 3,
-      } as PageRequestInterface
-    }
+      } as PageRequestInterface,
+    };
     spyOn(apiClient, 'getContacts').and.returnValue(of(apiResponse));
 
     effects.getContactsPage$.pipe(take(1)).subscribe(result => {
-      expect(result).toEqual(contactsActions.loadContactsPageSuccess({payload: apiResponse}));
+      expect(result).toEqual(contactsActions.loadContactsPageSuccess({ payload: apiResponse }));
     });
     done();
 
     actions$.next(contactsActions.loadContactsPage(request));
   });
 
-  it('should equal loadContactsPageFail after getContactsPage Error', (done) => {
-    let request = {payload: {
+  it('should equal loadContactsPageFail after getContactsPage Error', done => {
+    let request = {
+      payload: {
         pageNumber: 1,
         pageSize: 3,
-      } as PageRequestInterface
-    }
+      } as PageRequestInterface,
+    };
     spyOn(apiClient, 'getContacts').and.returnValue(throwError('x'));
 
     effects.getContactsPage$.pipe(take(1)).subscribe(result => {
-      expect(result).toEqual(contactsActions.loadContactsPageFail({payload: 'x'}));
+      expect(result).toEqual(contactsActions.loadContactsPageFail({ payload: 'x' }));
     });
     done();
 
     actions$.next(contactsActions.loadContactsPage(request));
   });
 
+  it('should successfully process on anonymizeContact action', done => {
+    apiResponse = new Observable<void>();
+    spyOn(apiClient, 'anonymizeContact').and.returnValue(of(apiResponse));
+    effects.anonymizeContact$.pipe(take(1)).subscribe(result => {
+      expect(result).toEqual(contactsActions.anonymizeContactSuccess());
+    });
+    done();
+    actions$.next(contactsActions.anonymizeContact({ payload: 'x' }));
+  });
 });