Merge branch 'DEVELOP' of ssh://git.eclipse.org:29418/openk-usermodules/org.eclipse.openk-usermodules.gridFailureInformation.frontend into SI-731-plz-based-distribution
diff --git a/i18n/distribution-group.de.json b/i18n/distribution-group.de.json
index 35afbb4..935d713 100644
--- a/i18n/distribution-group.de.json
+++ b/i18n/distribution-group.de.json
@@ -34,6 +34,13 @@
     "SalutationType": "Anrede",
     "PersonType": "Personentyp",
     "Department": "Abteilung",
-    "Export": "Export"
+    "Export": "Export",
+    "Postcodes": "PLZ"
+  },
+  "DistributionGroupMemberPostcodes": {
+    "Title": "PLZ",
+    "PostcodeInput": "Eingabe PLZ",
+    "AssignPostcode": "Hinzufügen",
+    "Postcode": "PLZ"
   }
 }
diff --git a/i18n/general.de.json b/i18n/general.de.json
index 97cc7dd..dd0753c 100644
--- a/i18n/general.de.json
+++ b/i18n/general.de.json
@@ -54,5 +54,7 @@
   "SelectedContactAlreadyAssigned": "Der ausgewählte Kontakt ist der Verteilergruppe bereits zugeordnet.",
   "NoContactSelected": "Es wurde kein Kontakt ausgewählt oder es wurde keine entsprechender gefunden.",
   "SelectedDistributionGroupAlreadyAssigned": "Die ausgewählte Verteilergruppe ist der Störinfo bereits zugeordnet.",
-  "SelectedStationAlreadyAssigned": "Die ausgewählte Station ist der Störungsmeldung bereits zugeordnet."
+  "SelectedStationAlreadyAssigned": "Die ausgewählte Station ist der Störungsmeldung bereits zugeordnet.",
+  "PostcodeNotNumber": "Bitte geben Sie eine Postleitzahl bestehend aus genau fünf Ziffern ein.",
+  "PostcodeAlreadyAssigned": "Diese Postleitzahl ist bereits zugeordnet"
 }
diff --git a/projects/grid-failure-information-app/src/app/pages/distribution-group/distribution-group-api-client.ts b/projects/grid-failure-information-app/src/app/pages/distribution-group/distribution-group-api-client.ts
index 1e5990f..9c9e21e 100644
--- a/projects/grid-failure-information-app/src/app/pages/distribution-group/distribution-group-api-client.ts
+++ b/projects/grid-failure-information-app/src/app/pages/distribution-group/distribution-group-api-client.ts
@@ -82,6 +82,16 @@
     return null;
   }
 
+  @PUT('/distribution-groups/{groupId}/members/{memberId}')
+  @Adapter(DistributionGroupService.itemAdapter)
+  public putDistributionGroupMember(
+    @Path('groupId') groupId: string,
+    @Path('memberId') memberId: string,
+    @Body() distributionGroupMember: DistributionGroupMember
+  ): Observable<DistributionGroupMember> {
+    return null;
+  }
+
   @GET('/contacts')
   @Adapter(DistributionGroupService.contactsPageAdapter)
   public getContacts(@Query('searchText') searchtext: string): Observable<Contact[]> {
diff --git a/projects/grid-failure-information-app/src/app/pages/distribution-group/distribution-group-details/distribution-group-details.component.html b/projects/grid-failure-information-app/src/app/pages/distribution-group/distribution-group-details/distribution-group-details.component.html
index db8183f..d874270 100644
--- a/projects/grid-failure-information-app/src/app/pages/distribution-group/distribution-group-details/distribution-group-details.component.html
+++ b/projects/grid-failure-information-app/src/app/pages/distribution-group/distribution-group-details/distribution-group-details.component.html
@@ -10,7 +10,7 @@
 *
 * SPDX-License-Identifier: EPL-2.0
 ********************************************************************************/ -->
-<form *ngIf="sandbox.distributionGroupDetailsFormState$ | async as formState" [ngrxFormState]="formState">
+<form class="detail-form" *ngIf="sandbox.distributionGroupDetailsFormState$ | async as formState" [ngrxFormState]="formState">
   <div class="form-group row detail-header">
     <span class="formTitle">{{ 'DistributionGroup.FormTitle' | translate }}</span>
     <div class="*visibleByRight">
diff --git a/projects/grid-failure-information-app/src/app/pages/distribution-group/distribution-group-details/distribution-group-details.component.scss b/projects/grid-failure-information-app/src/app/pages/distribution-group/distribution-group-details/distribution-group-details.component.scss
index 6ed3da9..30b26b1 100644
--- a/projects/grid-failure-information-app/src/app/pages/distribution-group/distribution-group-details/distribution-group-details.component.scss
+++ b/projects/grid-failure-information-app/src/app/pages/distribution-group/distribution-group-details/distribution-group-details.component.scss
@@ -36,3 +36,11 @@
 .save-button {
   margin-right: 10px;
 }
+
+.detail-form {
+  border: #bdc3c7;
+  border-style: solid;
+  padding: 10px;
+  margin-right: 16px;
+  border-width: thin;
+}
diff --git a/projects/grid-failure-information-app/src/app/pages/distribution-group/distribution-group-list/distribution-group-list.component.html b/projects/grid-failure-information-app/src/app/pages/distribution-group/distribution-group-list/distribution-group-list.component.html
index 0d30e0d..fe9150a 100644
--- a/projects/grid-failure-information-app/src/app/pages/distribution-group/distribution-group-list/distribution-group-list.component.html
+++ b/projects/grid-failure-information-app/src/app/pages/distribution-group/distribution-group-list/distribution-group-list.component.html
@@ -34,7 +34,10 @@
       >
       </ag-grid-angular>
       <app-spinner [isRunning]="sandbox.distributionGroupLoading$ | async"></app-spinner>
-      <app-distribution-group-members class="distribution-group-member"></app-distribution-group-members>
+      <div class="distribution-group-member-container">
+        <app-distribution-group-members class="distribution-group-member"></app-distribution-group-members>
+        <app-distribution-group-member-postcodes class="distribution-group-member-postcodes"></app-distribution-group-member-postcodes>
+      </div>
     </div>
   </div>
 </app-card-layout>
diff --git a/projects/grid-failure-information-app/src/app/pages/distribution-group/distribution-group-list/distribution-group-list.component.scss b/projects/grid-failure-information-app/src/app/pages/distribution-group/distribution-group-list/distribution-group-list.component.scss
index 1125bfa..ccf1ba6 100644
--- a/projects/grid-failure-information-app/src/app/pages/distribution-group/distribution-group-list/distribution-group-list.component.scss
+++ b/projects/grid-failure-information-app/src/app/pages/distribution-group/distribution-group-list/distribution-group-list.component.scss
@@ -31,3 +31,12 @@
   margin-top: 15px;
   flex-grow: 1;
 }
+
+.distribution-group-member-postcodes {
+  margin-top: 15px;
+  margin-left: 15px;
+}
+
+.distribution-group-member-container {
+  display: flex;
+}
diff --git a/projects/grid-failure-information-app/src/app/pages/distribution-group/distribution-group-list/distribution-group-list.component.ts b/projects/grid-failure-information-app/src/app/pages/distribution-group/distribution-group-list/distribution-group-list.component.ts
index 546f42a..c45878c 100644
--- a/projects/grid-failure-information-app/src/app/pages/distribution-group/distribution-group-list/distribution-group-list.component.ts
+++ b/projects/grid-failure-information-app/src/app/pages/distribution-group/distribution-group-list/distribution-group-list.component.ts
@@ -48,6 +48,7 @@
         this.sandbox.showMembersToSelectedGroup(event);
         this.sandbox.loadDistributionGroupDetail(event.data.id);
         this.sandbox.oldSelectedTemplate = DistributionPublicationStatusEnum.PUBLISH;
+        this.sandbox.selectedMemberRowIndex = 0;
       },
     };
     this.gridOptions.context = {
diff --git a/projects/grid-failure-information-app/src/app/pages/distribution-group/distribution-group-member-postcodes/distribution-group-member-postcodes-col-def.ts b/projects/grid-failure-information-app/src/app/pages/distribution-group/distribution-group-member-postcodes/distribution-group-member-postcodes-col-def.ts
new file mode 100644
index 0000000..8475ffb
--- /dev/null
+++ b/projects/grid-failure-information-app/src/app/pages/distribution-group/distribution-group-member-postcodes/distribution-group-member-postcodes-col-def.ts
@@ -0,0 +1,36 @@
+/********************************************************************************
+ * 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 { IconCellRendererComponent } from '@grid-failure-information-app/shared/components/cell-renderer/icon-cell-renderer/icon-cell-renderer.component';
+
+export const DISTRIBUTION_GROUP_MEMBER_POSTCODES_COLDEF = [
+  {
+    field: 'postcode',
+    headerName: 'DistributionGroupMemberPostcodes.Postcode',
+    sortable: true,
+    suppressMovable: true,
+    filter: 'setFilterComponent',
+  },
+  {
+    field: 'tools',
+    headerName: ' ',
+    pinned: 'right',
+    maxWidth: 50,
+    minWidth: 50,
+    lockPosition: true,
+    sortable: false,
+    filter: false,
+    suppressMenu: true,
+    suppressSizeToFit: true,
+    cellRendererFramework: IconCellRendererComponent,
+  },
+];
diff --git a/projects/grid-failure-information-app/src/app/pages/distribution-group/distribution-group-member-postcodes/distribution-group-member-postcodes.component.html b/projects/grid-failure-information-app/src/app/pages/distribution-group/distribution-group-member-postcodes/distribution-group-member-postcodes.component.html
new file mode 100644
index 0000000..5071caa
--- /dev/null
+++ b/projects/grid-failure-information-app/src/app/pages/distribution-group/distribution-group-member-postcodes/distribution-group-member-postcodes.component.html
@@ -0,0 +1,50 @@
+<!-- /********************************************************************************
+* 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
+********************************************************************************/ -->
+<div></div>
+<div class="table-menu">
+  <div class="table-menu-row">
+    <input
+      #postcodeInput
+      type="text"
+      size="5"
+      maxlength="5"
+      id="postcode-input"
+      autocomplete="off"
+      class="form-control"
+      placeholder="{{ 'DistributionGroupMemberPostcodes.Postcode' | translate }}"
+      onkeypress="return event.charCode >= 48 && event.charCode <= 57"
+      [disabled]="sandbox.disableMemberButton"
+    />
+    <button
+      type="button"
+      class="btn btn-primary btn-sm postcode-btn"
+      [disabled]="sandbox.disableMemberButton"
+      (click)="assignPostcode(postcodeInput.value); clearPostcodeInput()"
+    >
+      <i class="fa fa-plus"></i>
+    </button>
+  </div>
+</div>
+<div class="distribution-group-members">
+  <ag-grid-angular
+    autoResizeColumns
+    class="ag-theme-balham"
+    [gridOptions]="gridOptions"
+    [columnDefs]="columnDefinition"
+    [rowSelection]="'single'"
+    [frameworkComponents]="frameworkComponents"
+    [rowData]="sandbox.postcodes"
+    [overlayNoRowsTemplate]="noRowsTemplate"
+  >
+  </ag-grid-angular>
+</div>
diff --git a/projects/grid-failure-information-app/src/app/pages/distribution-group/distribution-group-member-postcodes/distribution-group-member-postcodes.component.scss b/projects/grid-failure-information-app/src/app/pages/distribution-group/distribution-group-member-postcodes/distribution-group-member-postcodes.component.scss
new file mode 100644
index 0000000..2724005
--- /dev/null
+++ b/projects/grid-failure-information-app/src/app/pages/distribution-group/distribution-group-member-postcodes/distribution-group-member-postcodes.component.scss
@@ -0,0 +1,20 @@
+/********************************************************************************
+ * 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
+ ********************************************************************************/
+
+.distribution-group-members {
+  height: 360px;
+}
+
+.postcode-btn {
+  margin-left: 10px;
+}
diff --git a/projects/grid-failure-information-app/src/app/pages/distribution-group/distribution-group-member-postcodes/distribution-group-member-postcodes.component.spec.ts b/projects/grid-failure-information-app/src/app/pages/distribution-group/distribution-group-member-postcodes/distribution-group-member-postcodes.component.spec.ts
new file mode 100644
index 0000000..7e73899
--- /dev/null
+++ b/projects/grid-failure-information-app/src/app/pages/distribution-group/distribution-group-member-postcodes/distribution-group-member-postcodes.component.spec.ts
@@ -0,0 +1,67 @@
+/********************************************************************************
+ * 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 { DistributionGroupSandbox } from '@grid-failure-information-app/app/pages/distribution-group/distribution-group.sandbox';
+import { DistributionGroupMemberPostcodesComponent } from '@grid-failure-information-app/app/pages/distribution-group/distribution-group-member-postcodes/distribution-group-member-postcodes.component';
+import { DistributionGroupMember } from '@grid-failure-information-app/shared/models';
+import { Subscription } from 'rxjs';
+
+describe('DistributionGroupMemberPostcodesComponent', () => {
+  let component: DistributionGroupMemberPostcodesComponent;
+  let sandbox: DistributionGroupSandbox;
+  interface PostcodeInterface {
+    postcode: string;
+  }
+
+  beforeEach(() => {
+    sandbox = {
+      getSelectedDistributionGroupMember() {
+        return new DistributionGroupMember();
+      },
+      displayPostcodeNotNumberNotification() {},
+      updateDistributionGroupMember() {},
+      deletePostcode() {},
+    } as any;
+    component = new DistributionGroupMemberPostcodesComponent(sandbox);
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+
+  it('should call appropriate function for delete event', () => {
+    const spy: any = spyOn(sandbox as any, 'deletePostcode');
+    component.ngOnInit();
+    component.gridOptions.context.eventSubject.next({ type: 'delete', data: new DistributionGroupMember() });
+    expect(spy).toHaveBeenCalled();
+  });
+
+  it('should call appropriate function for updating meber with new postcode when called with non-numeric input', () => {
+    const spy: any = spyOn(sandbox, 'displayPostcodeNotNumberNotification');
+    const input = '0774A';
+    component.assignPostcode(input);
+    expect(spy).toHaveBeenCalled();
+  });
+
+  it('should clear postcode input', () => {
+    component.postcodeInput = { nativeElement: { value: 'x' } };
+    component.clearPostcodeInput();
+    expect(component.postcodeInput.nativeElement.value).toBeFalsy();
+  });
+
+  it('should unsubscribe OnDestroy', () => {
+    component['_subscription'] = new Subscription();
+    const spy: any = spyOn(component['_subscription'], 'unsubscribe');
+    component.ngOnDestroy();
+    expect(spy).toHaveBeenCalled();
+  });
+});
diff --git a/projects/grid-failure-information-app/src/app/pages/distribution-group/distribution-group-member-postcodes/distribution-group-member-postcodes.component.ts b/projects/grid-failure-information-app/src/app/pages/distribution-group/distribution-group-member-postcodes/distribution-group-member-postcodes.component.ts
new file mode 100644
index 0000000..7e98b0b
--- /dev/null
+++ b/projects/grid-failure-information-app/src/app/pages/distribution-group/distribution-group-member-postcodes/distribution-group-member-postcodes.component.ts
@@ -0,0 +1,69 @@
+/********************************************************************************
+ * 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 { DistributionGroupSandbox, PostcodeInterface } from '@grid-failure-information-app/app/pages/distribution-group/distribution-group.sandbox';
+import { Component, OnInit, ViewChild, ElementRef } from '@angular/core';
+import { BaseList } from '@grid-failure-information-app/shared/components/base-components/base.list';
+import { Subscription } from 'rxjs';
+import { DISTRIBUTION_GROUP_MEMBER_POSTCODES_COLDEF } from '@grid-failure-information-app/app/pages/distribution-group/distribution-group-member-postcodes/distribution-group-member-postcodes-col-def';
+import { SetFilterComponent } from '@grid-failure-information-app/shared/filters/ag-grid/set-filter/set-filter.component';
+import { DIGITS_REGEXP } from '@grid-failure-information-app/shared/constants/regex.constants';
+
+@Component({
+  selector: 'app-distribution-group-member-postcodes',
+  templateUrl: './distribution-group-member-postcodes.component.html',
+  styleUrls: ['./distribution-group-member-postcodes.component.scss'],
+})
+export class DistributionGroupMemberPostcodesComponent extends BaseList implements OnInit {
+  @ViewChild('postcodeInput', { static: true }) postcodeInput: ElementRef;
+  public columnDefinition: any = DISTRIBUTION_GROUP_MEMBER_POSTCODES_COLDEF;
+  public frameworkComponents: { setFilterComponent: any };
+
+  private _subscription: Subscription;
+
+  constructor(public sandbox: DistributionGroupSandbox) {
+    super();
+    this.frameworkComponents = { setFilterComponent: SetFilterComponent };
+  }
+
+  ngOnInit() {
+    this.gridOptions.context = {
+      ...this.gridOptions.context,
+      icons: { delete: true },
+    };
+    this._subscription = this.gridOptions.context.eventSubject.subscribe(event => {
+      if (event.type === 'delete') {
+        this.sandbox.deletePostcode(event.data.postcode);
+      }
+    });
+  }
+
+  public assignPostcode(input: string) {
+    if (input) {
+      const regexp = RegExp(/^\d{5}$/);
+      if (regexp.test(input)) {
+        let postcode: PostcodeInterface = { postcode: input };
+        this.sandbox.addPostcode(postcode);
+      } else {
+        this.sandbox.displayPostcodeNotNumberNotification();
+      }
+    }
+  }
+
+  public clearPostcodeInput() {
+    this.postcodeInput.nativeElement.value = '';
+  }
+
+  public ngOnDestroy(): void {
+    this._subscription.unsubscribe();
+  }
+}
diff --git a/projects/grid-failure-information-app/src/app/pages/distribution-group/distribution-group-members/distribution-group-members-col-def.ts b/projects/grid-failure-information-app/src/app/pages/distribution-group/distribution-group-members/distribution-group-members-col-def.ts
index d22fa00..d2f650c 100644
--- a/projects/grid-failure-information-app/src/app/pages/distribution-group/distribution-group-members/distribution-group-members-col-def.ts
+++ b/projects/grid-failure-information-app/src/app/pages/distribution-group/distribution-group-members/distribution-group-members-col-def.ts
@@ -26,6 +26,7 @@
     sortable: true,
     filter: 'setFilterComponent',
     suppressMovable: true,
+    sort: 'asc',
   },
   {
     field: 'personType',
@@ -60,14 +61,21 @@
     headerName: 'DistributionGroupMember.MobileNumber',
     sortable: true,
     filter: 'setFilterComponent',
-    suppressMovable: true
+    suppressMovable: true,
+  },
+  {
+    field: 'postcodeList',
+    headerName: 'DistributionGroupMember.Postcodes',
+    sortable: true,
+    filter: 'setFilterComponent',
+    suppressMovable: true,
   },
   {
     field: 'tools',
     headerName: ' ',
     pinned: 'right',
-    maxWidth: 55,
-    minWidth: 55,
+    maxWidth: 50,
+    minWidth: 50,
     lockPosition: true,
     sortable: false,
     filter: false,
diff --git a/projects/grid-failure-information-app/src/app/pages/distribution-group/distribution-group-members/distribution-group-members.component.html b/projects/grid-failure-information-app/src/app/pages/distribution-group/distribution-group-members/distribution-group-members.component.html
index 6b22eb5..74b691f 100644
--- a/projects/grid-failure-information-app/src/app/pages/distribution-group/distribution-group-members/distribution-group-members.component.html
+++ b/projects/grid-failure-information-app/src/app/pages/distribution-group/distribution-group-members/distribution-group-members.component.html
@@ -48,6 +48,7 @@
     [frameworkComponents]="frameworkComponents"
     [rowData]="sandbox.disableMemberButton ? [] : (sandbox.distributionGroupMember$ | async)"
     [overlayNoRowsTemplate]="noRowsTemplate"
+    (gridReady)="onGridReady($event)"
   >
   </ag-grid-angular>
   <app-spinner [isRunning]="sandbox.distributionGroupMemberLoading$ | async"></app-spinner>
diff --git a/projects/grid-failure-information-app/src/app/pages/distribution-group/distribution-group-members/distribution-group-members.component.scss b/projects/grid-failure-information-app/src/app/pages/distribution-group/distribution-group-members/distribution-group-members.component.scss
index 1ae4450..34765bb 100644
--- a/projects/grid-failure-information-app/src/app/pages/distribution-group/distribution-group-members/distribution-group-members.component.scss
+++ b/projects/grid-failure-information-app/src/app/pages/distribution-group/distribution-group-members/distribution-group-members.component.scss
@@ -12,7 +12,7 @@
  ********************************************************************************/
 
 .distribution-group-members {
-  height: 340px;
+  height: 360px;
 }
 
 .group-member-search {
diff --git a/projects/grid-failure-information-app/src/app/pages/distribution-group/distribution-group-members/distribution-group-members.component.spec.ts b/projects/grid-failure-information-app/src/app/pages/distribution-group/distribution-group-members/distribution-group-members.component.spec.ts
index 37f8b75..237f33b 100644
--- a/projects/grid-failure-information-app/src/app/pages/distribution-group/distribution-group-members/distribution-group-members.component.spec.ts
+++ b/projects/grid-failure-information-app/src/app/pages/distribution-group/distribution-group-members/distribution-group-members.component.spec.ts
@@ -14,6 +14,7 @@
 import { DistributionGroupMembersComponent } from '@grid-failure-information-app/pages/distribution-group/distribution-group-members/distribution-group-members.component';
 import { DistributionGroupMember } from '@grid-failure-information-app/shared/models';
 import { Subscription } from 'rxjs';
+import { RowClickedEvent, ModelUpdatedEvent, RowNode, GridApi } from 'ag-grid-community';
 
 describe('DistributionGroupMembersComponent', () => {
   let component: DistributionGroupMembersComponent;
@@ -24,6 +25,8 @@
       registerEvents() {},
       endSubscriptions() {},
       deleteDistributionGroupMember() {},
+      transformPostcodes() {},
+      setSelectedDistributionGroupMember() {},
     } as any;
     component = new DistributionGroupMembersComponent(sandbox);
   });
@@ -58,4 +61,45 @@
     component.ngOnDestroy();
     expect(spy).toHaveBeenCalled();
   });
+
+  it('should call getDisplayedRowAtIndex on onModelUpdate event in ngOnInit()', () => {
+    let event = {
+      api: {
+        getDisplayedRowAtIndex(i: number) {
+          return {
+            setSelected(j: boolean): void {},
+          } as RowNode;
+        },
+      } as GridApi,
+    } as ModelUpdatedEvent;
+    const spy: any = spyOn(event.api, 'getDisplayedRowAtIndex');
+    component.ngOnInit();
+    component.gridOptions.onModelUpdated(event);
+    expect(spy).toHaveBeenCalled();
+  });
+
+  it('should set selectedMemberRowIndex on cellClickedEvent', () => {
+    let event: RowClickedEvent = {
+      type: 'cellClicked',
+      data: new DistributionGroupMember(),
+      rowIndex: 0,
+      column: {
+        getColDef() {
+          return { field: 'x' };
+        },
+      },
+    } as any;
+    component.ngOnInit();
+    component.gridOptions.onRowClicked(event);
+    expect(sandbox.selectedMemberRowIndex).toBe(0);
+  });
+
+  it('should set initial sorting', () => {
+    let sortModel;
+    let params = { api: { setSortModel: sortModel = {} } as any };
+    component['_gridApi'] = params.api;
+    const spy: any = spyOn(component['_gridApi'], 'setSortModel');
+    component.onGridReady(params);
+    expect(spy).toHaveBeenCalled();
+  });
 });
diff --git a/projects/grid-failure-information-app/src/app/pages/distribution-group/distribution-group-members/distribution-group-members.component.ts b/projects/grid-failure-information-app/src/app/pages/distribution-group/distribution-group-members/distribution-group-members.component.ts
index e18d537..1f3c300 100644
--- a/projects/grid-failure-information-app/src/app/pages/distribution-group/distribution-group-members/distribution-group-members.component.ts
+++ b/projects/grid-failure-information-app/src/app/pages/distribution-group/distribution-group-members/distribution-group-members.component.ts
@@ -16,6 +16,7 @@
 import { DISTRIBUTION_GROUP_MEMBER_COLDEF } from '@grid-failure-information-app/app/pages/distribution-group/distribution-group-members/distribution-group-members-col-def';
 import { SetFilterComponent } from '@grid-failure-information-app/shared/filters/ag-grid/set-filter/set-filter.component';
 import { Subscription } from 'rxjs';
+import { GridApi } from 'ag-grid-community';
 
 @Component({
   selector: 'app-distribution-group-members',
@@ -26,7 +27,9 @@
   @ViewChild('searchInput', { static: true }) searchInput: ElementRef;
   public columnDefinition: any = DISTRIBUTION_GROUP_MEMBER_COLDEF;
   public frameworkComponents: { setFilterComponent: any };
+
   private _subscription: Subscription;
+  private _gridApi: GridApi | null | undefined;
 
   constructor(public sandbox: DistributionGroupSandbox) {
     super();
@@ -34,10 +37,23 @@
   }
 
   ngOnInit() {
-    this.gridOptions.context = {
-      ...this.gridOptions.context,
-      icons: { delete: true },
-    };
+    (this.gridOptions = {
+      ...this.gridOptions,
+      onRowClicked: event => {
+        this.sandbox.selectedMemberRowIndex = event.rowIndex;
+        this.sandbox.setSelectedDistributionGroupMember(event.data);
+        this.sandbox.transformPostcodes();
+      },
+      onModelUpdated: event => {
+        if (event.api.getDisplayedRowAtIndex(this.sandbox.selectedMemberRowIndex)) {
+          event.api.getDisplayedRowAtIndex(this.sandbox.selectedMemberRowIndex).setSelected(true);
+        }
+      },
+    }),
+      (this.gridOptions.context = {
+        ...this.gridOptions.context,
+        icons: { delete: true },
+      });
     this._subscription = this.gridOptions.context.eventSubject.subscribe(event => {
       if (event.type === 'delete') {
         this.sandbox.deleteDistributionGroupMember(event.data.distributionGroupUuid, event.data.id);
@@ -45,6 +61,12 @@
     });
   }
 
+  public onGridReady(params): void {
+    this._gridApi = params.api;
+    const sortModel = [{ colId: 'name', sort: 'asc' }];
+    this._gridApi.setSortModel(sortModel);
+  }
+
   public clearSearchInput() {
     this.searchInput.nativeElement.value = '';
   }
diff --git a/projects/grid-failure-information-app/src/app/pages/distribution-group/distribution-group.module.ts b/projects/grid-failure-information-app/src/app/pages/distribution-group/distribution-group.module.ts
index 20a7bbd..caf50ac 100644
--- a/projects/grid-failure-information-app/src/app/pages/distribution-group/distribution-group.module.ts
+++ b/projects/grid-failure-information-app/src/app/pages/distribution-group/distribution-group.module.ts
@@ -34,6 +34,7 @@
 import { DistributionGroupResolver } from '@grid-failure-information-app/pages/distribution-group/distribution-group.resolver';
 import { DistributionGroupDetailsComponent } from '@grid-failure-information-app/pages/distribution-group/distribution-group-details/distribution-group-details.component';
 import { DistributionGroupMembersComponent } from '@grid-failure-information-app/pages/distribution-group/distribution-group-members/distribution-group-members.component';
+import { DistributionGroupMemberPostcodesComponent } from '@grid-failure-information-app/app/pages/distribution-group/distribution-group-member-postcodes/distribution-group-member-postcodes.component';
 
 @NgModule({
   imports: [
@@ -52,7 +53,12 @@
     DistributionGroupRoutingModule,
     NgbTypeaheadModule,
   ],
-  declarations: [DistributionGroupListComponent, DistributionGroupDetailsComponent, DistributionGroupMembersComponent],
+  declarations: [
+    DistributionGroupListComponent,
+    DistributionGroupDetailsComponent,
+    DistributionGroupMembersComponent,
+    DistributionGroupMemberPostcodesComponent,
+  ],
   providers: [DistributionGroupService, DistributionGroupApiClient, DistributionGroupSandbox, DistributionGroupResolver],
 })
 export class DistributionGroupModule {}
diff --git a/projects/grid-failure-information-app/src/app/pages/distribution-group/distribution-group.sandbox.spec.ts b/projects/grid-failure-information-app/src/app/pages/distribution-group/distribution-group.sandbox.spec.ts
index 139c0eb..f1a8ec5 100644
--- a/projects/grid-failure-information-app/src/app/pages/distribution-group/distribution-group.sandbox.spec.ts
+++ b/projects/grid-failure-information-app/src/app/pages/distribution-group/distribution-group.sandbox.spec.ts
@@ -20,6 +20,10 @@
 import { Contact, DistributionGroupMember, DistributionGroup } from '@grid-failure-information-app/shared/models';
 
 describe('DistributionGroupSandbox', () => {
+  interface PostcodeInterface {
+    postcode: string;
+  }
+
   let service: DistributionGroupSandbox;
   let appState: Store<store.State>;
   let actionsSubject: ActionsSubject;
@@ -32,7 +36,7 @@
     actionsSubject = { dispatch: () => {}, pipe: () => of(true), select: () => of(true) } as any;
     utilService = { displayNotification() {} } as any;
     modalService = { open() {} } as any;
-    spyAppStateDispatch=spyOn(appState, 'dispatch').and.callFake(() => {});
+    spyAppStateDispatch = spyOn(appState, 'dispatch').and.callFake(() => {});
 
     service = new DistributionGroupSandbox(appState, actionsSubject, utilService, modalService);
     service['_selectedDistributionGroup'] = new DistributionGroup({ id: 'x', emailSubjectView: 'emailSubjectView init' });
@@ -63,7 +67,7 @@
   });
 
   it('should call dispatch for saving an distribution group if a valid form state is provided', () => {
-    const spy: any = spyOn(service, 'saveDistributionGroup').and.callFake(()=>{});
+    const spy: any = spyOn(service, 'saveDistributionGroup').and.callFake(() => {});
     service.currentFormState = { isValid: true } as any;
     service.saveDistributionGroup();
     expect(spy).toHaveBeenCalled();
@@ -145,13 +149,12 @@
       value: {
         distributionTextView: '',
         emailSubjectView: '',
-
-      }
+      },
     };
-    service['currentFormState' as any]= formState;
+    service['currentFormState' as any] = formState;
 
-    service.changeEmailTemplate('complete','complete');
-     expect(spyAppStateDispatch).toHaveBeenCalledTimes(4);
+    service.changeEmailTemplate('complete', 'complete');
+    expect(spyAppStateDispatch).toHaveBeenCalledTimes(4);
   });
 
   it('should set update email text and subject to view binded properties in changeEmailTemplate() ', () => {
@@ -159,13 +162,12 @@
       value: {
         distributionTextView: '',
         emailSubjectView: '',
-
-      }
+      },
     };
-    service['currentFormState' as any]= formState;
+    service['currentFormState' as any] = formState;
 
-    service.changeEmailTemplate('update','update');
-     expect(spyAppStateDispatch).toHaveBeenCalledTimes(4);
+    service.changeEmailTemplate('update', 'update');
+    expect(spyAppStateDispatch).toHaveBeenCalledTimes(4);
   });
 
   it('should set publish email text and subject to view binded properties in changeEmailTemplate() ', () => {
@@ -173,13 +175,12 @@
       value: {
         distributionTextView: '',
         emailSubjectView: '',
-
-      }
+      },
     };
-    service['currentFormState' as any]= formState;
+    service['currentFormState' as any] = formState;
 
-    service.changeEmailTemplate('publish','publish');
-     expect(spyAppStateDispatch).toHaveBeenCalledTimes(4);
+    service.changeEmailTemplate('publish', 'publish');
+    expect(spyAppStateDispatch).toHaveBeenCalledTimes(4);
   });
 
   it('should make no changes in changeEmailTemplate() ', () => {
@@ -187,13 +188,12 @@
       value: {
         distributionTextView: '',
         emailSubjectView: '',
-
-      }
+      },
     };
-    service['currentFormState' as any]= formState;
+    service['currentFormState' as any] = formState;
 
-    service.changeEmailTemplate('','');
-     expect(spyAppStateDispatch).toHaveBeenCalledTimes(2);
+    service.changeEmailTemplate('', '');
+    expect(spyAppStateDispatch).toHaveBeenCalledTimes(2);
   });
 
   it('should exportContacts via exportContacts action', () => {
@@ -207,4 +207,73 @@
     service.exportContacts();
     expect(appState.dispatch).not.toHaveBeenCalled();
   });
+
+  it('should displayNotification via displayPostcodeNotNumberNotification()', () => {
+    const spy: any = spyOn(service['_utilService'], 'displayNotification');
+    service.displayPostcodeNotNumberNotification();
+    expect(service['_utilService'].displayNotification).toHaveBeenCalled();
+  });
+
+  it('should update distributionGroupMember', () => {
+    const postcodeList = ['test'];
+    service.updateDistributionGroupMember(postcodeList);
+    expect(appState.dispatch).toHaveBeenCalled();
+  });
+
+  it('should set _selectedDistributionGroupMember', () => {
+    const member = new DistributionGroupMember({ id: 'x' });
+    service.setSelectedDistributionGroupMember(member);
+    expect(service['_selectedDistributionGroupMember']).toEqual(member);
+  });
+
+  it('should updateMemeber for deleting a postcode', () => {
+    const spy: any = spyOn(service as any, '_updateMember');
+    service.deletePostcode('test');
+    expect(service['_updateMember']).toHaveBeenCalled();
+  });
+
+  it('should call appropriate function for updating member', () => {
+    const spy: any = spyOn(service, 'updateDistributionGroupMember');
+    let postcodes: PostcodeInterface[] = [{ postcode: '12345' }];
+    service['_updateMember'](postcodes);
+    expect(spy).toHaveBeenCalled();
+  });
+
+  it('should call not function for updating member if no postcodes are provided', () => {
+    const spy: any = spyOn(service, 'updateDistributionGroupMember');
+    let postcodes: PostcodeInterface[] = [];
+    service['_updateMember'](postcodes);
+    expect(spy).toHaveBeenCalledWith([]);
+  });
+
+  it('should updateMember to add a postcode', () => {
+    let input = { postcode: '12345' };
+    service.postcodes = [];
+    const spy: any = spyOn(service as any, '_updateMember');
+    service.addPostcode(input);
+    expect(service['_updateMember']).toHaveBeenCalled();
+  });
+
+  it('should display a notification if postcode is already assigned', () => {
+    let input = { postcode: '12345' };
+    service.postcodes = [{ postcode: '12345' }];
+    const spy: any = spyOn(service['_utilService'], 'displayNotification');
+    service.addPostcode(input);
+    expect(spy).toHaveBeenCalled();
+  });
+
+  it('should updateMember to add a postcode', () => {
+    let input = { postcode: '12345' };
+    service.postcodes = [{ postcode: '11111' }];
+    const spy: any = spyOn(service as any, '_updateMember');
+    service.addPostcode(input);
+    expect(service['_updateMember']).toHaveBeenCalled();
+  });
+
+  it('should transformPostcodes', () => {
+    let testMember = new DistributionGroupMember({ id: '1', postcodeList: ['11111'] });
+    service['_selectedDistributionGroupMember'] = testMember;
+    service.transformPostcodes();
+    expect(service.postcodes.length).toEqual(1);
+  });
 });
diff --git a/projects/grid-failure-information-app/src/app/pages/distribution-group/distribution-group.sandbox.ts b/projects/grid-failure-information-app/src/app/pages/distribution-group/distribution-group.sandbox.ts
index 4897f19..c60e386 100644
--- a/projects/grid-failure-information-app/src/app/pages/distribution-group/distribution-group.sandbox.ts
+++ b/projects/grid-failure-information-app/src/app/pages/distribution-group/distribution-group.sandbox.ts
@@ -29,6 +29,10 @@
 import { INITIAL_STATE } from '@grid-failure-information-app/shared/store/reducers/distribution-groups/distribution-group-details-form.reducer';
 import * as FileSaver from 'file-saver';
 
+export interface PostcodeInterface {
+  postcode: string;
+}
+
 @Injectable()
 export class DistributionGroupSandbox extends BaseSandbox {
   public distributionGroupList$: Observable<DistributionGroup[]> = this.appState$.select(store.getDistributionGroupsData);
@@ -42,9 +46,12 @@
   public distributionTemplate = DistributionPublicationStatusEnum;
   public selectedTemplate: string = DistributionPublicationStatusEnum.PUBLISH;
   public oldSelectedTemplate: string;
+  public selectedMemberRowIndex: number = 0;
+  public postcodes: PostcodeInterface[] = [];
   private _selectedDistributionGroup: DistributionGroup;
   private _selectedContact: Contact;
   private _distributionGroupMembers: Array<DistributionGroupMember>;
+  private _selectedDistributionGroupMember: DistributionGroupMember;
 
   constructor(
     protected appState$: Store<store.State>,
@@ -60,6 +67,7 @@
     this._clear();
     this.appState$.dispatch(new MarkAsTouchedAction(distributionGroupFormReducer.FORM_ID));
     this.disableMemberButton = true;
+    this.postcodes = [];
   }
 
   public loadDistributionGroups(): void {
@@ -107,6 +115,29 @@
     this.appState$.dispatch(distributionGroupActions.deleteDistributionGroupMember({ groupId: groupId, memberId: memberId }));
   }
 
+  public updateDistributionGroupMember(postcodeList: string[]): void {
+    let displayMainAddress: string = null;
+    if (
+      this._selectedDistributionGroupMember &&
+      this._selectedDistributionGroupMember.mainAddress &&
+      this._selectedDistributionGroupMember.mainAddress.trim().length > 0
+    ) {
+      displayMainAddress = this._selectedDistributionGroupMember.mainAddress;
+    }
+    this._selectedDistributionGroupMember = {
+      ...this._selectedDistributionGroupMember,
+      postcodeList: postcodeList,
+      displayMainAddress: displayMainAddress,
+    };
+    this.appState$.dispatch(
+      distributionGroupActions.updateDistributionGroupMember({
+        groupId: this._selectedDistributionGroup.id,
+        memberId: this._selectedDistributionGroupMember.id,
+        member: this._selectedDistributionGroupMember,
+      })
+    );
+  }
+
   public registerEvents(): void {
     this.distributionGroupDetailsFormState$.pipe(takeUntil(this._endSubscriptions$)).subscribe((formState: FormGroupState<DistributionGroup>) => {
       this.currentFormState = formState;
@@ -132,6 +163,10 @@
       )
       .subscribe((members: Array<DistributionGroupMember>) => {
         this._distributionGroupMembers = members;
+        if (!this._selectedDistributionGroupMember || this.selectedMemberRowIndex === 0) {
+          this._selectedDistributionGroupMember = this._distributionGroupMembers[0];
+        }
+        this.transformPostcodes();
       });
     this._actionsSubject
       .pipe(
@@ -228,6 +263,10 @@
     );
   }
 
+  public displayPostcodeNotNumberNotification() {
+    this._utilService.displayNotification('PostcodeNotNumber', 'alert');
+  }
+
   private _clear(): void {
     this.appState$.dispatch(new SetValueAction(distributionGroupFormReducer.FORM_ID, distributionGroupFormReducer.INITIAL_STATE.value));
     this.appState$.dispatch(new ResetAction(distributionGroupFormReducer.FORM_ID));
@@ -275,4 +314,56 @@
     this.appState$.dispatch(new SetValueAction(INITIAL_STATE.controls.emailSubjectView.id, emailsubject));
     this.appState$.dispatch(new SetValueAction(INITIAL_STATE.controls.distributionTextView.id, distributionText));
   }
+
+  public transformPostcodes() {
+    let postcodeStringArray: string[] = [];
+    if (this._selectedDistributionGroupMember || (this._distributionGroupMembers && this._distributionGroupMembers.length > 0)) {
+      postcodeStringArray = (this._selectedDistributionGroupMember ? this._selectedDistributionGroupMember : this._distributionGroupMembers[0]).postcodeList;
+    }
+    if (postcodeStringArray.length > 0) {
+      let postcodes: PostcodeInterface[] = [];
+      for (var index in postcodeStringArray) {
+        postcodes.push({ postcode: postcodeStringArray[index] });
+      }
+      this.postcodes = postcodes;
+    } else {
+      this.postcodes = [];
+    }
+  }
+
+  public setSelectedDistributionGroupMember(member: DistributionGroupMember): void {
+    this._selectedDistributionGroupMember = member;
+  }
+
+  public deletePostcode(postcodeString: string): void {
+    this.postcodes = this.postcodes.filter(item => item.postcode != postcodeString);
+    this._updateMember(this.postcodes);
+  }
+
+  public addPostcode(input: PostcodeInterface) {
+    let postcodeAlreadyAssigned = false;
+    if (this.postcodes.length > 0) {
+      for (var index in this.postcodes) {
+        if (this.postcodes[index].postcode === input.postcode) {
+          postcodeAlreadyAssigned = true;
+        }
+      }
+    }
+    if (postcodeAlreadyAssigned) {
+      this._utilService.displayNotification('PostcodeAlreadyAssigned', 'alert');
+    } else {
+      this.postcodes = [...this.postcodes, input];
+      this._updateMember(this.postcodes);
+    }
+  }
+
+  private _updateMember(postcodes: PostcodeInterface[]) {
+    let postcodeStringArray: string[] = [];
+    if (postcodes.length > 0) {
+      for (var index in postcodes) {
+        postcodeStringArray.push(postcodes[index].postcode);
+      }
+    }
+    this.updateDistributionGroupMember(postcodeStringArray);
+  }
 }
diff --git a/projects/grid-failure-information-app/src/app/shared/components/cell-renderer/icon-cell-renderer/icon-cell-renderer.component.html b/projects/grid-failure-information-app/src/app/shared/components/cell-renderer/icon-cell-renderer/icon-cell-renderer.component.html
index 2949616..b4ec432 100644
--- a/projects/grid-failure-information-app/src/app/shared/components/cell-renderer/icon-cell-renderer/icon-cell-renderer.component.html
+++ b/projects/grid-failure-information-app/src/app/shared/components/cell-renderer/icon-cell-renderer/icon-cell-renderer.component.html
@@ -29,3 +29,6 @@
 <div *ngIf="condensedIcon" (click)="clicked('loadCondensedItems')" class="tool-icon">
   <span class="badge badge-primary" id="condensedCount"> {{ params.data.condensedCount }}</span>
 </div>
+<button *ngIf="postcodeIcon" (click)="clicked('postcode')" class="tool-icon">
+  <img src="/assets/images/icons/plz1.png" alt="PLZ Icon" width="20" height="18" />
+</button>
diff --git a/projects/grid-failure-information-app/src/app/shared/components/cell-renderer/icon-cell-renderer/icon-cell-renderer.component.ts b/projects/grid-failure-information-app/src/app/shared/components/cell-renderer/icon-cell-renderer/icon-cell-renderer.component.ts
index 88a8288..d90ce3b 100644
--- a/projects/grid-failure-information-app/src/app/shared/components/cell-renderer/icon-cell-renderer/icon-cell-renderer.component.ts
+++ b/projects/grid-failure-information-app/src/app/shared/components/cell-renderer/icon-cell-renderer/icon-cell-renderer.component.ts
@@ -29,6 +29,7 @@
   public addIcon = null;
   public removeIcon = null;
   public condensedIcon = null;
+  public postcodeIcon = null;
   public params: any;
 
   private _modeEnum = ModeEnum;
@@ -46,6 +47,7 @@
       this.addIcon = !!contextIcons && !!contextIcons.add;
       this.removeIcon = !!contextIcons && !!contextIcons.remove;
       this.condensedIcon = !!contextIcons && !!contextIcons.loadCondensedItems;
+      this.postcodeIcon = !!contextIcons && !!contextIcons.postcode;
     }
   }
 
diff --git a/projects/grid-failure-information-app/src/app/shared/models/distribution-group-member.model.ts b/projects/grid-failure-information-app/src/app/shared/models/distribution-group-member.model.ts
index 46f06a1..8b58945 100644
--- a/projects/grid-failure-information-app/src/app/shared/models/distribution-group-member.model.ts
+++ b/projects/grid-failure-information-app/src/app/shared/models/distribution-group-member.model.ts
@@ -22,6 +22,7 @@
   public mobileNumber: string = null;
   public personType: string = null;
   public salutationType: string = null;
+  public postcodeList: string[] = [];
 
   public constructor(data: any = null) {
     Object.keys(data || {})
diff --git a/projects/grid-failure-information-app/src/app/shared/store/actions/distribution-groups.action.ts b/projects/grid-failure-information-app/src/app/shared/store/actions/distribution-groups.action.ts
index 7111d19..cc75bec 100644
--- a/projects/grid-failure-information-app/src/app/shared/store/actions/distribution-groups.action.ts
+++ b/projects/grid-failure-information-app/src/app/shared/store/actions/distribution-groups.action.ts
@@ -49,6 +49,13 @@
 export const createDistributionGroupMemberSuccess = createAction('[DistributionGroupMember] Create Success', props<{ payload: DistributionGroupMember }>());
 export const createDistributionGroupMemberFail = createAction('[DistributionGroupMember] Create Fail', props<{ payload: string }>());
 
+export const updateDistributionGroupMember = createAction(
+  '[DistributionGroupMember] Update',
+  props<{ groupId: string; memberId: string; member: DistributionGroupMember }>()
+);
+export const updateDistributionGroupMemberSuccess = createAction('[DistributionGroupMember] Update Success', props<{ payload: DistributionGroupMember }>());
+export const updateDistributionGroupMemberFail = createAction('[DistributionGroupMember] Update Fail', props<{ payload: string }>());
+
 export const loadDistributionGroupTextPlaceholders = createAction('[DistributionGroupTextPlaceholder] Load');
 export const loadDistributionGroupTextPlaceholdersSuccess = createAction(
   '[DistributionGroupTextPlaceholder] Load Success',
diff --git a/projects/grid-failure-information-app/src/app/shared/store/effects/distribution-groups.effect.spec.ts b/projects/grid-failure-information-app/src/app/shared/store/effects/distribution-groups.effect.spec.ts
index e9d511f..dcbe95e 100644
--- a/projects/grid-failure-information-app/src/app/shared/store/effects/distribution-groups.effect.spec.ts
+++ b/projects/grid-failure-information-app/src/app/shared/store/effects/distribution-groups.effect.spec.ts
@@ -38,6 +38,7 @@
       postDistributionGroupMember() {},
       getDistributionGroupTextPlaceholders() {},
       exportContacts() {},
+      putDistributionGroupMember() {},
     } as any;
     store = {
       dispatch() {},
@@ -211,6 +212,25 @@
     actions$.next(distributionGroupActions.createDistributionGroupMember({ groupId: 'x', newMember: new DistributionGroupMember({ id: '1' }) }));
   });
 
+  it('should equal updateDistributionGroupMemberSuccess after putDistributionGroupMember was called', done => {
+    apiResponse = [new DistributionGroupMember({ id: '1' })];
+    spyOn(apiClient, 'putDistributionGroupMember').and.returnValue(of(apiResponse));
+    effects.putDistributionGroupMember$.pipe(take(1)).subscribe(result => {
+      expect(result).toEqual(distributionGroupActions.updateDistributionGroupMemberSuccess({ payload: apiResponse }));
+    });
+    done();
+    actions$.next(distributionGroupActions.updateDistributionGroupMember({ groupId: 'x', memberId: 'y', member: new DistributionGroupMember({ id: '1' }) }));
+  });
+
+  it('should equal updateDistributionGroupMemberFail after putDistributionGroupMember Error', done => {
+    spyOn(apiClient, 'putDistributionGroupMember').and.returnValue(throwError('x'));
+    effects.putDistributionGroupMember$.pipe(take(1)).subscribe(result => {
+      expect(result).toEqual(distributionGroupActions.updateDistributionGroupMemberFail({ payload: 'x' }));
+    });
+    done();
+    actions$.next(distributionGroupActions.updateDistributionGroupMember({ groupId: 'x', memberId: 'y', member: new DistributionGroupMember({ id: '1' }) }));
+  });
+
   it('should equal loadDistributionGroupTextPlaceholdersSuccess after getDistributionTextPlaceholders was called', done => {
     apiResponse = new DistributionGroupTextPlaceholder();
     spyOn(apiClient, 'getDistributionGroupTextPlaceholders').and.returnValue(of(apiResponse));
diff --git a/projects/grid-failure-information-app/src/app/shared/store/effects/distribution-groups.effect.ts b/projects/grid-failure-information-app/src/app/shared/store/effects/distribution-groups.effect.ts
index 56bdf2a..f6e800b 100644
--- a/projects/grid-failure-information-app/src/app/shared/store/effects/distribution-groups.effect.ts
+++ b/projects/grid-failure-information-app/src/app/shared/store/effects/distribution-groups.effect.ts
@@ -19,7 +19,7 @@
 import * as distributionGroupActions from '@grid-failure-information-app/shared/store/actions/distribution-groups.action';
 import { DistributionGroupApiClient } from '@grid-failure-information-app/pages/distribution-group/distribution-group-api-client';
 import { catchError, map, switchMap, exhaustMap } from 'rxjs/operators';
-import { DistributionGroup, DistributionGroupTextPlaceholder } from '@grid-failure-information-app/shared/models';
+import { DistributionGroup, DistributionGroupMember } from '@grid-failure-information-app/shared/models';
 import { Store } from '@ngrx/store';
 
 @Injectable()
@@ -95,7 +95,11 @@
       map(action => action['payload']),
       switchMap((id: string) => {
         return this._apiClient.getDistributionGroupMembers(id).pipe(
-          map(item => distributionGroupActions.loadDistributionGroupMembersSuccess({ payload: item })),
+          map((groupMembers: DistributionGroupMember[]) => {
+            let members = distributionGroupActions.loadDistributionGroupMembersSuccess({ payload: groupMembers });
+            members.payload.sort((a, b) => a.name.localeCompare(b.name));
+            return members;
+          }),
           catchError(error => of(distributionGroupActions.loadDistributionGroupMembersFail({ payload: error })))
         );
       })
@@ -144,6 +148,21 @@
     )
   );
 
+  putDistributionGroupMember$: any = createEffect(() =>
+    this._actions$.pipe(
+      ofType(distributionGroupActions.updateDistributionGroupMember),
+      exhaustMap(action => {
+        return this._apiClient.putDistributionGroupMember(action.groupId, action.memberId, action.member).pipe(
+          map(item => {
+            this._store.dispatch(distributionGroupActions.loadDistributionGroupMembers({ payload: action.groupId }));
+            return distributionGroupActions.updateDistributionGroupMemberSuccess({ payload: item });
+          }),
+          catchError(error => of(distributionGroupActions.updateDistributionGroupMemberFail({ payload: error })))
+        );
+      })
+    )
+  );
+
   getDistributionTextPlaceholders$: any = createEffect(() =>
     this._actions$.pipe(
       ofType(distributionGroupActions.loadDistributionGroupTextPlaceholders),
diff --git a/projects/grid-failure-information-app/src/assets/images/icons/plz1.png b/projects/grid-failure-information-app/src/assets/images/icons/plz1.png
new file mode 100644
index 0000000..1fb22fc
--- /dev/null
+++ b/projects/grid-failure-information-app/src/assets/images/icons/plz1.png
Binary files differ