Merge branch 'SI-77' of ssh://git.eclipse.org:29418/openk-usermodules/org.eclipse.openk-usermodules.gridFailureInformation.frontend into SI-444
diff --git a/projects/grid-failure-information-app/src/app/pages/grid-failure/grid-failure-api-client.ts b/projects/grid-failure-information-app/src/app/pages/grid-failure/grid-failure-api-client.ts
index 6dfd970..bcb49bb 100644
--- a/projects/grid-failure-information-app/src/app/pages/grid-failure/grid-failure-api-client.ts
+++ b/projects/grid-failure-information-app/src/app/pages/grid-failure/grid-failure-api-client.ts
@@ -22,6 +22,7 @@
   FailureState,
   FailureExpectedReason,
   FailureRadius,
+  FailureStation,
 } from '@grid-failure-information-app/shared/models';
 import { POST } from '@grid-failure-information-app/shared/async-services/http';
 
@@ -120,4 +121,10 @@
   public putGridFailuresCondensation(@Path('gridFailureId') gridFailureId: string, @Body() list: string[]): Observable<GridFailure[]> {
     return null;
   }
+
+  @GET('/stations')
+  @Adapter(GridFailureService.stationListAdapter)
+  public getGridFailureStations(): Observable<FailureStation[]> {
+    return null;
+  }
 }
diff --git a/projects/grid-failure-information-app/src/app/pages/grid-failure/grid-failure-details/grid-failure-details.component.html b/projects/grid-failure-information-app/src/app/pages/grid-failure/grid-failure-details/grid-failure-details.component.html
index b2590a9..d373824 100644
--- a/projects/grid-failure-information-app/src/app/pages/grid-failure/grid-failure-details/grid-failure-details.component.html
+++ b/projects/grid-failure-information-app/src/app/pages/grid-failure/grid-failure-details/grid-failure-details.component.html
@@ -449,9 +449,14 @@
                   type="text"
                   maxlength="255"
                   class="form-control"
+                  [ngbTypeahead]="gridFailureDetailsSandbox.searchForStation"
+                  [ngrxValueConverter]="gridFailureDetailsSandbox.stationValueConverter"
+                  (selectItem)="gridFailureDetailsSandbox.latLonMapping($event)"
                   id="stationDescription"
                   [ngrxFormControlState]="((gridFailureDetailsSandbox.gridFailureDetailsFormState$ | async)?.controls)['stationDescription']"
                   autocomplete="off"
+                  [resultFormatter]="gridFailureDetailsSandbox.formatter"
+                  [inputFormatter]="gridFailureDetailsSandbox.formatter"
                 />
               </div>
             </div>
diff --git a/projects/grid-failure-information-app/src/app/pages/grid-failure/grid-failure-details/grid-failure-details.sandbox.spec.ts b/projects/grid-failure-information-app/src/app/pages/grid-failure/grid-failure-details/grid-failure-details.sandbox.spec.ts
index 545dc1f..65e09dc 100644
--- a/projects/grid-failure-information-app/src/app/pages/grid-failure/grid-failure-details/grid-failure-details.sandbox.spec.ts
+++ b/projects/grid-failure-information-app/src/app/pages/grid-failure/grid-failure-details/grid-failure-details.sandbox.spec.ts
@@ -20,6 +20,7 @@
 import { of } from 'rxjs';
 import { Router } from '@angular/router';
 import { StateEnum } from '@grid-failure-information-app/shared/constants/enums';
+import { FailureStation } from '@grid-failure-information-app/shared/models';
 
 describe('GridFailureDetailsSandbox', () => {
   let service: GridFailureDetailsSandbox;
@@ -255,4 +256,44 @@
     expect(spySave).toHaveBeenCalled();
     expect(dispatchSpy).toHaveBeenCalled();
   });
+
+  it('should load GridFailureStations', () => {
+    service.loadGridFailureStations();
+    expect(dispatchSpy).toHaveBeenCalledWith(Object({ type: gridFailureActions.loadGridFailureStations.type }));
+  });
+
+  it('should map lon and lat values', () => {
+    const gfdetail = new GridFailure();
+    gfdetail.id = 'id';
+    gfdetail.responsibility = 'test';
+
+    service.currentFormState = {
+      ...service.currentFormState,
+      isValid: true,
+      value: gfdetail,
+    };
+
+    const event = { item: { longitude: 1.24, latitude: 1.23 } };
+
+    service.latLonMapping(event);
+
+    expect(dispatchSpy).toHaveBeenCalled();
+  });
+
+  it('should format Object to String', () => {
+    const station: FailureStation = {
+      g3efid: 0,
+      id: '',
+      longitude: 0,
+      latitude: 0,
+      sdoxl: 0,
+      sdoyl: 0,
+      stationId: '',
+      stationName: 'test',
+    };
+
+    const result = service.formatter(station);
+
+    expect(result).toBe('test');
+  });
 });
diff --git a/projects/grid-failure-information-app/src/app/pages/grid-failure/grid-failure-details/grid-failure-details.sandbox.ts b/projects/grid-failure-information-app/src/app/pages/grid-failure/grid-failure-details/grid-failure-details.sandbox.ts
index aedcb9c..d1d073a 100644
--- a/projects/grid-failure-information-app/src/app/pages/grid-failure/grid-failure-details/grid-failure-details.sandbox.ts
+++ b/projects/grid-failure-information-app/src/app/pages/grid-failure/grid-failure-details/grid-failure-details.sandbox.ts
@@ -28,13 +28,14 @@
   FailureState,
   FailureRadius,
   FailureExpectedReason,
+  FailureStation,
 } from '@grid-failure-information-app/shared/models';
 import { BaseFormSandbox } from '@grid-failure-information-app/shared/sandbox/base-form.sandbox';
 import * as store from '@grid-failure-information-app/shared/store';
 import * as gridFailureActions from '@grid-failure-information-app/shared/store/actions/grid-failures.action';
 import * as fromGridFailuresDetailFormReducer from '@grid-failure-information-app/shared/store/reducers/grid-failures/grid-failure-details-form.reducer';
 import * as gridFailuresDetailFormReducer from '@grid-failure-information-app/shared/store/reducers/grid-failures/grid-failure-details-form.reducer';
-import { dateTimeValueConverter, navigateHome } from '@grid-failure-information-app/shared/utility';
+import { dateTimeValueConverter, navigateHome, stationToStationNameConverter } from '@grid-failure-information-app/shared/utility';
 import { UtilService } from '@grid-failure-information-app/shared/utility/utility.service';
 import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
 import { ofType } from '@ngrx/effects';
@@ -42,7 +43,7 @@
 import { Moment } from 'moment';
 import { DisableAction, EnableAction, FormGroupState, NgrxValueConverter, ResetAction, SetValueAction } from 'ngrx-forms';
 import { Observable } from 'rxjs';
-import { take, takeUntil, map } from 'rxjs/operators';
+import { take, takeUntil, map, debounceTime, distinctUntilChanged } from 'rxjs/operators';
 import { Globals } from '@grid-failure-information-app/shared/constants/globals';
 import { StateEnum } from '@grid-failure-information-app/shared/constants/enums';
 
@@ -72,6 +73,7 @@
   public maxVersionNumber: number;
   public showQualifyButton: boolean = false;
   public showStornoButton: boolean = false;
+  private gridFailureStations: Array<FailureStation> = new Array<FailureStation>();
 
   private _gridFailureId: string;
   private _qualifyState: FailureState;
@@ -79,7 +81,7 @@
 
   constructor(
     protected appState$: Store<store.State>,
-    private _actionsSubject: ActionsSubject,
+    protected actionsSubject: ActionsSubject,
     private _router: Router,
     private _utilService: UtilService,
     private _modalService: NgbModal
@@ -117,6 +119,10 @@
     this.appState$.dispatch(gridFailureActions.loadGridFailureExpectedReasons());
   }
 
+  public loadGridFailureStations(): void {
+    this.appState$.dispatch(gridFailureActions.loadGridFailureStations());
+  }
+
   public loadGridFailureVersions(gridFailureId: string): void {
     this._gridFailureId = gridFailureId;
     this.appState$.dispatch(gridFailureActions.loadGridFailureVersions({ payload: gridFailureId }));
@@ -204,7 +210,7 @@
           payload: new GridFailure(this.currentFormState.value),
         })
       );
-      this._actionsSubject.pipe(ofType(gridFailureActions.saveGridFailureSuccess), take(1), takeUntil(this._endSubscriptions$)).subscribe(() => {
+      this.actionsSubject.pipe(ofType(gridFailureActions.saveGridFailureSuccess), take(1), takeUntil(this._endSubscriptions$)).subscribe(() => {
         this._clear();
       });
     } else {
@@ -217,11 +223,38 @@
       this.currentFormState = formState;
       this._showButtonsByState(formState.value.statusIntern);
     });
-    this._actionsSubject
+    this.actionsSubject
       .pipe(ofType(gridFailureActions.loadGridFailureVersionsSuccess), takeUntil(this._endSubscriptions$))
       .map(action => action['payload'])
       .map(gridFailureVersions => Math.max(...gridFailureVersions.map(o => o.versionNumber)))
       .subscribe(versionNumber => (this.maxVersionNumber = versionNumber));
+    this.actionsSubject
+      .pipe(
+        ofType(gridFailureActions.loadGridFailureStationsSuccess),
+        map(action => action.payload),
+        takeUntil(this._endSubscriptions$)
+      )
+      .subscribe((stations: Array<FailureStation>) => {
+        this.gridFailureStations = stations;
+      });
+  }
+
+  public searchForStation = (text$: Observable<string>) =>
+    text$.pipe(
+      debounceTime(200),
+      distinctUntilChanged(),
+      map(term => (term.length < 2 ? [] : this.gridFailureStations.filter(s => s.stationName.toLowerCase().indexOf(term.toLowerCase()) > -1)))
+    );
+
+  public formatter = (s: FailureStation) => s.stationName;
+
+  public stationValueConverter: NgrxValueConverter<any | null, string | null> = stationToStationNameConverter;
+
+  public latLonMapping(event) {
+    !!event &&
+      this.appState$.dispatch(
+        new SetValueAction(this.currentFormState.id, { ...this.currentFormState.value, longitude: event.item.longitude, latitude: event.item.longitude })
+      );
   }
 
   private _clear(): void {
diff --git a/projects/grid-failure-information-app/src/app/pages/grid-failure/grid-failure.module.ts b/projects/grid-failure-information-app/src/app/pages/grid-failure/grid-failure.module.ts
index 045af88..f2b3670 100644
--- a/projects/grid-failure-information-app/src/app/pages/grid-failure/grid-failure.module.ts
+++ b/projects/grid-failure-information-app/src/app/pages/grid-failure/grid-failure.module.ts
@@ -41,6 +41,7 @@
 import { UtilityModule } from '@grid-failure-information-app/shared/utility';
 import { PipesModule } from '@grid-failure-information-app/shared/pipes/pipes.module';
 import { GridFailureInformationMapModule } from 'openk/grid-failure-information-map/src/public-api';
+import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
 
 @NgModule({
   imports: [
@@ -64,6 +65,7 @@
     PipesModule,
     GridFailureRoutingModule,
     GridFailureInformationMapModule,
+    NgbModule,
   ],
   declarations: [GridFailureListComponent, GridFailureDetailsComponent],
   providers: [GridFailureSandbox, GridFailureDetailsSandbox, GridFailureService, GridFailureApiClient, GridFailuresResolver],
diff --git a/projects/grid-failure-information-app/src/app/pages/grid-failure/grid-failure.resolver.spec.ts b/projects/grid-failure-information-app/src/app/pages/grid-failure/grid-failure.resolver.spec.ts
index b90658e..5f42f3b 100644
--- a/projects/grid-failure-information-app/src/app/pages/grid-failure/grid-failure.resolver.spec.ts
+++ b/projects/grid-failure-information-app/src/app/pages/grid-failure/grid-failure.resolver.spec.ts
@@ -31,6 +31,7 @@
       loadGridFailureStates() {},
       loadGridFailureRadii() {},
       loadGridFailureExpectedReasons() {},
+      loadGridFailureStations() {},
     } as any;
   });
 
diff --git a/projects/grid-failure-information-app/src/app/pages/grid-failure/grid-failure.resolver.ts b/projects/grid-failure-information-app/src/app/pages/grid-failure/grid-failure.resolver.ts
index e04536c..7b4759d 100644
--- a/projects/grid-failure-information-app/src/app/pages/grid-failure/grid-failure.resolver.ts
+++ b/projects/grid-failure-information-app/src/app/pages/grid-failure/grid-failure.resolver.ts
@@ -35,5 +35,6 @@
     this._detailSandbox.loadGridFailureStates();
     this._detailSandbox.loadGridFailureRadii();
     this._detailSandbox.loadGridFailureExpectedReasons();
+    this._detailSandbox.loadGridFailureStations();
   }
 }
diff --git a/projects/grid-failure-information-app/src/app/pages/grid-failure/grid-failure.service.ts b/projects/grid-failure-information-app/src/app/pages/grid-failure/grid-failure.service.ts
index f7ed7bc..b333f10 100644
--- a/projects/grid-failure-information-app/src/app/pages/grid-failure/grid-failure.service.ts
+++ b/projects/grid-failure-information-app/src/app/pages/grid-failure/grid-failure.service.ts
@@ -19,6 +19,7 @@
   FailureState,
   FailureRadius,
   FailureExpectedReason,
+  FailureStation,
 } from '@grid-failure-information-app/shared/models';
 
 @Injectable()
@@ -54,4 +55,8 @@
   static expectedReasonListAdapter(response: any): Array<FailureExpectedReason> {
     return response.map(responseItem => new FailureExpectedReason(responseItem));
   }
+
+  static stationListAdapter(response: any): Array<FailureStation> {
+    return response.map(responseItem => new FailureStation(responseItem));
+  }
 }
diff --git a/projects/grid-failure-information-app/src/app/shared/models/failure.station.model.ts b/projects/grid-failure-information-app/src/app/shared/models/failure.station.model.ts
new file mode 100644
index 0000000..e46f42b
--- /dev/null
+++ b/projects/grid-failure-information-app/src/app/shared/models/failure.station.model.ts
@@ -0,0 +1,28 @@
+/********************************************************************************
+ * 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
+ ********************************************************************************/
+export class FailureStation {
+  public g3efid: number = null;
+  public id: string = null;
+  public longitude: number = null;
+  public latitude: number = null;
+  public sdoxl: number = null;
+  public sdoyl: number = null;
+  public stationId: string = null;
+  public stationName: string = null;
+
+  public constructor(data: any = null) {
+    Object.keys(data || {})
+      .filter(property => this.hasOwnProperty(property))
+      .forEach(property => (this[property] = data[property]));
+  }
+}
diff --git a/projects/grid-failure-information-app/src/app/shared/models/index.ts b/projects/grid-failure-information-app/src/app/shared/models/index.ts
index f8e95ba..288013d 100644
--- a/projects/grid-failure-information-app/src/app/shared/models/index.ts
+++ b/projects/grid-failure-information-app/src/app/shared/models/index.ts
@@ -18,3 +18,4 @@
 export * from './failure-state.model';
 export * from './failure-radius.model';
 export * from './failure-expected-reason.model';
+export * from './failure.station.model';
diff --git a/projects/grid-failure-information-app/src/app/shared/store/actions/grid-failures.action.ts b/projects/grid-failure-information-app/src/app/shared/store/actions/grid-failures.action.ts
index 6af74f5..2395748 100644
--- a/projects/grid-failure-information-app/src/app/shared/store/actions/grid-failures.action.ts
+++ b/projects/grid-failure-information-app/src/app/shared/store/actions/grid-failures.action.ts
@@ -19,6 +19,7 @@
   FailureState,
   FailureRadius,
   FailureExpectedReason,
+  FailureStation,
 } from '@grid-failure-information-app/shared/models';
 
 export interface ILoadGridFailuresSuccess {
@@ -94,3 +95,7 @@
 export const putGridFailuresCondensation = createAction('[CondensedGridFailures] Put', props<{ gridFailureId: string; payload: string[] }>());
 export const putGridFailuresCondensationSuccess = createAction('[CondensedGridFailures] Put Success', props<{ payload: GridFailure[] }>());
 export const putGridFailuresCondensationFail = createAction('[CondensedGridFailures] Put Fail', props<{ payload: string }>());
+
+export const loadGridFailureStations = createAction('[GridFailureStations] Load');
+export const loadGridFailureStationsSuccess = createAction('[GridFailureStations] Load Success', props<{ payload: Array<FailureStation> }>());
+export const loadGridFailureStationsFail = createAction('[GridFailureStations] Load Fail', props<{ payload: string }>());
diff --git a/projects/grid-failure-information-app/src/app/shared/store/effects/grid-failures.effect.spec.ts b/projects/grid-failure-information-app/src/app/shared/store/effects/grid-failures.effect.spec.ts
index 0240e07..2be5cab 100644
--- a/projects/grid-failure-information-app/src/app/shared/store/effects/grid-failures.effect.spec.ts
+++ b/projects/grid-failure-information-app/src/app/shared/store/effects/grid-failures.effect.spec.ts
@@ -21,6 +21,7 @@
   FailureState,
   FailureRadius,
   FailureExpectedReason,
+  FailureStation,
 } from '@grid-failure-information-app/shared/models';
 import * as gridFailureActions from '@grid-failure-information-app/shared/store/actions/grid-failures.action';
 import { GridFailureApiClient } from '@grid-failure-information-app/pages/grid-failure/grid-failure-api-client';
@@ -50,6 +51,7 @@
       postGridFailuresCondensation() {},
       putGridFailuresCondensation() {},
       getCondensedGridFailures() {},
+      getGridFailureStations() {},
     } as any;
     store = {
       dispatch() {},
@@ -330,4 +332,23 @@
     done();
     actions$.next(gridFailureActions.putGridFailuresCondensation({ gridFailureId: id, payload: apiResponse }));
   });
+
+  it('should equal getGridFailureStationsSuccess after getGridFailureStations', done => {
+    apiResponse = [new FailureStation({ id: '1' })];
+    spyOn(apiClient, 'getGridFailureStations').and.returnValue(of(apiResponse));
+    effects.getGridFailureStations$.pipe(take(1)).subscribe(result => {
+      expect(result).toEqual(gridFailureActions.loadGridFailureStationsSuccess({ payload: apiResponse }));
+    });
+    done();
+    actions$.next(gridFailureActions.loadGridFailureStations());
+  });
+
+  it('should equal getGridFailureStationsFail in response to getGridFailureStations Error', done => {
+    spyOn(apiClient, 'getGridFailureStations').and.returnValue(throwError('x'));
+    effects.getGridFailureStations$.pipe(take(1)).subscribe(result => {
+      expect(result).toEqual(gridFailureActions.loadGridFailureStationsFail({ payload: 'x' }));
+    });
+    done();
+    actions$.next(gridFailureActions.loadGridFailureStations());
+  });
 });
diff --git a/projects/grid-failure-information-app/src/app/shared/store/effects/grid-failures.effect.ts b/projects/grid-failure-information-app/src/app/shared/store/effects/grid-failures.effect.ts
index ab21fba..6cceb53 100644
--- a/projects/grid-failure-information-app/src/app/shared/store/effects/grid-failures.effect.ts
+++ b/projects/grid-failure-information-app/src/app/shared/store/effects/grid-failures.effect.ts
@@ -27,6 +27,7 @@
   FailureRadius,
   FailureBranch,
   FailureExpectedReason,
+  FailureStation,
 } from '@grid-failure-information-app/shared/models';
 import { Store } from '@ngrx/store';
 
@@ -211,5 +212,17 @@
     )
   );
 
+  getGridFailureStations$: any = createEffect(() =>
+    this._actions$.pipe(
+      ofType(gridFailureActions.loadGridFailureStations),
+      switchMap(action => {
+        return this._apiClient
+          .getGridFailureStations()
+          .map((response: FailureStation[]) => gridFailureActions.loadGridFailureStationsSuccess({ payload: response }))
+          .catch(error => of(gridFailureActions.loadGridFailureStationsFail({ payload: error })));
+      })
+    )
+  );
+
   constructor(private _actions$: Actions, private _apiClient: GridFailureApiClient, private _store: Store<any>) {}
 }
diff --git a/projects/grid-failure-information-app/src/app/shared/store/index.ts b/projects/grid-failure-information-app/src/app/shared/store/index.ts
index 8be237d..0506ef1 100644
--- a/projects/grid-failure-information-app/src/app/shared/store/index.ts
+++ b/projects/grid-failure-information-app/src/app/shared/store/index.ts
@@ -26,6 +26,7 @@
 import * as fromGridFailureStates from '@grid-failure-information-app/shared/store/reducers/grid-failures/grid-failure-states.reducer';
 import * as fromGridFailureRadii from '@grid-failure-information-app/shared/store/reducers/grid-failures/grid-failure-radii.reducer';
 import * as fromGridFailureExpectedReasons from '@grid-failure-information-app/shared/store/reducers/grid-failures/grid-failure-expected-reasons.reducer';
+import * as fromGridFailureStations from '@grid-failure-information-app/shared/store/reducers/grid-failures/grid-failure-stations.reducer';
 import * as fromGridFailuresDetailForm from '@grid-failure-information-app/shared/store/reducers/grid-failures/grid-failure-details-form.reducer';
 import * as fromCondensedGridFailures from '@grid-failure-information-app/shared/store/reducers/grid-failures/condensed-grid-failures.reducer';
 import { createFeatureSelector } from '@ngrx/store';
@@ -51,6 +52,7 @@
   gridFailureStates: fromGridFailureStates.State;
   gridFailureRadii: fromGridFailureRadii.State;
   gridFailureExpectedReasons: fromGridFailureExpectedReasons.State;
+  gridFailureStations: fromGridFailureStations.State;
   condensedGridFailures: fromCondensedGridFailures.State;
 }
 /**
@@ -74,6 +76,7 @@
   gridFailureStates: fromGridFailureStates.reducer,
   gridFailureRadii: fromGridFailureRadii.reducer,
   gridFailureExpectedReasons: fromGridFailureExpectedReasons.reducer,
+  gridFailureStations: fromGridFailureStations.reducer,
   condensedGridFailures: fromCondensedGridFailures.reducer,
 };
 
@@ -161,6 +164,13 @@
 export const getGridFailureExpectedReasonsFailed = createSelector(selectGridFailureExpectedReasons, fromGridFailureExpectedReasons.getFailed);
 export const getGridFailureExpectedReasonsData = createSelector(selectGridFailureExpectedReasons, fromGridFailureExpectedReasons.getData);
 
+// GridFailure stations
+export const selectGridFailureStations = createSelector(selectGridFailuresState, (state: GridFailureState) => state.gridFailureStations);
+export const getGridFailureStationsLoaded = createSelector(selectGridFailureStations, fromGridFailureStations.getLoaded);
+export const getGridFailureStationsLoading = createSelector(selectGridFailureStations, fromGridFailureStations.getLoading);
+export const getGridFailureStationsFailed = createSelector(selectGridFailureStations, fromGridFailureStations.getFailed);
+export const getGridFailureStationsData = createSelector(selectGridFailureStations, fromGridFailureStations.getData);
+
 // CondensedGridFailures
 export const selectCondensedGridFailures = createSelector(selectGridFailuresState, (state: GridFailureState) => state.condensedGridFailures);
 export const getCondensedGridFailuresLoaded = createSelector(selectCondensedGridFailures, fromCondensedGridFailures.getLoaded);
diff --git a/projects/grid-failure-information-app/src/app/shared/store/reducers/grid-failures/grid-failure-stations.reducer.spec.ts b/projects/grid-failure-information-app/src/app/shared/store/reducers/grid-failures/grid-failure-stations.reducer.spec.ts
new file mode 100644
index 0000000..fb4271c
--- /dev/null
+++ b/projects/grid-failure-information-app/src/app/shared/store/reducers/grid-failures/grid-failure-stations.reducer.spec.ts
@@ -0,0 +1,85 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+import {
+  GridFailureStationsReducer,
+  INITIAL_STATE,
+  getData,
+  getLoading,
+  getLoaded,
+  getFailed,
+  reducer,
+} from '@grid-failure-information-app/shared/store/reducers/grid-failures/grid-failure-stations.reducer';
+import * as gridFailureActions from '@grid-failure-information-app/shared/store/actions/grid-failures.action';
+import { FailureStation } from '@grid-failure-information-app/shared/models';
+
+describe('GridFailureStationsReducer', () => {
+  it('should return the initial state', () => {
+    const action = { type: 'NOOP' } as any;
+    const result = reducer(undefined, action);
+
+    expect(result).toBe(INITIAL_STATE);
+  });
+
+  it('should trigger loading state', () => {
+    const action = gridFailureActions.loadGridFailureStations();
+    const result = GridFailureStationsReducer(INITIAL_STATE, action);
+
+    expect(result).toEqual({
+      ...INITIAL_STATE,
+      loading: true,
+    });
+  });
+
+  it('should trigger loaded state', () => {
+    const items = { payload: [new FailureStation()] };
+    const action = gridFailureActions.loadGridFailureStationsSuccess(items);
+    const result = GridFailureStationsReducer(INITIAL_STATE, action);
+
+    expect(result.loaded).toBe(true);
+  });
+
+  it('should trigger failed state', () => {
+    const error = { payload: 'err_msg' };
+    const action = gridFailureActions.loadGridFailureStationsFail(error);
+    const result = GridFailureStationsReducer(INITIAL_STATE, action);
+
+    expect(result).toEqual({
+      ...INITIAL_STATE,
+      failed: true,
+    });
+  });
+
+  it('getData return state.data', () => {
+    const state = { ...INITIAL_STATE };
+    const result = getData(state);
+    expect(result).toBe(state.data);
+  });
+
+  it('getLoading return state.loading', () => {
+    const state = { ...INITIAL_STATE };
+    const result = getLoading(state);
+    expect(result).toBe(state.loading);
+  });
+
+  it('getLoaded return state.loaded', () => {
+    const state = { ...INITIAL_STATE };
+    const result = getLoaded(state);
+    expect(result).toBe(state.loaded);
+  });
+
+  it('getFailed return state.failed', () => {
+    const state = { ...INITIAL_STATE };
+    const result = getFailed(state);
+    expect(result).toBe(state.failed);
+  });
+});
diff --git a/projects/grid-failure-information-app/src/app/shared/store/reducers/grid-failures/grid-failure-stations.reducer.ts b/projects/grid-failure-information-app/src/app/shared/store/reducers/grid-failures/grid-failure-stations.reducer.ts
new file mode 100644
index 0000000..4de0241
--- /dev/null
+++ b/projects/grid-failure-information-app/src/app/shared/store/reducers/grid-failures/grid-failure-stations.reducer.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 * as gridFailureActions from '@grid-failure-information-app/shared/store/actions/grid-failures.action';
+import { FailureStation } from '@grid-failure-information-app/shared/models';
+import { createReducer, on } from '@ngrx/store';
+
+export interface State {
+  loading: boolean;
+  loaded: boolean;
+  failed: boolean;
+  data: Array<FailureStation>;
+}
+
+export const INITIAL_STATE: State = {
+  loading: false,
+  loaded: false,
+  failed: false,
+  data: [],
+};
+
+export const GridFailureStationsReducer = createReducer(
+  INITIAL_STATE,
+  on(gridFailureActions.loadGridFailureStations, (state: any, action: any) => {
+    return {
+      ...state,
+      loading: true,
+      loaded: false,
+      failed: false,
+      data: [],
+    };
+  }),
+  on(gridFailureActions.loadGridFailureStationsSuccess, (state: any, action: any) => {
+    return {
+      ...state,
+      loading: false,
+      loaded: true,
+      failed: false,
+      data: action['payload'],
+    };
+  }),
+  on(gridFailureActions.loadGridFailureStationsFail, (state: any, action: any) => {
+    return {
+      ...state,
+      loaded: false,
+      loading: false,
+      failed: true,
+      data: [],
+    };
+  })
+);
+
+export function reducer(state = INITIAL_STATE, action: any): State {
+  return GridFailureStationsReducer(state, action);
+}
+
+export const getData = (state: State) => state.data;
+export const getLoading = (state: State) => state.loading;
+export const getLoaded = (state: State) => state.loaded;
+export const getFailed = (state: State) => state.failed;
diff --git a/projects/grid-failure-information-app/src/app/shared/utility/utilityHelpers.ts b/projects/grid-failure-information-app/src/app/shared/utility/utilityHelpers.ts
index 59deca7..2d1cf77 100644
--- a/projects/grid-failure-information-app/src/app/shared/utility/utilityHelpers.ts
+++ b/projects/grid-failure-information-app/src/app/shared/utility/utilityHelpers.ts
@@ -82,3 +82,24 @@
     return '';
   }
 }
+
+/**
+ * Convert a station object to station name
+ */
+export const stationToStationNameConverter: NgrxValueConverter<any | null, string | null> = {
+  convertViewToStateValue(value) {
+    if (value === null) {
+      return null;
+    }
+
+    const result = value.stationName;
+    return NgrxValueConverters.objectToJSON.convertViewToStateValue(result);
+  },
+  convertStateToViewValue(value) {
+    if (value === null) {
+      return null;
+    }
+
+    return value;
+  },
+};