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

handle location form array

parent 4c1682c2
No related branches found
No related tags found
1 merge request!527NCM: service call
import {HttpParams} from '@angular/common/http';
import {computed, Injectable, Signal, signal} from '@angular/core'; import {computed, Injectable, Signal, signal} from '@angular/core';
import {FormBuilder} from '@angular/forms'; import {FormBuilder} from '@angular/forms';
import { import {
FormGroupControls,
NshmpService, NshmpService,
ServiceCallInfo, ServiceCallInfo,
SpinnerService, SpinnerService,
...@@ -8,10 +10,16 @@ import { ...@@ -8,10 +10,16 @@ import {
import { import {
DefaultPlotOptions, DefaultPlotOptions,
NshmpPlot, NshmpPlot,
PlotOptions,
plotUtils, plotUtils,
} from '@ghsc/nshmp-lib-ng/plot'; } from '@ghsc/nshmp-lib-ng/plot';
import {GeophysicalUsage} from '@ghsc/nshmp-utils-ts/libs/ncm/geophysical'; import {
GeophysicalResponse,
GeophysicalUsage,
} from '@ghsc/nshmp-utils-ts/libs/ncm/geophysical';
import {Location} from '@ghsc/nshmp-utils-ts/libs/nshmp-lib/geo';
import deepEqual from 'deep-equal'; import deepEqual from 'deep-equal';
import {PlotData} from 'plotly.js';
import {environment} from 'projects/nshmp-apps/src/environments/environment'; import {environment} from 'projects/nshmp-apps/src/environments/environment';
import {AppServiceModel} from 'projects/nshmp-apps/src/shared/models/app-service.model'; import {AppServiceModel} from 'projects/nshmp-apps/src/shared/models/app-service.model';
import {SharedService} from 'projects/nshmp-apps/src/shared/services/shared.service'; import {SharedService} from 'projects/nshmp-apps/src/shared/services/shared.service';
...@@ -35,7 +43,11 @@ export class AppService ...@@ -35,7 +43,11 @@ export class AppService
private serviceUrl = `${this.ncm.url}${this.ncm.services.geophysical}`; private serviceUrl = `${this.ncm.url}${this.ncm.services.geophysical}`;
/** Form group */ /** Form group */
formGroup = this.formBuilder.group<ControlForm>(this.defaultFormValues()); formGroup = this.formBuilder.group({
...this.defaultFormValues(),
locations: this.formBuilder.array([this.locationForm()]),
});
/** State */ /** State */
state = signal<AppState>(this.initialState()); state = signal<AppState>(this.initialState());
...@@ -70,36 +82,79 @@ export class AppService ...@@ -70,36 +82,79 @@ export class AppService
return computed(() => this.state().usageResponse); return computed(() => this.state().usageResponse);
} }
/**
* Add a new location form group to form array.
*/
addLocationForm(): void {
this.formGroup.controls.locations.controls.push(this.locationForm());
this.formGroup.controls.locations.updateValueAndValidity();
}
/**
* Add form validators
*/
addValidators(): void { addValidators(): void {
const controls = this.formGroup.controls; const controls = this.formGroup.controls;
controls.depthInc.addValidators(this.validateRequired()); controls.depthInc.addValidators(this.validateRequired());
controls.depthMax.addValidators(this.validateRequired()); controls.depthMax.addValidators(this.validateRequired());
controls.depthMin.addValidators(this.validateRequired()); controls.depthMin.addValidators(this.validateRequired());
controls.latitude.addValidators([ controls.locations.addValidators(this.validateRequired());
this.validateNan(),
this.validateRequired(),
]);
controls.longitude.addValidators([
this.validateNan(),
this.validateRequired(),
]);
} }
/**
* Call NCM geophysical web service
*/
callService(): void { callService(): void {
throw new Error('Method not implemented.'); const spinnerRef = this.spinnerService.show(SpinnerService.MESSAGE_SERVICE);
const values = this.formGroup.getRawValue();
const params = new HttpParams().appendAll({
depths: `${values.depthMin},${values.depthInc},${values.depthMax}`,
location: this.formGroup.controls.locations
.getRawValue()
.map(location => `${location.latitude},${location.longitude}`)
.join(','),
});
const url = `${this.serviceUrl}?${params.toString()}`;
this.nshmpService
.callService$<GeophysicalResponse>(url)
.pipe(
catchError((error: Error) => {
spinnerRef.close();
return this.nshmpService.throwError$(error);
})
)
.subscribe(serviceResponse => {
this.updateState({
serviceCallInfo: {
...this.state().serviceCallInfo,
serviceCalls: [url],
},
serviceResponse,
});
this.createPlots();
spinnerRef.close();
});
} }
/**
* Returns the default control form values.
*/
defaultFormValues(): ControlForm { defaultFormValues(): ControlForm {
return { return {
depthInc: 100, depthInc: 100,
depthMax: 2000, depthMax: 2000,
depthMin: 0, depthMin: 0,
latitude: null, locations: [],
longitude: null,
}; };
} }
/**
* Returns the default plots.
*/
defaultPlots(): Plots { defaultPlots(): Plots {
const xLabel = 'Depth (meters)'; const xLabel = 'Depth (meters)';
...@@ -137,6 +192,9 @@ export class AppService ...@@ -137,6 +192,9 @@ export class AppService
}; };
} }
/**
* Initialize application, call usage.
*/
init(): void { init(): void {
const spinnerRef = this.spinnerService.show( const spinnerRef = this.spinnerService.show(
SpinnerService.MESSAGE_METADATA SpinnerService.MESSAGE_METADATA
...@@ -163,6 +221,9 @@ export class AppService ...@@ -163,6 +221,9 @@ export class AppService
}); });
} }
/**
* Returns the initial state.
*/
initialState(): AppState { initialState(): AppState {
return { return {
plots: this.defaultPlots(), plots: this.defaultPlots(),
...@@ -184,9 +245,17 @@ export class AppService ...@@ -184,9 +245,17 @@ export class AppService
...this.defaultFormValues(), ...this.defaultFormValues(),
}); });
this.formGroup.controls.locations.clear();
this.addLocationForm();
this.resetState(); this.resetState();
} }
/**
* Update the state.
*
* @param state The partial state to update.
*/
updateState(state: Partial<AppState>): void { updateState(state: Partial<AppState>): void {
const updatedState = { const updatedState = {
...this.state(), ...this.state(),
...@@ -201,8 +270,40 @@ export class AppService ...@@ -201,8 +270,40 @@ export class AppService
} }
} }
/**
* Create the plots for service response.
*/
private createPlots(): void {
this.updateState({
plots: this.serviceResponseToPlots(),
});
}
/**
* Returns a default plot.
*
* @param options The plot options
*/
private defaultPlot(options: DefaultPlotOptions): NshmpPlot { private defaultPlot(options: DefaultPlotOptions): NshmpPlot {
const plotData = plotUtils.defaultPlot(options); const values = this.formGroup.getRawValue();
const plotOptions: PlotOptions = {
layout: {
xaxis: {
range: [values.depthMin, values.depthMax],
type: 'linear',
},
yaxis: {
range: [0, 100],
type: 'linear',
},
},
};
const plotData = plotUtils.defaultPlot({
...options,
mobileOptions: plotOptions,
options: plotOptions,
});
return { return {
label: options.title, label: options.title,
...@@ -214,6 +315,26 @@ export class AppService ...@@ -214,6 +315,26 @@ export class AppService
}; };
} }
/**
* Returns a new location form group for the form array.
*/
private locationForm(): FormGroupControls<Location> {
const form = this.formBuilder.group({
latitude: [NaN, [this.validateRequired(), this.validateNan()]],
longitude: [NaN, [this.validateRequired(), this.validateNan()]],
});
form.valueChanges.subscribe(() => {
this.formGroup.controls.locations.updateValueAndValidity();
this.formGroup.controls.locations.markAsDirty();
});
return form;
}
/**
* Reset the current state.
*/
private resetState(): void { private resetState(): void {
this.updateState({ this.updateState({
serviceCallInfo: { serviceCallInfo: {
...@@ -223,4 +344,102 @@ export class AppService ...@@ -223,4 +344,102 @@ export class AppService
serviceResponse: null, serviceResponse: null,
}); });
} }
/**
* Transform the service response to plots.
*/
private serviceResponseToPlots(): Plots {
const serviceResponse = this.state().serviceResponse;
if (serviceResponse === null || serviceResponse === undefined) {
return this.defaultPlots();
}
const temperaturePlotData: Partial<PlotData>[] = [];
const porosityPlotData: Partial<PlotData>[] = [];
const vsPlotData: Partial<PlotData>[] = [];
const vpPlotData: Partial<PlotData>[] = [];
const densityPlotData: Partial<PlotData>[] = [];
const xs = serviceResponse.request.depths.depth_vector;
serviceResponse.response.results.forEach(result => {
const name = `${result.location.latitude}, ${result.location.longitude}`;
temperaturePlotData.push({
mode: 'lines+markers',
name,
x: xs,
y: result.profile.temperature,
});
porosityPlotData.push({
mode: 'lines+markers',
name,
x: xs,
y: result.profile.porosity,
});
vpPlotData.push({
mode: 'lines+markers',
name,
x: xs,
y: result.profile.vp,
});
vsPlotData.push({
mode: 'lines+markers',
name,
x: xs,
y: result.profile.vs,
});
densityPlotData.push({
mode: 'lines+markers',
name,
x: xs,
y: result.profile.density,
});
});
const plots = this.plots();
return {
density: {
...plots.density,
plotData: {
...plots.density.plotData,
data: densityPlotData,
},
},
porosity: {
...plots.porosity,
plotData: {
...plots.porosity.plotData,
data: porosityPlotData,
},
},
temperature: {
...plots.temperature,
plotData: {
...plots.temperature.plotData,
data: temperaturePlotData,
},
},
vp: {
...plots.vp,
plotData: {
...plots.vp.plotData,
data: vpPlotData,
},
},
vs: {
...plots.vs,
plotData: {
...plots.vs.plotData,
data: vsPlotData,
},
},
};
}
} }
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