Skip to content
Snippets Groups Projects
Commit c5c600e9 authored by Clayton, Brandon Scott's avatar Clayton, Brandon Scott
Browse files

remove state

parent 6da2f1ea
No related branches found
No related tags found
1 merge request!446No NGRX: GMM magnitude
......@@ -2,8 +2,6 @@ import {Routes} from '@angular/router';
import {provideEffects} from '@ngrx/effects';
import {provideState} from '@ngrx/store';
import {MagnitudeAppEffects} from './magnitude/state/app.effects';
import {magnitudeAppFeature} from './magnitude/state/app.reducer';
import {SpectraAppEffects} from './spectra/state/app.effects';
import {spectraAppFeature} from './spectra/state/app.reducer';
......@@ -18,10 +16,6 @@ const routes: Routes = [
loadComponent: () =>
import('./magnitude/app.component').then(com => com.AppComponent),
path: 'magnitude',
providers: [
provideState(magnitudeAppFeature),
provideEffects(MagnitudeAppEffects),
],
},
{
loadComponent: () =>
......
import {
GmmMagnitudeResponse,
GmmMagnitudeUsage,
} from '@ghsc/nshmp-utils-ts/libs/nshmp-ws/gmm-services';
import {createActionGroup, emptyProps, props} from '@ngrx/store';
import {sharedActions} from 'projects/nshmp-apps/src/shared/state/shared';
/**
* GMM vs magnitude NGRX actions.
*/
export const actions = createActionGroup({
events: {
...sharedActions,
/** Action to set the initial form values from query or default */
'Initial Form Set': emptyProps(),
/** Service response action */
'Service Response': props<{serviceResponses: GmmMagnitudeResponse[]}>(),
/** Usage response action */
'Usage Response': props<{usageResponses: GmmMagnitudeUsage}>(),
},
source: 'GMM vs Magnitude',
});
import {Injectable} from '@angular/core';
import {gmmUtils} from '@ghsc/nshmp-lib-ng/gmm';
import {NshmpService, SpinnerService} from '@ghsc/nshmp-lib-ng/nshmp';
import {plotUtils} from '@ghsc/nshmp-lib-ng/plot';
import {
GmmMagnitudeResponse,
GmmMagnitudeUsage,
} from '@ghsc/nshmp-utils-ts/libs/nshmp-ws/gmm-services';
import {Actions, createEffect, ofType} from '@ngrx/effects';
import {concatLatestFrom} from '@ngrx/operators';
import {Store} from '@ngrx/store';
import {environment} from 'projects/nshmp-apps/src/environments/environment';
import {catchError, exhaustMap, map, mergeMap} from 'rxjs/operators';
import {defaultFormValues} from '../utils/app.default-values';
import {serviceResponseToPlotData} from '../utils/response.handler';
import {actions} from './app.actions';
import {AppFacade} from './app.facade';
import {magnitudeAppFeature} from './app.reducer';
/**
* NGRX application effects.
*/
@Injectable()
export class MagnitudeAppEffects {
/** nshmp-ws base URL */
baseUrl = environment.webServices.data.url;
/** GMM service URL */
serviceUrl = `${this.baseUrl}${environment.webServices.data.services.gmmMagnitude}`;
/**
* Call the services.
*/
callService$ = createEffect(() =>
this.actions$.pipe(
ofType(actions.callServices),
concatLatestFrom(() =>
this.store.select(magnitudeAppFeature.selectGmmMagnitudeAppState)
),
exhaustMap(([, state]) => {
this.spinnerService.show(SpinnerService.MESSAGE_SERVICE);
const urls = gmmUtils.serviceEndpoints(
this.serviceUrl,
state.controlForm.value,
state.controlForm.value.multiSelectableParam
);
return this.nshmpService.callServices$(urls).pipe(
mergeMap((serviceResponses: GmmMagnitudeResponse[]) => {
return [actions.serviceResponse({serviceResponses})];
}),
catchError((error: Error) => this.nshmpService.throwError$(error))
);
}),
catchError((error: Error) => this.nshmpService.throwError$(error))
)
);
/**
* Transform the service responses to plot data.
*/
createData$ = createEffect(() =>
this.actions$.pipe(
ofType(actions.serviceResponse),
concatLatestFrom(() =>
this.store.select(magnitudeAppFeature.selectGmmMagnitudeAppState)
),
map(([, state]) => {
const plots = plotUtils.updateAppPlotSettings(
serviceResponseToPlotData(state)
);
this.spinnerService.remove();
return actions.plots({plots});
}),
catchError((error: Error) => this.nshmpService.throwError$(error))
)
);
/**
* Initialize the application.
*/
init$ = createEffect(() =>
this.actions$.pipe(
ofType(actions.init),
concatLatestFrom(() =>
this.store.select(magnitudeAppFeature.selectControlForm)
),
exhaustMap(([, form]) => {
this.spinnerService.show(SpinnerService.MESSAGE_METADATA);
return this.nshmpService
.callService$<GmmMagnitudeUsage>(this.serviceUrl)
.pipe(
mergeMap(usage => {
const parameters = usage.response.parameters;
const controls = form.controls;
const values = defaultFormValues(parameters);
const typedActions = gmmUtils.initialFormSetActions(
form,
values,
parameters
);
typedActions.push(actions.usageResponse({usageResponses: usage}));
gmmUtils.addFormAction(
parameters.distance,
controls.distance.id,
values.distance,
typedActions
);
gmmUtils.addFormAction(
parameters.mMax,
controls.mMax.id,
values.mMax,
typedActions
);
gmmUtils.addFormAction(
parameters.mMin,
controls.mMin.id,
values.mMin,
typedActions
);
gmmUtils.addFormAction(
parameters.step,
controls.step.id,
values.step,
typedActions
);
this.spinnerService.remove();
return typedActions;
}),
catchError((error: Error) => this.nshmpService.throwError$(error))
);
}),
catchError((error: Error) => this.nshmpService.throwError$(error))
)
);
constructor(
private actions$: Actions,
private facade: AppFacade,
private nshmpService: NshmpService,
private spinnerService: SpinnerService,
private store: Store
) {}
}
import {GmmFormControlIds, gmmUtils} from '@ghsc/nshmp-lib-ng/gmm';
import {NshmpPlot} from '@ghsc/nshmp-lib-ng/plot';
import {createFeature, createReducer, createSelector, on} from '@ngrx/store';
import {
box,
createFormGroupState,
disable,
enable,
onNgrxForms,
onNgrxFormsAction,
setValue,
SetValueAction,
unbox,
updateGroup,
wrapReducerWithFormStateUpdate,
} from 'ngrx-forms';
import {environment} from 'projects/nshmp-apps/src/environments/environment';
import {
onPlotRedraw,
onPlotSettingsForm,
onResetSetting,
} from 'projects/nshmp-apps/src/shared/state/shared';
import {GmmMagnitudeFormControls} from '../models/gmm-magnitude-form-controls.model';
import {
defaultFormValues,
defaultPlots,
MEAN_PLOT_SETTING_ID,
SIGMA_PLOT_SETTING_ID,
} from '../utils/app.default-values';
import {validateControlPanelForm} from '../utils/control-panel.validators';
import {serviceResponseToPlotData} from '../utils/response.handler';
import {actions} from './app.actions';
import {AppState, CONTROL_FORM_ID, INITIAL_STATE} from './app.state';
/** Form state key ids */
const formKeys = {
control: {
gmmSource: `${CONTROL_FORM_ID}.${GmmFormControlIds.GMM_SOURCE}`,
multiSelectable: `${CONTROL_FORM_ID}.${GmmFormControlIds.MULTI_SELECTABLE_PARAM}`,
Mw: `${CONTROL_FORM_ID}.${GmmFormControlIds.MW}`,
showEpistemicUncertainty: `${CONTROL_FORM_ID}.${GmmFormControlIds.SHOW_EPISTEMIC_UNCERTAINTY}`,
vs30: `${CONTROL_FORM_ID}.${GmmFormControlIds.VS30}`,
},
settings: {
mean: MEAN_PLOT_SETTING_ID,
sigma: SIGMA_PLOT_SETTING_ID,
},
};
const baseUrl = environment.webServices.data.url;
const endpoint = environment.webServices.data.services.gmmMagnitude;
const serviceUrl = `${baseUrl}${endpoint}`;
/**
* NGRX application raw reducer.
*/
export const magnitudeAppFeature = createFeature({
extraSelectors: ({selectPlots}) => ({
selectMeanPlot: createSelector(selectPlots, plots =>
plots.get(gmmUtils.PlotType.MEANS)
),
selectSigmaPlot: createSelector(selectPlots, plots =>
plots.get(gmmUtils.PlotType.SIGMA)
),
}),
name: 'gmmMagnitudeApp',
reducer: createReducer(
/** Application intitial sate */
INITIAL_STATE,
/* On NGRX forms */
onNgrxForms(),
/* On form change */
onNgrxFormsAction(SetValueAction, (state, action) => {
const clearPlots = new Map<string, NshmpPlot>();
state.plots.forEach((plot, key) =>
clearPlots.set(key, {
...plot,
plotData: {
...plot.plotData,
data: [
...plot.plotData.data.map(data => {
data = {...data};
data.x = [];
data.y = [];
return data;
}),
],
},
})
);
const clearState: AppState = {
...state,
controlForm: updateGroup<GmmMagnitudeFormControls>({
showEpistemicUncertainty: control =>
disable(setValue(control, false)),
})(state.controlForm),
plots: clearPlots,
serviceResponses: null,
};
switch (action.controlId) {
case formKeys.control.multiSelectable: {
let form = {...clearState.controlForm};
const parameters =
clearState.usageResponses?.response?.parameters || null;
if (form.value.multiSelectableParam === GmmFormControlIds.VS30) {
form = updateGroup<GmmMagnitudeFormControls>({
gmmSource: gmm => setValue(gmm, box([])),
vs30: vs30 =>
setValue(vs30, (parameters.vs30.value as number) || null),
vs30Multi: vs30 => setValue(vs30, box([])),
})(clearState.controlForm);
}
return {
...clearState,
controlForm: form,
serviceCallInfo: gmmUtils.serviceCallInfo({
multiSelectableParam: form.value.multiSelectableParam,
serviceName: clearState.serviceCallInfo.serviceName,
serviceResponses: clearState.serviceResponses,
serviceUrl,
values: form.value,
}),
};
}
case formKeys.control.gmmSource: {
const gmm = unbox(clearState.controlForm.value.gmmSource);
const serviceCallInfo = gmmUtils.serviceCallInfo({
multiSelectableParam:
clearState.controlForm.value.multiSelectableParam,
serviceName: clearState.serviceCallInfo.serviceName,
serviceResponses: clearState.serviceResponses,
serviceUrl,
values: clearState.controlForm.value,
});
if (
clearState.usageResponses &&
clearState.controlForm.controls.gmmSource &&
gmm.length > 0
) {
const supportedImts = gmmUtils.getSupportedImts(
gmm,
clearState.usageResponses
);
const controlForm = gmmUtils.onGmmChange(
clearState.controlForm,
supportedImts
);
return {
...clearState,
controlForm,
serviceCallInfo,
supportedImts,
};
}
return {
...clearState,
serviceCallInfo,
};
}
case formKeys.control.showEpistemicUncertainty: {
return {
...state,
plots: serviceResponseToPlotData(state),
};
}
default: {
if (
action.controlId.includes(formKeys.settings.mean) ||
action.controlId.includes(formKeys.settings.sigma)
) {
return onPlotSettingsForm(state, action);
} else {
return {
...clearState,
serviceCallInfo: gmmUtils.serviceCallInfo({
multiSelectableParam:
clearState.controlForm.value.multiSelectableParam,
serviceName: clearState.serviceCallInfo.serviceName,
serviceResponses: clearState.serviceResponses,
serviceUrl,
values: clearState.controlForm.value,
}),
};
}
}
}
}),
/* On init action */
on(actions.init, () => {
return {
...INITIAL_STATE,
};
}),
/* On reset control panel action */
on(actions.resetControlPanel, state => {
const controlForm = createFormGroupState<GmmMagnitudeFormControls>(
CONTROL_FORM_ID,
defaultFormValues(state.usageResponses.response.parameters)
);
state = {
...state,
controlForm,
plots: INITIAL_STATE.plots,
serviceCallInfo: INITIAL_STATE.serviceCallInfo,
serviceResponses: INITIAL_STATE.serviceResponses,
};
return {
...state,
serviceCallInfo: gmmUtils.serviceCallInfo({
multiSelectableParam: state.controlForm.value.multiSelectableParam,
serviceName: state.serviceCallInfo.serviceName,
serviceResponses: state.serviceResponses,
serviceUrl,
values: state.controlForm.value,
}),
};
}),
/* On reset plot settings action */
on(actions.resetSettings, state => {
return onResetSetting(state, defaultPlots());
}),
/* On plots action */
on(actions.plots, (state, {plots}) => {
return {
...state,
plots,
};
}),
/* On plot redraw action */
on(actions.plotRedraw, state => {
return onPlotRedraw(state);
}),
/* On service response action */
on(actions.serviceResponse, (state, {serviceResponses}) => {
const means = serviceResponses.map(s => s.response.means);
const sigmas = serviceResponses.map(s => s.response.sigmas);
const hasLogicTree = gmmUtils.hasTree([...means, ...sigmas]);
state = {
...state,
controlForm: updateGroup<GmmMagnitudeFormControls>({
showEpistemicUncertainty: hasLogicTree ? enable : disable,
})(state.controlForm),
serviceResponses,
};
return {
...state,
serviceCallInfo: gmmUtils.serviceCallInfo({
multiSelectableParam: state.controlForm.value.multiSelectableParam,
serviceName: state.serviceCallInfo.serviceName,
serviceResponses: state.serviceResponses,
serviceUrl,
values: state.controlForm.value,
}),
};
}),
/* On service call info action */
on(actions.serviceCallInfo, (state, {serviceCallInfo}) => {
return {
...state,
serviceCallInfo: {
...state.serviceCallInfo,
...serviceCallInfo,
},
};
}),
/* On usage response action */
on(actions.usageResponse, (state, {usageResponses}) => {
return {
...state,
usageResponses,
};
})
),
});
/**
* Application NGRX reducer with validators.
*/
magnitudeAppFeature.reducer = wrapReducerWithFormStateUpdate(
magnitudeAppFeature.reducer,
state => state.controlForm,
validateControlPanelForm
);
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment