[KON-19,20] codereview, unittests

Signed-off-by: Dimitrios Chalepakis <dimitrios.chalepakis@pta.de>
diff --git a/i18n/contacts.de.json b/i18n/contacts.de.json
index 5c6a924..10a6755 100644
--- a/i18n/contacts.de.json
+++ b/i18n/contacts.de.json
@@ -17,6 +17,6 @@
     "AddressList": "Adressliste",
     "AllContactTypes": "Alle Kontakttypen",
     "Department": "Abteilung",
-    "CommunicationsDataList": "Kommunikationsdatenliste"
+    "CommunicationsDataList": "Kommunikationskanäle"
   }
 }
diff --git a/src/app/pages/company/company-details/communications-data-details/communications-data-details.component.html b/src/app/pages/company/company-details/communications-data-details/communications-data-details.component.html
index 8deb480..009f395 100644
--- a/src/app/pages/company/company-details/communications-data-details/communications-data-details.component.html
+++ b/src/app/pages/company/company-details/communications-data-details/communications-data-details.component.html
@@ -22,7 +22,7 @@
           class="form-control"
           [ngrxFormControlState]="((companyDetailsSandbox.communicationsDataDetailsFormState$ | async)?.controls)['communicationTypeId']">
           <option [value]="">{{ 'SelectOption' | translate }}</option> -->
-          <option *ngFor="let communicationType of communicationTypesSandbox.communicationTypes$ | async" [value]="communicationType.id">{{communicationType.type}}</option>
+          <option *ngFor="let communicationType of communicationTypesSandbox.communicationTypes$ | async" [disabled]="communicationType.isDisabled" [value]="communicationType.id">{{communicationType.type}}</option>
         </select>
       </div>
     </div>
@@ -32,7 +32,7 @@
       <label for="communicationData" class="col-sm-4 col-form-label">{{ 'CommunicationsData.CommunicationData' | translate }}</label>
       <div  class="col-sm-7">
         <input type="text"
-                maxlength="30"
+                maxlength="1024"
                 class="form-control"
                 id="communicationData"
                 [ngrxFormControlState]="((companyDetailsSandbox.communicationsDataDetailsFormState$ | async)?.controls)['communicationData']"
diff --git a/src/app/pages/company/company-details/communications-data-details/communications-data-details.component.scss b/src/app/pages/company/company-details/communications-data-details/communications-data-details.component.scss
index 4a90022..b959869 100644
--- a/src/app/pages/company/company-details/communications-data-details/communications-data-details.component.scss
+++ b/src/app/pages/company/company-details/communications-data-details/communications-data-details.component.scss
@@ -20,3 +20,6 @@
 div.form-group.row {
 	padding-left: 15px;
 }
+select option[disabled]{
+  background-color: rgb(160, 164, 168);
+}
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 419e75f..7ca4925 100644
--- a/src/app/pages/company/company-details/company-details.sandbox.ts
+++ b/src/app/pages/company/company-details/company-details.sandbox.ts
@@ -1,4 +1,3 @@
-import { MarkAsTouchedAction } from 'ngrx-forms';
 /********************************************************************************
  * Copyright (c) 2020 Contributors to the Eclipse Foundation
  *
@@ -15,18 +14,20 @@
 import { Injectable } from '@angular/core';
 import * as companyActions from '@shared/store/actions/company/company.action';
 import { FormGroupState, SetValueAction, ResetAction } from 'ngrx-forms';
-import { Company, CommunicationsData } from '@shared/models';
+import { Company, CommunicationsData, CommunicationType } from '@shared/models';
 import { Observable } from 'rxjs';
 import * as store from '@shared/store';
 import { Store, ActionsSubject } from '@ngrx/store';
 import * as companyDetailsFormReducer from '@shared/store/reducers/company/company-details-form.reducer';
 import { ofType } from '@ngrx/effects';
 import { UtilService } from '@shared/utility';
-import { takeUntil, take } from 'rxjs/operators';
+import { takeUntil, take, map } from 'rxjs/operators';
 import { Router } from '@angular/router';
 import { SafetyQueryDialogComponent } from '@shared/components/dialogs/safety-query-dialog/safety-query-dialog.component';
 import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
 import * as companyCommunicationsDataDetailsFormReducer from '@shared/store/reducers/company/communications-data-details-form.reducer';
+import * as communicationTypesActions from '@shared/store/actions/admin/communication-types.action';
+import { MarkAsTouchedAction } from 'ngrx-forms';
 
 @Injectable()
 export class CompanyDetailsSandBox extends BaseSandbox {
@@ -43,6 +44,8 @@
 
   private _companyContactId: string;
 
+  private _communicationTypes: Array<CommunicationType> = new Array<CommunicationType>();
+
   /**
    *  Company Sandbox constructor
    */
@@ -109,9 +112,34 @@
   }
 
   public loadCommunicationsData(companyId: string): void {
-    this.appState$.dispatch(
-      companyActions.loadCompanyDetailCommunicationsData({ payload: companyId })
-    );
+    this.actionsSubject
+          .pipe(
+            ofType(communicationTypesActions.loadCommunicationTypesSuccess),
+            map((action: communicationTypesActions.ILoadCommunicationTypesSuccess) => action.payload),
+            take(1),
+            takeUntil(this._endSubscriptions$)
+          )
+          .subscribe((payload: Array<CommunicationType>) => {
+            this._communicationTypes = payload;
+            this.appState$.dispatch(companyActions.loadCompanyDetailCommunicationsData({ payload: companyId }));
+          });
+
+    this.actionsSubject
+          .pipe(
+            ofType(companyActions.loadCompanyDetailCommunicationsDataSuccess),
+            map((action: companyActions.ILoadCompanyCommunicationsDataSuccess) => action.payload),
+            take(1),
+            takeUntil(this._endSubscriptions$)
+          )
+          .subscribe((communicationsData: Array<CommunicationsData>) => {
+            if (this._communicationTypes) {
+              for (let i = 0; i < this._communicationTypes.length; i++) {
+                const ct = this._communicationTypes[i];
+                const existingCommunicationsData: CommunicationsData = communicationsData.find(cd => cd.communicationTypeId == ct.id);
+                ct.isDisabled = existingCommunicationsData ? true : false;
+              }
+            }
+          });
   }
 
   public loadCommunicationsDataDetails(communicationsDataId: string): void {
@@ -157,6 +185,7 @@
   }
 
   public closeCommunicationsDataDetail(): void {
+    this.loadCommunicationsData(this._companyContactId);
     this.clearCommunicationsData();
     this.isCommunicationsDataDetailViewVisible = false;
   }
diff --git a/src/app/pages/persons/external-person/external-person-details/communications-data-details/communications-data-details.component.html b/src/app/pages/persons/external-person/external-person-details/communications-data-details/communications-data-details.component.html
index c7157f7..c5dbac6 100644
--- a/src/app/pages/persons/external-person/external-person-details/communications-data-details/communications-data-details.component.html
+++ b/src/app/pages/persons/external-person/external-person-details/communications-data-details/communications-data-details.component.html
@@ -22,7 +22,7 @@
           class="form-control"
           [ngrxFormControlState]="((externalPersonDetailsSandbox.communicationsDataDetailsFormState$ | async)?.controls)['communicationTypeId']">
           <option [value]="">{{ 'SelectOption' | translate }}</option> -->
-          <option *ngFor="let communicationType of communicationTypesSandbox.communicationTypes$ | async" [value]="communicationType.id">{{communicationType.type}}</option>
+          <option *ngFor="let communicationType of communicationTypesSandbox.communicationTypes$ | async" [disabled]="communicationType.isDisabled" [value]="communicationType.id">{{communicationType.type}}</option>
         </select>
       </div>
     </div>
@@ -32,7 +32,7 @@
       <label for="communicationData" class="col-sm-4 col-form-label">{{ 'CommunicationsData.CommunicationData' | translate }}</label>
       <div  class="col-sm-7">
         <input type="text"
-                maxlength="30"
+                maxlength="1024"
                 class="form-control"
                 id="communicationData"
                 [ngrxFormControlState]="((externalPersonDetailsSandbox.communicationsDataDetailsFormState$ | async)?.controls)['communicationData']"
diff --git a/src/app/pages/persons/external-person/external-person-details/communications-data-details/communications-data-details.component.scss b/src/app/pages/persons/external-person/external-person-details/communications-data-details/communications-data-details.component.scss
index 4a90022..b959869 100644
--- a/src/app/pages/persons/external-person/external-person-details/communications-data-details/communications-data-details.component.scss
+++ b/src/app/pages/persons/external-person/external-person-details/communications-data-details/communications-data-details.component.scss
@@ -20,3 +20,6 @@
 div.form-group.row {
 	padding-left: 15px;
 }
+select option[disabled]{
+  background-color: rgb(160, 164, 168);
+}
diff --git a/src/app/pages/persons/external-person/external-person-details/external-person-details.sandbox.spec.ts b/src/app/pages/persons/external-person/external-person-details/external-person-details.sandbox.spec.ts
index d9b6487..32a6cdb 100644
--- a/src/app/pages/persons/external-person/external-person-details/external-person-details.sandbox.spec.ts
+++ b/src/app/pages/persons/external-person/external-person-details/external-person-details.sandbox.spec.ts
@@ -130,12 +130,14 @@
   it('should open modal before deleting an address', () => {
     spyOn(component['modalService'], 'open')
       .and.returnValue({componentInstance: {title: ''}, result: {then: () => of(true)}} as any);
-      component.deleteAddress(new Address());
+    // (component as any)._communicationTypes = [new CommunicationType];
+    component.deleteAddress(new Address());
     expect(modalService.open).toHaveBeenCalled();
   });
 
   it('should call dispatch if load an external person communications Data', () => {
     const spy = spyOn(appState, 'dispatch');
+    // (component as any)._communicationTypes = [new CommunicationType];
     component.loadCommunicationsData('ID');
     expect(spy).toHaveBeenCalledWith( Object({ payload: 'ID', type: externalPersonActions.loadExternalPersonDetailCommunicationsData.type }));
   });
@@ -180,9 +182,11 @@
 
   it('should call clearCommunicationsData and negate isCommunicationsDataDetailViewVisible after call closeCommunicationsDataDetail', () => {
     const spy = spyOn(component, 'clearCommunicationsData');
+    const spy1 = spyOn(component, 'loadCommunicationsData');
     component.isCommunicationsDataDetailViewVisible = true;
     component.closeCommunicationsDataDetail();
     expect(spy).toHaveBeenCalled();
+    expect(spy1).toHaveBeenCalled();
     expect(component.isCommunicationsDataDetailViewVisible).toBe(false);
   });
 
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 bceedbc..547ecdb 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
@@ -14,7 +14,7 @@
 import { Injectable } from '@angular/core';
 import * as externalPersonActions from '@shared/store/actions/persons/external-person.action';
 import { FormGroupState, SetValueAction, ResetAction, MarkAsTouchedAction } from 'ngrx-forms';
-import { ExternalPerson, CommunicationsData, Address } from '@shared/models';
+import { ExternalPerson, CommunicationsData, Address, CommunicationType } from '@shared/models';
 import { Observable } from 'rxjs';
 import * as store from '@shared/store';
 import { Store, ActionsSubject } from '@ngrx/store';
@@ -22,11 +22,12 @@
 import * as externalAddressDetailsFormReducer from '@shared/store/reducers/persons/external-person/addresses-details-form.reducer';
 import { ofType } from '@ngrx/effects';
 import { UtilService } from '@shared/utility';
-import { takeUntil, take } from 'rxjs/operators';
+import { takeUntil, take, map } 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';
 import * as externalCommunicationsDataDetailsFormReducer from '@shared/store/reducers/persons/external-person/communications-data-details-form.reducer';
+import * as communicationTypesActions from '@shared/store/actions/admin/communication-types.action';
 
 @Injectable()
 export class ExternalPersonDetailsSandBox extends BaseSandbox {
@@ -51,6 +52,8 @@
 
   private _externalPersonContactId: string;
 
+  private _communicationTypes: Array<CommunicationType> = new Array<CommunicationType>();
+
   /**
    *  ExternalPerson Sandbox constructor
    */
@@ -180,7 +183,7 @@
         externalPersonDetailsFormReducer.INITIAL_STATE.value
       )
     );
-    this.appState$.dispatch(new ResetAction(externalPersonDetailsFormReducer.FORM_ID));    
+    this.appState$.dispatch(new ResetAction(externalPersonDetailsFormReducer.FORM_ID));
     this.appState$.dispatch(new MarkAsTouchedAction(externalPersonDetailsFormReducer.FORM_ID));
   }
 
@@ -220,9 +223,34 @@
   }
 
   public loadCommunicationsData(externalPersonId: string): void {
-    this.appState$.dispatch(
-      externalPersonActions.loadExternalPersonDetailCommunicationsData({ payload: externalPersonId })
-    );
+    this.actionsSubject
+          .pipe(
+            ofType(communicationTypesActions.loadCommunicationTypesSuccess),
+            map((action: communicationTypesActions.ILoadCommunicationTypesSuccess) => action.payload),
+            take(1),
+            takeUntil(this._endSubscriptions$)
+          )
+          .subscribe((payload: Array<CommunicationType>) => {
+            this._communicationTypes = payload;
+            this.appState$.dispatch(externalPersonActions.loadExternalPersonDetailCommunicationsData({ payload: externalPersonId }));
+          });
+
+    this.actionsSubject
+          .pipe(
+            ofType(externalPersonActions.loadExternalPersonDetailCommunicationsDataSuccess),
+            map((action: externalPersonActions.ILoadExternalPersonCommunicationsDataSuccess) => action.payload),
+            take(1),
+            takeUntil(this._endSubscriptions$)
+          )
+          .subscribe((communicationsData: Array<CommunicationsData>) => {
+            if (this._communicationTypes) {
+              for (let i = 0; i < this._communicationTypes.length; i++) {
+                const ct = this._communicationTypes[i];
+                const existingCommunicationsData: CommunicationsData = communicationsData.find(cd => cd.communicationTypeId == ct.id);
+                ct.isDisabled = existingCommunicationsData ? true : false;
+              }
+            }
+          });
   }
 
   public loadCommunicationsDataDetails(communicationsDataId: string): void {
@@ -268,6 +296,7 @@
   }
 
   public closeCommunicationsDataDetail(): void {
+    this.loadCommunicationsData(this._externalPersonContactId);
     this.clearCommunicationsData();
     this.isCommunicationsDataDetailViewVisible = false;
   }
diff --git a/src/app/pages/persons/internal-person/internal-person-details/communications-data-details/communications-data-details.component.html b/src/app/pages/persons/internal-person/internal-person-details/communications-data-details/communications-data-details.component.html
index c8871e3..9cde522 100644
--- a/src/app/pages/persons/internal-person/internal-person-details/communications-data-details/communications-data-details.component.html
+++ b/src/app/pages/persons/internal-person/internal-person-details/communications-data-details/communications-data-details.component.html
@@ -22,7 +22,7 @@
           class="form-control"
           [ngrxFormControlState]="((internalPersonDetailsSandbox.communicationsDataDetailsFormState$ | async)?.controls)['communicationTypeId']">
           <option [value]="">{{ 'SelectOption' | translate }}</option> -->
-          <option *ngFor="let communicationType of communicationTypesSandbox.communicationTypes$ | async" [value]="communicationType.id">{{communicationType.type}}</option>
+          <option *ngFor="let communicationType of communicationTypesSandbox.communicationTypes$ | async" [disabled]="communicationType.isDisabled" [value]="communicationType.id">{{communicationType.type}}</option>
         </select>
       </div>
     </div>
@@ -32,7 +32,7 @@
       <label for="communicationData" class="col-sm-4 col-form-label">{{ 'CommunicationsData.CommunicationData' | translate }}</label>
       <div  class="col-sm-7">
         <input type="text"
-                maxlength="30"
+                maxlength="1024"
                 class="form-control"
                 id="communicationData"
                 [ngrxFormControlState]="((internalPersonDetailsSandbox.communicationsDataDetailsFormState$ | async)?.controls)['communicationData']"
diff --git a/src/app/pages/persons/internal-person/internal-person-details/communications-data-details/communications-data-details.component.scss b/src/app/pages/persons/internal-person/internal-person-details/communications-data-details/communications-data-details.component.scss
index 4a90022..b959869 100644
--- a/src/app/pages/persons/internal-person/internal-person-details/communications-data-details/communications-data-details.component.scss
+++ b/src/app/pages/persons/internal-person/internal-person-details/communications-data-details/communications-data-details.component.scss
@@ -20,3 +20,6 @@
 div.form-group.row {
 	padding-left: 15px;
 }
+select option[disabled]{
+  background-color: rgb(160, 164, 168);
+}
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 d272a93..7b0cca7 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
@@ -14,7 +14,7 @@
 import { Injectable } from '@angular/core';
 import * as internalPersonActions from '@shared/store/actions/persons/internal-person.action';
 import { FormGroupState, SetValueAction, ResetAction, MarkAsTouchedAction } from 'ngrx-forms';
-import { InternalPerson, CommunicationsData } from '@shared/models';
+import { InternalPerson, CommunicationsData, CommunicationType } from '@shared/models';
 import { Observable } from 'rxjs';
 import * as store from '@shared/store';
 import { Store, ActionsSubject } from '@ngrx/store';
@@ -26,6 +26,7 @@
 import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
 import { SafetyQueryDialogComponent } from '@shared/components/dialogs/safety-query-dialog/safety-query-dialog.component';
 import * as internalCommunicationsDataDetailsFormReducer from '@shared/store/reducers/persons/internal-person/communications-data-details-form.reducer';
+import * as communicationTypesActions from '@shared/store/actions/admin/communication-types.action';
 
 @Injectable()
 export class InternalPersonDetailsSandBox extends BaseSandbox {
@@ -33,17 +34,16 @@
   public formState$: Observable<FormGroupState<InternalPerson>> = this.appState$.select(store.getInternalPersonDetails);
   public currentFormState: FormGroupState<InternalPerson>;
   public salutations$ = this.appState$.select(store.getSalutationsData);
-  private _currentInternalPerson: InternalPerson = null;
+  public isCommunicationsDataDetailViewVisible: boolean = false;
 
   public communicationsDataDetailsFormState$: Observable<FormGroupState<CommunicationsData>> = this.appState$.select(store.getInternalPersonCommunicationsDataDetails);
   public communicationsDataDetailsCurrentFormState: FormGroupState<CommunicationsData>;
-
   public communicationsDataList$: Observable<Array<CommunicationsData>> = this.appState$.select(store.getInternalCommunicationsDataData);
   public communicationsDataListLoading$: Observable<boolean> = this.appState$.select(store.getInternalCommunicationsDataLoading);
 
-  public isCommunicationsDataDetailViewVisible: boolean = false;
-
+  private _currentInternalPerson: InternalPerson = null;
   private _internalPersonContactId: string;
+  private _communicationTypes: Array<CommunicationType> = new Array<CommunicationType>();
 
   /**
    *  InternalPerson Sandbox constructor
@@ -173,9 +173,34 @@
   }
 
   public loadCommunicationsData(internalPersonId: string): void {
-    this.appState$.dispatch(
-      internalPersonActions.loadInternalPersonDetailCommunicationsData({ payload: internalPersonId })
-    );
+    this.actionsSubject
+          .pipe(
+            ofType(communicationTypesActions.loadCommunicationTypesSuccess),
+            map((action: communicationTypesActions.ILoadCommunicationTypesSuccess) => action.payload),
+            take(1),
+            takeUntil(this._endSubscriptions$)
+          )
+          .subscribe((payload: Array<CommunicationType>) => {
+            this._communicationTypes = payload;
+            this.appState$.dispatch(internalPersonActions.loadInternalPersonDetailCommunicationsData({ payload: internalPersonId }));
+          });
+
+    this.actionsSubject
+          .pipe(
+            ofType(internalPersonActions.loadInternalPersonDetailCommunicationsDataSuccess),
+            map((action: internalPersonActions.ILoadInternalPersonCommunicationsDataSuccess) => action.payload),
+            take(1),
+            takeUntil(this._endSubscriptions$)
+          )
+          .subscribe((communicationsData: Array<CommunicationsData>) => {
+            if (this._communicationTypes) {
+              for (let i = 0; i < this._communicationTypes.length; i++) {
+                const ct = this._communicationTypes[i];
+                const existingCommunicationsData: CommunicationsData = communicationsData.find(cd => cd.communicationTypeId == ct.id);
+                ct.isDisabled = existingCommunicationsData ? true : false;
+              }
+            }
+          });
   }
 
   public loadCommunicationsDataDetails(communicationsDataId: string): void {
@@ -221,6 +246,7 @@
   }
 
   public closeCommunicationsDataDetail(): void {
+    this.loadCommunicationsData(this._internalPersonContactId);
     this.clearCommunicationsData();
     this.isCommunicationsDataDetailViewVisible = false;
   }
diff --git a/src/app/shared/models/admin/communication-type.model.ts b/src/app/shared/models/admin/communication-type.model.ts
index 317a04c..b5f46aa 100644
--- a/src/app/shared/models/admin/communication-type.model.ts
+++ b/src/app/shared/models/admin/communication-type.model.ts
@@ -17,6 +17,7 @@
   public description: string = null;
   public editable: boolean = null;
   public mappingLdap: boolean = null;
+  public isDisabled: boolean = null;
 
   public constructor(data: any = null) {
     Object.keys(data || {})