blob: 4c1fee7420ec22b25eb02192eb0b0b5a298bf604 [file] [log] [blame]
/********************************************************************************
* 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 { loadAddressCommunities } from '@grid-failure-information-app/shared/store/actions/grid-failures.action';
import { Injectable } from '@angular/core';
import { Router } from '@angular/router';
import { SafetyQueryDialogComponent } from '@grid-failure-information-app/shared/components/dialogs/safety-query-dialog/safety-query-dialog.component';
import { InternExternEnum, PressureLevelEnum, PublicationStatusEnum, StateEnum, VoltageLevelEnum } from '@grid-failure-information-app/shared/constants/enums';
import { Globals } from '@grid-failure-information-app/shared/constants/globals';
import {
FailureAddress,
FailureBranch,
FailureClassification,
FailureCoords,
FailureExpectedReason,
FailureHousenumber,
FailureRadius,
FailureState,
FailureStation,
FailureType,
GridFailure,
} 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 { navigateHome, stationToStationNameConverter as stationToStationDescriptionConverter } from '@grid-failure-information-app/shared/utility';
import { unboxProperties } from '@grid-failure-information-app/shared/utility/form-utils';
import { UtilService } from '@grid-failure-information-app/shared/utility/utility.service';
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
import { ofType } from '@ngrx/effects';
import { ActionsSubject, Store } from '@ngrx/store';
import { Observable } from 'rxjs';
import { debounceTime, distinctUntilChanged, map, take, takeUntil } from 'rxjs/operators';
import { FORM_ID, NO_BRANCH_ID_KEY } from '@grid-failure-information-app/shared/store/reducers/grid-failures/grid-failure-details-form.reducer';
import { FormGroupState, NgrxValueConverter, SetValueAction, ResetAction, EnableAction, SetUserDefinedPropertyAction, DisableAction } from 'ngrx-forms';
@Injectable()
export class GridFailureDetailsSandbox extends BaseFormSandbox<GridFailure> {
public Globals = Globals;
public StateEnum = StateEnum;
public gridFailureDetailsFormState$: Observable<FormGroupState<GridFailure>> = this.appState$.select(store.getGridFailuresDetails);
public currentFormState: FormGroupState<GridFailure>;
public gridFailureClassifications$: Observable<FailureClassification[]> = this.appState$.select(store.getGridFailureClassificationsData);
public gridFailureTypes$: Observable<FailureType[]> = this.appState$.select(store.getGridFailureTypesData);
public gridFailureBranches$: Observable<FailureBranch[]> = this.appState$.select(store.getGridFailureBranchesData);
public gridFailureActions = gridFailureActions;
public gridFailureInternalStates$: Observable<FailureState[]> = this.appState$
.select(store.getGridFailureStatesData)
.pipe(map(states => states.filter(item => item.internal)));
public gridFailureExternalStates$: Observable<FailureState[]> = this.appState$
.select(store.getGridFailureStatesData)
.pipe(map(states => states.filter(item => item.external)));
public gridFailureRadii$: Observable<FailureRadius[]> = this.appState$.select(store.getGridFailureRadiiData);
public gridFailureExpectedReasons$: Observable<FailureExpectedReason[]> = this.appState$.select(store.getGridFailureExpectedReasonsData);
public voltageLevelEnum = VoltageLevelEnum;
public pressureLevelEnum = PressureLevelEnum;
public publicationStatusEnum = PublicationStatusEnum;
public internExternEnum = InternExternEnum;
public maxVersionNumber: number;
public currentGridFailureDetailsCoords: FailureCoords = new FailureCoords();
public noBranchId: string;
public isFieldRequiredDependingOnBranchId: boolean = false;
public addressCommunities$: Observable<Array<string>> = this.actionsSubject.pipe(
ofType(gridFailureActions.loadAddressCommunitiesSuccess),
map(action => action.payload),
takeUntil(this._endSubscriptions$)
);
public addressDistricts$: Observable<Array<string>> = this.actionsSubject.pipe(
ofType(gridFailureActions.loadAddressDistrictsSuccess),
map(action => action.payload),
takeUntil(this._endSubscriptions$)
);
public addressStreets$: Observable<Array<string>> = this.actionsSubject.pipe(
ofType(gridFailureActions.loadAddressStreetsSuccess),
map(action => action.payload),
takeUntil(this._endSubscriptions$)
);
public addressHouseNumbers$: Observable<Array<string>> = this.actionsSubject.pipe(
ofType(gridFailureActions.loadAddressHouseNumbersSuccess),
map(action => action.payload),
map(payload => payload.map(adrs => adrs.housenumber)),
takeUntil(this._endSubscriptions$)
);
public addressHouseNumbers: Array<FailureHousenumber>;
public showQualifyButton: boolean = false;
public showStornoButton: boolean = false;
public showCreatedButton: boolean = false;
public showUpdateButton: boolean = false;
public gridFailureAddress: FailureAddress;
private _gridFailureStations: Array<FailureStation> = new Array<FailureStation>();
private _gridFailureId: string;
private _addressPostalcodes: Array<string> = [];
constructor(
protected appState$: Store<store.State>,
protected actionsSubject: ActionsSubject,
private _router: Router,
private _utilService: UtilService,
private _modalService: NgbModal
) {
super(appState$);
this.init();
}
public init() {
this.actionsSubject
.pipe(
ofType(gridFailureActions.loadAddressPostalcodesSuccess),
map(action => action.payload),
takeUntil(this._endSubscriptions$)
)
.subscribe((items: Array<string>) => {
this._addressPostalcodes = items;
});
this.setNoBranchId();
}
public loadGridFailure(gridFailureId: string): void {
this.appState$.dispatch(gridFailureActions.loadGridFailureDetail({ payload: gridFailureId }));
}
public loadGridFailureBranches(): void {
this.appState$.dispatch(gridFailureActions.loadGridFailureBranches());
}
public loadGridFailureClassifications(): void {
this.appState$.dispatch(gridFailureActions.loadGridFailureClassifications());
}
public loadGridFailureTypes(): void {
this.appState$.dispatch(gridFailureActions.loadGridFailureTypes());
}
public loadGridFailureStates(): void {
this.appState$.dispatch(gridFailureActions.loadGridFailureStates());
}
public loadGridFailureRadii(): void {
this.appState$.dispatch(gridFailureActions.loadGridFailureRadii());
}
public loadGridFailureExpectedReasons(): void {
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 }));
}
public loadGridFailureVersion(versionNumber: number): void {
this.appState$.dispatch(gridFailureActions.loadGridFailureVersion({ gridFailureId: this._gridFailureId, versionNumber: versionNumber }));
if (versionNumber < this.maxVersionNumber) {
this.appState$.dispatch(new DisableAction(fromGridFailuresDetailFormReducer.FORM_ID));
} else {
this.appState$.dispatch(new EnableAction(fromGridFailuresDetailFormReducer.FORM_ID));
}
}
public setState(newState: string): void {
this.gridFailureInternalStates$
.pipe(
map(states => states.filter(item => item.status === newState)),
take(1),
takeUntil(this._endSubscriptions$)
)
.subscribe(states => {
if (states && states.length > 0) {
this.appState$.dispatch(new SetValueAction(gridFailuresDetailFormReducer.INITIAL_STATE.controls.statusInternId.id, states[0].id));
this.saveGridFailure();
}
});
}
public cancel(): void {
if (!this.currentFormState.isPristine) {
const modalRef = this._modalService.open(SafetyQueryDialogComponent);
modalRef.componentInstance.title = 'ConfirmDialog.Action.edit';
modalRef.componentInstance.body = 'ConfirmDialog.Content';
modalRef.result.then(
() => {
this._clear();
},
() => {}
);
} else {
this._clear();
}
}
public saveGridFailure(): void {
if (this.currentFormState.isValid) {
const gridFailure = unboxProperties(this.currentFormState.value) as GridFailure;
this.appState$.dispatch(
gridFailureActions.saveGridFailure({
payload: gridFailure,
})
);
this.actionsSubject.pipe(ofType(gridFailureActions.saveGridFailureSuccess), take(1), takeUntil(this._endSubscriptions$)).subscribe(() => {
this._clear();
});
} else {
this._utilService.displayNotification('MandatoryFieldError', 'alert');
}
}
public setLatLong(hsnr: string): void {
const test$ = this.actionsSubject.pipe(
ofType(gridFailureActions.loadAddressHouseNumbersSuccess),
map(action => action.payload),
takeUntil(this._endSubscriptions$)
);
if (this.addressHouseNumbers.length > 0) {
const failureHousenumber: FailureHousenumber = this.addressHouseNumbers.find((housenumber: FailureHousenumber) => {
return housenumber.housenumber === hsnr;
});
if (!!failureHousenumber) {
this.appState$.dispatch(gridFailureActions.loadGridFailureAddress({ payload: failureHousenumber.uuid }));
}
return;
}
test$.pipe(take(1)).subscribe(addresses => {
const failureHousenumber: FailureHousenumber = addresses.find((housenumber: FailureHousenumber) => {
return housenumber.housenumber === hsnr;
});
if (!!failureHousenumber) {
this.appState$.dispatch(gridFailureActions.loadGridFailureAddress({ payload: failureHousenumber.uuid }));
}
});
}
public registerEvents(): void {
this.actionsSubject
.pipe(
ofType(gridFailureActions.loadAddressHouseNumbersSuccess),
map(action => action.payload),
takeUntil(this._endSubscriptions$)
)
.subscribe(hnr => (this.addressHouseNumbers = hnr));
this.gridFailureDetailsFormState$.pipe(takeUntil(this._endSubscriptions$)).subscribe((formState: FormGroupState<GridFailure>) => {
this.currentFormState = formState;
this._showButtonsByState(formState.value.statusIntern);
this.setDynamicRequired();
if (!formState.value || !formState.controls) return;
switch (formState.userDefinedProperties[fromGridFailuresDetailFormReducer.DEPENDENT_FIELD_KEY]) {
case formState.id:
this._loadInitialDependentFieldValues(formState);
break;
case formState.controls.postcode.id:
this.appState$.dispatch(gridFailureActions.loadAddressCommunities({ payload: formState.value.postcode }));
break;
case formState.controls.city.id:
this.appState$.dispatch(
gridFailureActions.loadAddressDistricts({
postcode: formState.value.postcode,
community: formState.value.city,
})
);
break;
case formState.controls.district.id:
this.appState$.dispatch(
gridFailureActions.loadAddressStreets({
postcode: formState.value.postcode,
community: formState.value.city,
district: formState.value.district,
})
);
break;
case formState.controls.street.id:
this.appState$.dispatch(
gridFailureActions.loadAddressHouseNumbers({
postcode: formState.value.postcode,
community: formState.value.city,
street: formState.value.street,
})
);
break;
case formState.controls.housenumber.id:
this.setLatLong(formState.controls.housenumber.value);
break;
default:
break;
}
});
this.actionsSubject
.pipe(
ofType(gridFailureActions.loadGridFailureVersionsSuccess),
takeUntil(this._endSubscriptions$),
map(action => {
const gridFailures: GridFailure[] = action['payload'];
return !!gridFailures && Math.max(...gridFailures.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;
});
this.actionsSubject
.pipe(
ofType(gridFailureActions.loadGridFailureAddressSuccess),
map(action => action.payload),
takeUntil(this._endSubscriptions$)
)
.subscribe((address: FailureAddress) => {
this.gridFailureAddress = address;
const event = { longitude: address.longitude, latitude: address.latitude };
this.latLonMapping(event);
});
this.gridFailureDetailsFormState$.subscribe(gridFailureDetails => {
if (
this.currentGridFailureDetailsCoords.latitude !== gridFailureDetails.value.latitude ||
this.currentGridFailureDetailsCoords.longitude !== gridFailureDetails.value.longitude
) {
this.currentGridFailureDetailsCoords = new FailureCoords(gridFailureDetails.value);
}
});
}
public searchForStation = (text$: Observable<string>) =>
text$.pipe(
debounceTime(200),
distinctUntilChanged(),
map(term => (term.length < 2 ? [] : this._gridFailureStations.filter(s => s.failureStationSearchString.toLowerCase().indexOf(term.toLowerCase()) > -1)))
);
public formatter = (s: FailureStation | string) => {
if (s instanceof FailureStation) return s.failureStationSearchString;
else return s;
};
public stationValueConverter: NgrxValueConverter<any | null, string | null> = stationToStationDescriptionConverter;
public latLonMapping(data: { longitude: number; latitude: number }): void {
!!data &&
this.appState$.dispatch(
new SetValueAction(this.currentFormState.id, {
...this.currentFormState.value,
longitude: data.longitude,
latitude: data.latitude,
})
);
}
public setStationId(stationId: string): void {
!!stationId &&
this.appState$.dispatch(
new SetValueAction(this.currentFormState.id, {
...this.currentFormState.value,
stationId: stationId,
})
);
}
public resetCoords(): void {
this.appState$.dispatch(
new SetValueAction(this.currentFormState.id, {
...this.currentFormState.value,
longitude: null,
latitude: null,
})
);
}
public resetStationId() {
this.appState$.dispatch(
new SetValueAction(this.currentFormState.id, {
...this.currentFormState.value,
stationId: null,
})
);
}
public searchForAddressPostalcodes = (text$: Observable<string>) =>
text$.pipe(
debounceTime(300),
distinctUntilChanged(),
map(term => (term.length < 2 ? [] : this._addressPostalcodes.filter(v => v.toLowerCase().indexOf(term.toLowerCase()) > -1)))
);
public resetFailureLocationValues() {
this.appState$.dispatch(
new SetValueAction(this.currentFormState.id, {
...this.currentFormState.value,
stationDescription: null,
stationId: null,
latitude: null,
longitude: null,
postcode: null,
district: null,
city: null,
street: null,
housenumber: null,
radius: null,
radiusId: null,
})
);
}
public disableUnnecessaryRequiredProperties(part: string): void {
switch (part) {
case Globals.FAILURE_LOCATION_NS:
this.appState$.dispatch(new EnableAction(fromGridFailuresDetailFormReducer.INITIAL_STATE.controls.postcode.id));
this.appState$.dispatch(new DisableAction(fromGridFailuresDetailFormReducer.INITIAL_STATE.controls.radiusId.id));
break;
case Globals.FAILURE_LOCATION_MS:
this._disableAddressControls();
this.appState$.dispatch(new EnableAction(fromGridFailuresDetailFormReducer.INITIAL_STATE.controls.radiusId.id));
break;
case Globals.FAILURE_LOCATION_MAP:
this.appState$.dispatch(new DisableAction(fromGridFailuresDetailFormReducer.INITIAL_STATE.controls.radiusId.id));
this._disableAddressControls();
break;
default:
break;
}
}
private _disableAddressControls(): void {
this.appState$.dispatch(new DisableAction(fromGridFailuresDetailFormReducer.INITIAL_STATE.controls.postcode.id));
this.appState$.dispatch(new DisableAction(fromGridFailuresDetailFormReducer.INITIAL_STATE.controls.city.id));
this.appState$.dispatch(new DisableAction(fromGridFailuresDetailFormReducer.INITIAL_STATE.controls.district.id));
this.appState$.dispatch(new DisableAction(fromGridFailuresDetailFormReducer.INITIAL_STATE.controls.street.id));
this.appState$.dispatch(new DisableAction(fromGridFailuresDetailFormReducer.INITIAL_STATE.controls.housenumber.id));
}
public isAddressLoaded(): Observable<boolean> {
return this.actionsSubject.pipe(
ofType(loadAddressCommunities.type),
map(item => true),
take(1)
);
}
private _loadInitialDependentFieldValues(formState: FormGroupState<GridFailure>) {
if (!formState.value || !formState.controls) return;
this.appState$.dispatch(gridFailureActions.loadAddressCommunities({ payload: formState.value.postcode }));
this.appState$.dispatch(
gridFailureActions.loadAddressDistricts({
postcode: formState.value.postcode,
community: formState.value.city,
})
);
this.appState$.dispatch(
gridFailureActions.loadAddressStreets({
postcode: formState.value.postcode,
community: formState.value.city,
district: formState.value.district,
})
);
this.appState$.dispatch(
gridFailureActions.loadAddressHouseNumbers({
postcode: formState.value.postcode,
community: formState.value.city,
street: formState.value.street,
})
);
}
public loadAddressPostalcodes(): void {
this.appState$.dispatch(gridFailureActions.loadAddressPostalcodes());
}
private setNoBranchId(): void {
this.gridFailureBranches$.subscribe((branches: FailureBranch[]) => {
if (branches.length > 0) {
const noBranch: FailureBranch = branches.find(branch => branch.name === Globals.NO_BRANCH_NAME);
this.noBranchId = !!noBranch ? noBranch.id : null;
this.appState$.dispatch(new SetUserDefinedPropertyAction(FORM_ID, NO_BRANCH_ID_KEY, this.noBranchId));
}
});
}
private _clear(): void {
this.appState$.dispatch(new SetValueAction(fromGridFailuresDetailFormReducer.FORM_ID, fromGridFailuresDetailFormReducer.INITIAL_STATE.value));
this.appState$.dispatch(new ResetAction(fromGridFailuresDetailFormReducer.FORM_ID));
this.appState$.dispatch(new EnableAction(fromGridFailuresDetailFormReducer.FORM_ID));
this._gridFailureId = null;
this.maxVersionNumber = null;
navigateHome(this._router);
}
private setDynamicRequired(): void {
this.isFieldRequiredDependingOnBranchId =
!!this.currentFormState.controls && !!this.currentFormState.controls.branchId ? this.currentFormState.controls.branchId.value !== this.noBranchId : null;
}
private _showButtonsByState(state: string): void {
this.showQualifyButton = false;
this.showStornoButton = false;
this.showCreatedButton = false;
this.showUpdateButton = false;
switch (state) {
case StateEnum.NEW:
case StateEnum.PLANNED:
this.showCreatedButton = true;
break;
case StateEnum.CREATED:
case StateEnum.UPDATED:
this.showQualifyButton = true;
this.showStornoButton = true;
break;
case StateEnum.QUALIFIED:
this.showUpdateButton = true;
break;
default:
break;
}
}
}