- Abfragebeispiele ogc service

- legend-entry-component: jum to first or last value of a dataset
- npm updates
This commit is contained in:
Arno Kaimbacher 2021-10-22 15:43:32 +02:00
parent cd4119b986
commit 9579a23e8e
10 changed files with 2082 additions and 1691 deletions

136
AbfrageBeispielSOSOGC.json Normal file
View file

@ -0,0 +1,136 @@
{
"request": "GetObservation",
"service": "SOS",
"version": "2.0.0",
"procedure": "laakirchen_10",
"offering": "laakirchen_10",
"observedProperty": "Slope",
"spatialFilter": {
"bbox": {
"ref": "om:featureOfInterest/sams:SF_SpatialSamplingFeature/sams:shape",
"value": {
"type": "Polygon",
"coordinates": [
[
[
10.817907,
47.215147
],
[
11.116667,
47.215147
],
[
11.116667,
47.333300
],
[
10.817907,
47.333300
]
]
]
}
}
},
"temporalFilter": {
"during": {
"ref": "om:phenomenonTime",
"value": [
"2010-11-19T14:00:00+01:00",
"2015-11-19T15:00:00+01:00"
]
}
}
}
{
"request": "GetObservation",
"service": "SOS",
"version": "2.0.0",
"featureOfInterest": [
"GSA02B-007-0911"
],
"observedProperty": [
"Slope"
],
"procedure": [
"laakirchen_10"
],
"temporalFilter": {
"during": {
"ref": "om:phenomenonTime",
"value": [
"2011-12-07T00:00:00Z",
"2011-12-14T00:00:00Z"
]
}
},
"spatialFilter": {
"bbox": {
"ref": "om:featureOfInterest/sams:SF_SpatialSamplingFeature/sams:shape",
"value": {
"type": "Polygon",
"coordinates": [
[
[
9.47996951665,
46.4318173285
],
[
16.9796667823,
46.4318173285
],
[
16.9796667823,
49.0390742051
],
[
9.47996951665,
49.0390742051
]
]
]
}
}
}
}
"spatialFilter": {
"bbox": {
"ref": "om:featureOfInterest/sams:SF_SpatialSamplingFeature/sams:shape",
"value": {
"type": "Polygon",
"coordinates": [
[
[
9.47996951665,
46.4318173285
],
[
16.9796667823,
46.4318173285
],
[
16.9796667823,
49.0390742051
],
[
9.47996951665,
49.0390742051
]
]
]
}
}
}
(9.47996951665,
46.4318173285,
16.9796667823,
49.0390742051

3394
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,5 @@
<div id="geomon-legend-entry" class="legendItem" style="position: relative;"
<div id="geomon-legend-entry" class="legendItem" style="position: relative;" [ngStyle]="{'border-color': datasetOption?.color}" [ngStyle]="{'border-color': datasetOption?.color}" [ngClass]="{'selected': selected}" (click)="toggleSelection();">
[ngClass]="{'selected': selected}" (click)="toggleSelection();">
<!-- <div class="loading-overlay" *ngIf="loading" [ngStyle]="{'background-color': datasetOption?.color}"> <!-- <div class="loading-overlay" *ngIf="loading" [ngStyle]="{'background-color': datasetOption?.color}">
<div class="fa fa-refresh fa-spin fa-3x fa-fw"></div> <div class="fa fa-refresh fa-spin fa-3x fa-fw"></div>
</div> --> </div> -->
@ -38,8 +37,27 @@
</div> </div>
<div class="legendicons"> <div class="legendicons">
<!-- <span class="fa" [ngClass]="{'fa-eye-slash': datasetOption?.visible, 'fa-eye': !datasetOption?.visible}" (click)="toggleVisibility(); $event.stopPropagation();"></span> --> <!-- <span class="fa" [ngClass]="{'fa-eye-slash': datasetOption?.visible, 'fa-eye': !datasetOption?.visible}" (click)="toggleVisibility(); $event.stopPropagation();"></span> -->
<fa-icon [icon]="datasetOption?.visible ? faEye : faEyeSlash" (click)="toggleVisibility(); $event.stopPropagation();"></fa-icon> <fa-icon [icon]="datasetOption?.visible ? faEye : faEyeSlash"
</div> (click)="toggleVisibility(); $event.stopPropagation();"></fa-icon>
</div>
<div class="collapseLegendEntry small-label">
<div class="firstLastEntry additionalLegendEntry" *ngIf="firstValue"
(click)="jumpToFirstTimeStamp(); $event.stopPropagation();">
<fa-icon [icon]="faChevronRight"></fa-icon>
<span>Erster Wert bei </span>
<span>{{ firstValue.timestamp }}</span>
<span class="hidden-medium">({{ firstValue.value }} {{uom}})</span>
</div>
<div class="firstLastEntry additionalLegendEntry" *ngIf="lastValue"
(click)="jumpToLastTimeStamp(); $event.stopPropagation();">
<fa-icon [icon]="faChevronRight"></fa-icon>
<span>Letzter Wert bei</span>
<span>{{lastValue.timestamp }}</span>
<span class="hidden-medium">({{lastValue.value}} {{uom}})</span>
</div>
</div>
</div> </div>
</div> </div>

View file

@ -6,7 +6,8 @@ import { TimeInterval } from '../../../shared/models/timespan';
import { DatasetApiService } from '../../services/dataset-api.service'; import { DatasetApiService } from '../../services/dataset-api.service';
import { InternalIdHandler, InternalDatasetId } from '../../../common/components/services/internal-id-handler.service'; import { InternalIdHandler, InternalDatasetId } from '../../../common/components/services/internal-id-handler.service';
import { DatasetOptions } from '../../../shared/models/options'; import { DatasetOptions } from '../../../shared/models/options';
import { faEye, faEyeSlash } from '@fortawesome/free-solid-svg-icons'; import { faEye, faEyeSlash, faChevronRight } from '@fortawesome/free-solid-svg-icons';
import { FirstLastValue } from '../../../shared/models/dataset';
@Component({ @Component({
selector: 'geomon-legend-entry', selector: 'geomon-legend-entry',
@ -21,10 +22,11 @@ export class LegendEntryComponent {
public onSelectDate: EventEmitter<Date> = new EventEmitter(); public onSelectDate: EventEmitter<Date> = new EventEmitter();
faEye = faEye; faEye = faEye;
faEyeSlash= faEyeSlash; faEyeSlash = faEyeSlash;
faChevronRight = faChevronRight;
// public firstValue: FirstLastValue; public firstValue: FirstLastValue;
// public lastValue: FirstLastValue; public lastValue: FirstLastValue;
public hasData = true; public hasData = true;
public informationVisible = false; public informationVisible = false;
@ -84,6 +86,13 @@ export class LegendEntryComponent {
} }
public jumpToFirstTimeStamp() {
this.onSelectDate.emit(new Date(this.dataset.firstValue.timestamp));
}
public jumpToLastTimeStamp() {
this.onSelectDate.emit(new Date(this.dataset.lastValue.timestamp));
}
protected loadDataset(locale?: string): void { protected loadDataset(locale?: string): void {
const params: DatasetFilter = {}; const params: DatasetFilter = {};
@ -123,23 +132,38 @@ export class LegendEntryComponent {
this.procedureLabel = this.dataset.parameters.procedure.label; this.procedureLabel = this.dataset.parameters.procedure.label;
this.categoryLabel = this.dataset.parameters.category.label; this.categoryLabel = this.dataset.parameters.category.label;
this.uom = this.dataset.uom; this.uom = this.dataset.uom;
}
public toggleSelection() { this.firstValue = this.dataset.firstValue;
this.lastValue = this.dataset.lastValue;
// this.checkDataInTimespan();
}
// private checkDataInTimespan() {
// if (this.timeInterval && this.dataset && this.dataset.firstValue && this.dataset.lastValue) {
// this.hasData = this.timeSrvc.overlaps(
// this.timeInterval,
// this.dataset.firstValue.timestamp,
// this.dataset.lastValue.timestamp
// );
// }
// }
public toggleSelection() {
this.selected = !this.selected; this.selected = !this.selected;
this.onSelectDataset.emit(this.selected); this.onSelectDataset.emit(this.selected);
} }
public toggleVisibility() { public toggleVisibility() {
this.datasetOption.visible = !this.datasetOption.visible; this.datasetOption.visible = !this.datasetOption.visible;
this.onUpdateOptions.emit(this.datasetOption); this.onUpdateOptions.emit(this.datasetOption);
} }
public editDatasetOptions() { public editDatasetOptions() {
// this.onEditOptions.emit(this.datasetOptions); // this.onEditOptions.emit(this.datasetOptions);
} }
public showGeometry() { public showGeometry() {
this.onShowGeometry.emit(this.dataset.platform.geometry); this.onShowGeometry.emit(this.dataset.platform.geometry);
} }

View file

@ -24,14 +24,14 @@ export class PlatformDetailComponent implements OnInit {
private datasetService: DatasetApiService, private datasetService: DatasetApiService,
private location: Location private location: Location
) { ) {
this.getHero(); this.getPlatform();
} }
ngOnInit(): void { ngOnInit(): void {
// this.getHero(); // this.getHero();
} }
getHero(): void { getPlatform(): void {
const id = String(this.route.snapshot.paramMap.get('id')); const id = String(this.route.snapshot.paramMap.get('id'));
this.datasetService.getPlatform(id, 'https://geomon.geologie.ac.at/52n-sos-webapp/api/') this.datasetService.getPlatform(id, 'https://geomon.geologie.ac.at/52n-sos-webapp/api/')
.subscribe({ .subscribe({

View file

@ -129,7 +129,9 @@ export class DatasetApiService {
const url = this.createRequestUrl(apiUrl, 'datasets', id); const url = this.createRequestUrl(apiUrl, 'datasets', id);
return this.requestApi<GeomonTimeseries>(url, params, options) return this.requestApi<GeomonTimeseries>(url, params, options)
.pipe( .pipe(
map((res) => this.prepareDataset(res, apiUrl)) map(
(res) => this.prepareDataset(res, apiUrl)
)
); );
} }

View file

@ -10,7 +10,7 @@
<div class="input-area is-4 column"> <div class="input-area is-4 column">
<div *ngFor="let id of datasetIds"> <div *ngFor="let id of datasetIds">
<geomon-legend-entry [datasetId]="id" [datasetOption]="datasetOptions.get(id)" (onSelectDataset)="onSelectDataset($event, id)" (onUpdateOptions)="onUpdateOptions($event, id)"> <geomon-legend-entry [datasetId]="id" [datasetOption]="datasetOptions.get(id)" (onSelectDataset)="onSelectDataset($event, id)" (onUpdateOptions)="onUpdateOptions($event, id)" (onSelectDate)="jumpToDate($event)">
</geomon-legend-entry> </geomon-legend-entry>
</div> </div>
</div> </div>

View file

@ -5,6 +5,7 @@ import { DatasetService } from '../../services/dataset.service';
import { AppRouterService } from '../../services/app-router.service'; import { AppRouterService } from '../../services/app-router.service';
// import { GeomonTimeseries, GeomonDataset } from '../../../shared/models/dataset'; // import { GeomonTimeseries, GeomonDataset } from '../../../shared/models/dataset';
import { DatasetOptions } from '../../../shared/models/options'; import { DatasetOptions } from '../../../shared/models/options';
import { TimeService } from '../../../common/core/time/time.service';
@Component({ @Component({
selector: 'app-bar', selector: 'app-bar',
@ -32,7 +33,8 @@ export class DiagramViewComponent implements OnInit {
constructor( constructor(
public datasetService: DatasetService<DatasetOptions>, public datasetService: DatasetService<DatasetOptions>,
public appRouter: AppRouterService,) { } public appRouter: AppRouterService,
private timeService: TimeService) { }
ngOnInit(): void { ngOnInit(): void {
// this.createSvg(); // this.createSvg();
@ -77,5 +79,9 @@ export class DiagramViewComponent implements OnInit {
// this.datasetOptions = this.datasetService.datasetOptions; // this.datasetOptions = this.datasetService.datasetOptions;
} }
public jumpToDate(date: Date) {
this.datasetService.timespan = this.timeService.centerTimespan(this.datasetService.timespan, date);
}
} }

View file

@ -1,7 +1,7 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { Timespan, TimeInterval, BufferedTime } from '../../../shared/models/timespan'; import { Timespan, TimeInterval, BufferedTime } from '../../../shared/models/timespan';
import moment from 'moment'; import * as moment from 'moment';
// import 'moment-duration-format'; // import 'moment-duration-format';
@Injectable() @Injectable()
@ -9,6 +9,13 @@ export class TimeService {
constructor() { } constructor() { }
public centerTimespan(timespan: Timespan, date: Date): Timespan {
const halfduration = this.getDuration(timespan).asMilliseconds() / 2;
const from = moment(date).subtract(halfduration).unix() * 1000;
const to = moment(date).add(halfduration).unix() * 1000;
return new Timespan(from, to);
}
public getBufferedTimespan(timespan: Timespan, factor: number, maxBufferInMs?: number): Timespan { public getBufferedTimespan(timespan: Timespan, factor: number, maxBufferInMs?: number): Timespan {
const durationMillis = this.getDuration(timespan).asMilliseconds(); const durationMillis = this.getDuration(timespan).asMilliseconds();
let buffer = durationMillis * factor; let buffer = durationMillis * factor;

View file

@ -204,6 +204,7 @@ export class GeomonTimeseriesChartComponent implements AfterViewInit, DoCheck {
this.addDatasetByInternalId(datasetOption.internalId); this.addDatasetByInternalId(datasetOption.internalId);
} }
// let firstDatasetId = this.datasetIds[0]; // let firstDatasetId = this.datasetIds[0];
// let dataset = this.datasetOptions.get(firstDatasetId); // let dataset = this.datasetOptions.get(firstDatasetId);
// this.addDataset(dataset.id, 'https://geomon.geologie.ac.at/52n-sos-webapp/api/'); // this.addDataset(dataset.id, 'https://geomon.geologie.ac.at/52n-sos-webapp/api/');
@ -214,19 +215,19 @@ export class GeomonTimeseriesChartComponent implements AfterViewInit, DoCheck {
public ngOnChanges(changes: SimpleChanges): void { public ngOnChanges(changes: SimpleChanges): void {
if (changes.timeInterval && this.timeInterval) { if (changes.timeInterval && this.timeInterval) {
this.timespan = this.timeService.createTimespanOfInterval(this.timeInterval); this.timespan = this.timeService.createTimespanOfInterval(this.timeInterval);
// this.timeIntervalChanges(); this.timeIntervalChanges();
} }
// if (changes.reloadForDatasets && this.reloadForDatasets && this.reloadDataForDatasets.length > 0) { // if (changes.reloadForDatasets && this.reloadForDatasets && this.reloadDataForDatasets.length > 0) {
// this.reloadDataForDatasets(this.reloadForDatasets); // this.reloadDataForDatasets(this.reloadForDatasets);
// } // }
if (changes.datasetOptions && this.datasetOptions) { // if (changes.datasetOptions && this.datasetOptions) {
// this.preparedData.forEach((dataEntry: InternalDataEntry, index) => { // let test = changes.datasetOptions;
// }
}
// this.processData(dataEntry, index); protected timeIntervalChanges(): void {
// }); this.datasetMap.forEach((dataset) => this.loadDatasetData(dataset, false));
let test = changes.datasetOptions;
}
} }
public getDataset(internalId: string) { public getDataset(internalId: string) {
@ -397,39 +398,63 @@ export class GeomonTimeseriesChartComponent implements AfterViewInit, DoCheck {
const datasetIdx = this.preparedData.findIndex((e) => e.internalId === dataset.internalId); const datasetIdx = this.preparedData.findIndex((e) => e.internalId === dataset.internalId);
let datasetOptions = this.datasetOptions.get(dataset.internalId); let datasetOptions = this.datasetOptions.get(dataset.internalId);
datasetOptions.color = color; datasetOptions.color = (datasetOptions.color == null) ? color: datasetOptions.color;
let dataEntry: InternalDataEntry = {
internalId: dataset.internalId,
selected: this.selectedDatasetIds.indexOf(dataset.internalId) >= 0,
// data: datasetOptions.visible ? data.values.map(d => ({ timestamp: d[0], value: d[1] })) : [],
data: values,
options: datasetOptions,
axisOptions: {
uom: dataset.uom,
label: dataset.label,
// zeroBased: datasetOptions.zeroBasedYAxis,
// yAxisRange: options.yAxisRange,
// autoRangeSelection: datasetOptions.autoRangeSelection,
// separateYAxis: datasetOptions.separateYAxis,
parameters: {
feature: dataset.parameters.feature,
phenomenon: dataset.parameters.phenomenon,
offering: dataset.parameters.offering
}
},
referenceValueData: [],
visible: true //datasetOptions.visible,
// bar: barConfig
};
// let dataEntry: InternalDataEntry = {
// internalId: dataset.internalId,
// selected: this.selectedDatasetIds.indexOf(dataset.internalId) >= 0,
// // data: datasetOptions.visible ? data.values.map(d => ({ timestamp: d[0], value: d[1] })) : [],
// data: values,
// options: datasetOptions,
// axisOptions: {
// uom: dataset.uom,
// label: dataset.label,
// // zeroBased: datasetOptions.zeroBasedYAxis,
// // yAxisRange: options.yAxisRange,
// // autoRangeSelection: datasetOptions.autoRangeSelection,
// // separateYAxis: datasetOptions.separateYAxis,
// parameters: {
// feature: dataset.parameters.feature,
// phenomenon: dataset.parameters.phenomenon,
// offering: dataset.parameters.offering
// }
// },
// referenceValueData: [],
// visible: true //datasetOptions.visible,
// // bar: barConfig
// };
let dataEntry: InternalDataEntry;
if (datasetIdx >= 0) { if (datasetIdx >= 0) {
this.preparedData[datasetIdx] = dataEntry; dataEntry = this.preparedData[datasetIdx];
dataEntry.data = values;
} else { } else {
dataEntry = {
internalId: dataset.internalId,
selected: this.selectedDatasetIds.indexOf(dataset.internalId) >= 0,
// data: datasetOptions.visible ? data.values.map(d => ({ timestamp: d[0], value: d[1] })) : [],
data: values,
options: datasetOptions,
axisOptions: {
uom: dataset.uom,
label: dataset.label,
// zeroBased: datasetOptions.zeroBasedYAxis,
// yAxisRange: options.yAxisRange,
// autoRangeSelection: datasetOptions.autoRangeSelection,
// separateYAxis: datasetOptions.separateYAxis,
parameters: {
feature: dataset.parameters.feature,
phenomenon: dataset.parameters.phenomenon,
offering: dataset.parameters.offering
}
},
referenceValueData: [],
visible: true //datasetOptions.visible,
// bar: barConfig
};
this.preparedData.push(dataEntry); this.preparedData.push(dataEntry);
} }
this.processData(dataEntry); this.processData(dataEntry, dataEntry.datasetIndex);
// this.redrawCompleteGraph(); // this.redrawCompleteGraph();
// var newDataset = { // var newDataset = {
@ -462,27 +487,28 @@ export class GeomonTimeseriesChartComponent implements AfterViewInit, DoCheck {
this.width = this.calculateWidth(); this.width = this.calculateWidth();
} }
private processData(dataEntry: InternalDataEntry, datasetIndex?: number): void { private processData(internalDataEntry: InternalDataEntry, datasetIndex?: number): void {
let dataset: ChartDataset; let dataset: ChartDataset;
if (datasetIndex != null) { if (datasetIndex != null) {
dataset = this.lineChart.data.datasets[datasetIndex]; dataset = this.lineChart.data.datasets[datasetIndex];
dataset.label = dataEntry.axisOptions.label; dataset.label = internalDataEntry.axisOptions.label;
dataset.borderWidth = dataEntry.selected ? 4 : 1; dataset.borderWidth = internalDataEntry.selected ? 4 : 1;
dataset.hidden = !dataEntry.visible; dataset.hidden = !internalDataEntry.visible;
dataset.data = internalDataEntry.data;
} else { } else {
dataset = { dataset = {
label: dataEntry.axisOptions.label, label: internalDataEntry.axisOptions.label,
// selected: dataEntry.selected, // selected: dataEntry.selected,
// backgroundColor: 'rgba(99, 255, 132, 0.2)', // backgroundColor: 'rgba(99, 255, 132, 0.2)',
backgroundColor: dataEntry.options.color, backgroundColor: internalDataEntry.options.color,
borderColor: dataEntry.options.color, //'rgba(99, 255, 132, 1)', borderColor: internalDataEntry.options.color, //'rgba(99, 255, 132, 1)',
borderWidth: 1, borderWidth: 1,
data: dataEntry.data, data: internalDataEntry.data,
}; };
this.lineChart.data.datasets.push(dataset); this.lineChart.data.datasets.push(dataset);
dataEntry.datasetIndex = this.lineChart.data.datasets.length - 1; internalDataEntry.datasetIndex = this.lineChart.data.datasets.length - 1;
} }
// You add the newly created dataset to the list of `data` // You add the newly created dataset to the list of `data`
@ -564,15 +590,15 @@ export class GeomonTimeseriesChartComponent implements AfterViewInit, DoCheck {
pan: { pan: {
enabled: true enabled: true
}, },
zoom: { // zoom: {
wheel: { // wheel: {
enabled: true, // enabled: true,
}, // },
pinch: { // pinch: {
enabled: true // enabled: true
}, // },
mode: 'xy', // mode: 'xy',
} // }
}, },
legend: { legend: {
display: false display: false
@ -580,9 +606,9 @@ export class GeomonTimeseriesChartComponent implements AfterViewInit, DoCheck {
}, },
scales: { scales: {
y: { y: {
suggestedMin: 0, // minimum will be 0, unless there is a lower value. // suggestedMin: 0, // minimum will be 0, unless there is a lower value.
// OR // // OR //
beginAtZero: true // minimum value will be 0. // beginAtZero: true // minimum value will be 0.
}, },
x: { x: {