- watch all changes on DataOptions models in dataservice

- npm updates
This commit is contained in:
Arno Kaimbacher 2021-10-12 16:42:07 +02:00
parent 7f13e31251
commit cd4119b986
9 changed files with 948 additions and 467 deletions

1178
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -1,10 +1,12 @@
<div> <div>
<h2>{{ platform.label }} Details</h2>
<h2><span [innerHTML]="platform.label"></span> Details</h2>
<div><span>id: </span>{{platform.id}}</div> <div><span>id: </span>{{platform.id}}</div>
<div> <div><span>label: </span>{{platform.label}}</div>
<label for="hero-name">Platform label: </label> <div>
<!-- <label for="hero-name">Platform label: {{ platform.label }}</label> -->
<!-- <input id="hero-name" [(ngModel)]="hero.name" placeholder="Hero name"/> --> <!-- <input id="hero-name" [(ngModel)]="hero.name" placeholder="Hero name"/> -->
<!-- <input type="text" id="hero-name" [(ngModel)]="platform.label" placeholder="Platform label"/> --> <!-- <input id="hero-name" [value]="platform.label" placeholder="Platform label"/> -->
</div> </div>
<button (click)="goBack()">go back</button> <button (click)="goBack()">go back</button>
</div> </div>

View file

@ -14,28 +14,42 @@ import { DatasetApiService } from '../../services/dataset-api.service';
}) })
export class PlatformDetailComponent implements OnInit { export class PlatformDetailComponent implements OnInit {
platform: GeomonPlatform; public platform: GeomonPlatform | undefined;
public loading: boolean;
public error: any;
title: string = 'AppComponent';
constructor( constructor(
private route: ActivatedRoute, private route: ActivatedRoute,
private datasetService: DatasetApiService, private datasetService: DatasetApiService,
private location: Location private location: Location
) {} ) {
this.getHero();
}
ngOnInit(): void { ngOnInit(): void {
this.getHero(); // this.getHero();
} }
getHero(): void { getHero(): 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((platform) => { .subscribe({
this.platform = platform; next: (platform: GeomonPlatform) => {
this.platform = platform;
this.title = "neuer Titel im Event";
},
error: (err: any) => this.handleError(err)
}); });
} }
protected handleError(error: any) {
this.loading = false;
this.error = error;
}
goBack(): void { goBack(): void {
this.location.back(); this.location.back();
} }

View file

@ -58,6 +58,7 @@ export class DatasetService<T extends DatasetOptions> {
// options.forEach((e) => temp.push(e)); // options.forEach((e) => temp.push(e));
// // this.saveState(); // // this.saveState();
// } // }
options.visible = true;
this.datasetOptions.set(internalId, options); this.datasetOptions.set(internalId, options);
this.datasetIdsChanged.emit(this.datasetIds); this.datasetIdsChanged.emit(this.datasetIds);

View file

@ -3,7 +3,7 @@
<div class="canvas-area is-8 column"> <div class="canvas-area is-8 column">
<!-- <h2>Bar Chart</h2> <!-- <h2>Bar Chart</h2>
<canvas id="line-chart" width="800" height="450"></canvas> --> <canvas id="line-chart" width="800" height="450"></canvas> -->
<geomon-timeseries-chart [datasetOptions]="datasetOptions" [datasetIds]="datasetIds" <geomon-timeseries-chart [datasetOptions]="datasetOptions" [datasetArray]="datasetArray" [datasetIds]="datasetIds"
[timeInterval]="datasetService.timespan" [selectedDatasetIds]="selectedIds"></geomon-timeseries-chart> [timeInterval]="datasetService.timespan" [selectedDatasetIds]="selectedIds"></geomon-timeseries-chart>
</div> </div>

View file

@ -18,6 +18,7 @@ export class DiagramViewComponent implements OnInit {
public selectedIds: string[] = []; public selectedIds: string[] = [];
public datasetOptions: Map<string, DatasetOptions> = new Map(); public datasetOptions: Map<string, DatasetOptions> = new Map();
public datasetArray: Array <DatasetOptions>;
public diagramLoading: boolean; public diagramLoading: boolean;
public overviewLoading: boolean; public overviewLoading: boolean;
@ -43,6 +44,7 @@ export class DiagramViewComponent implements OnInit {
private setDatasets() { private setDatasets() {
this.datasetIds = this.datasetService.datasetIds; this.datasetIds = this.datasetService.datasetIds;
this.datasetOptions = this.datasetService.datasetOptions; this.datasetOptions = this.datasetService.datasetOptions;
this.datasetArray = Array.from(this.datasetOptions.values());
} }
public removeAllTimeseries() { public removeAllTimeseries() {
@ -65,8 +67,14 @@ export class DiagramViewComponent implements OnInit {
this.selectedIds = []; this.selectedIds = [];
} }
public onUpdateOptions(options: DatasetOptions, internalId: string) { public onUpdateOptions(datasetOption: DatasetOptions, internalId: string) {
this.datasetService.updateDatasetOptions(options, internalId); // this.datasetService.updateDatasetOptions(datasetOption, internalId);
// let arrIndex = this.datasetArray.findIndex(x => x.internalId === internalId);
// this.datasetArray[arrIndex] = datasetOption;
// this.datasetOptions = new Map <string, DatasetOptions>([]);
// this.datasetOptions = this.datasetService.datasetOptions;
} }

View file

@ -1,5 +1,5 @@
import { import {
Input, Component, AfterViewInit, ViewChild, ElementRef, SimpleChanges, DoCheck, IterableDiffer, IterableDiffers Input, Component, AfterViewInit, ViewChild, ElementRef, SimpleChanges, DoCheck, IterableDiffer, IterableDiffers, KeyValueDiffer, KeyValueDiffers, KeyValueChangeRecord
} from '@angular/core'; } from '@angular/core';
// import * as d3 from 'd3'; // import * as d3 from 'd3';
import { Chart, ChartDataset, registerables } from 'chart.js'; import { Chart, ChartDataset, registerables } from 'chart.js';
@ -21,7 +21,7 @@ import zoomPlugin from 'chartjs-plugin-zoom';
Chart.register(zoomPlugin); Chart.register(zoomPlugin);
import { InternalIdHandler, InternalDatasetId } from '../../../common/components/services/internal-id-handler.service'; import { InternalIdHandler, InternalDatasetId } from '../../../common/components/services/internal-id-handler.service';
import { InternalDataEntry } from '../../../shared/models/chart'; import { DataEntry, InternalDataEntry } from '../../../shared/models/chart';
// interface Color { // interface Color {
// borderColor: string, // borderColor: string,
// pointBackgroundColor: string // pointBackgroundColor: string
@ -34,7 +34,7 @@ import { InternalDataEntry } from '../../../shared/models/chart';
}) })
export class GeomonTimeseriesChartComponent implements AfterViewInit, DoCheck { export class GeomonTimeseriesChartComponent implements AfterViewInit, DoCheck {
// @ViewChild('geomon_timeseries', { static: true }) // @ViewChild('geomon_timeseries', { static: true })
// public chartElem: ElementRef; // public chartElem: ElementRef;
@ -48,6 +48,10 @@ export class GeomonTimeseriesChartComponent implements AfterViewInit, DoCheck {
*/ */
@Input() @Input()
public datasetOptions: Map<string, DatasetOptions>; public datasetOptions: Map<string, DatasetOptions>;
protected oldDatasetOptions: Map<string, DatasetOptions>;
@Input()
public datasetArray: Array<DatasetOptions> = [];
/** /**
* List of presented dataset ids. * List of presented dataset ids.
@ -55,13 +59,13 @@ export class GeomonTimeseriesChartComponent implements AfterViewInit, DoCheck {
@Input() @Input()
public datasetIds: string[] = []; public datasetIds: string[] = [];
/** /**
* List of presented selected dataset ids. * List of presented selected dataset ids.
*/ */
@Input() @Input()
public selectedDatasetIds: string[] = []; public selectedDatasetIds: string[] = [];
/** /**
* The time interval in which the data should presented. * The time interval in which the data should presented.
@ -90,17 +94,41 @@ export class GeomonTimeseriesChartComponent implements AfterViewInit, DoCheck {
private datasetIdsDiffer: IterableDiffer<string>; private datasetIdsDiffer: IterableDiffer<string>;
private selectedDatasetIdsDiffer: IterableDiffer<string>; private selectedDatasetIdsDiffer: IterableDiffer<string>;
// siehe https://www.concretepage.com/angular/angular-keyvaluediffers
empDifferMap = new Map<string, any>();
empMap = new Map<string, DatasetOptions>();
private arrayDiffer: any;
changeLogs: string[] = [];
constructor( constructor(
protected iterableDiffers: IterableDiffers, protected iterableDiffers: IterableDiffers,
private kvDiffers: KeyValueDiffers,
protected datasetIdResolver: InternalIdHandler, protected datasetIdResolver: InternalIdHandler,
protected datasetApiService: DatasetApiService, protected datasetApiService: DatasetApiService,
protected timeService: TimeService, protected timeService: TimeService,
public datasetService: DatasetService<DatasetOptions>, public datasetService: DatasetService<DatasetOptions>,
) { ) {
this.datasetIdsDiffer = this.iterableDiffers.find([]).create(); this.datasetIdsDiffer = this.iterableDiffers.find([]).create();
this.selectedDatasetIdsDiffer = this.iterableDiffers.find([]).create(); this.selectedDatasetIdsDiffer = this.iterableDiffers.find([]).create();
} }
ngOnInit() {
// this.arrayDiffer = this.kvDiffers.find(this.datasetArray).create();
this.datasetArray.forEach(emp => {
// this.empDifferMap[emp.internalId] = this.kvDiffers.find(emp).create();
this.empDifferMap.set(emp.internalId, this.kvDiffers.find(emp).create());
// this.empMap[emp.internalId] = emp;
this.empMap.set(emp.internalId, emp);
})
}
private setProperty<T, K extends keyof T>(o: T, propertyName: K, value: any): void {
// return o[propertyName]; // o[propertyName] is of type T[K]
o[propertyName] = value;
}
public ngDoCheck(): void { public ngDoCheck(): void {
const selectedDatasetIdsChanges = this.selectedDatasetIdsDiffer.diff(this.selectedDatasetIds); const selectedDatasetIdsChanges = this.selectedDatasetIdsDiffer.diff(this.selectedDatasetIds);
@ -113,10 +141,40 @@ export class GeomonTimeseriesChartComponent implements AfterViewInit, DoCheck {
}); });
} }
if(this.datasetOptions){ for (let [key, empDiffer] of this.empDifferMap) {
let test = this.datasetOptions; let empChanges = empDiffer.diff(this.empMap.get(key));
if (empChanges) {
empChanges.forEachChangedItem((record: KeyValueChangeRecord<string, any>) => {
// console.log('Previous value: ' + record.previousValue);
// console.log('Current value: ' + record.currentValue);
// console.log('Attribute: ' + record.key);
let attribute = record.key;
const internalEntry = this.preparedData.find((e) => e.internalId === key);
this.setProperty(internalEntry, attribute as keyof InternalDataEntry, record.currentValue);
// internalEntry[attribute as keyof InternalDataEntry] = record.currentValue;
this.processData(internalEntry, internalEntry.datasetIndex);
this.lineChart.update();
});
}
} }
}
// let empArrayChanges = this.arrayDiffer.diff(this.datasetArray);
// if (empArrayChanges) {
// empArrayChanges.forEachAddedItem((record) => {
// let emp = record.currentValue;
// console.log('Added ' + emp.name);
// });
// empArrayChanges.forEachRemovedItem((record) => {
// let emp = record.previousValue;
// console.log('Removed ' + emp.name);
// });
// }
}
protected setSelectedId(internalId: string): void { protected setSelectedId(internalId: string): void {
const internalEntry = this.preparedData.find((e) => e.internalId === internalId); const internalEntry = this.preparedData.find((e) => e.internalId === internalId);
@ -130,7 +188,7 @@ export class GeomonTimeseriesChartComponent implements AfterViewInit, DoCheck {
this.redrawCompleteGraph(); this.redrawCompleteGraph();
} }
ngAfterViewInit(): void { ngAfterViewInit(): void {
this.canvas = document.getElementById("line-chart") as HTMLCanvasElement; this.canvas = document.getElementById("line-chart") as HTMLCanvasElement;
@ -141,9 +199,9 @@ export class GeomonTimeseriesChartComponent implements AfterViewInit, DoCheck {
for (let i = 0; i < this.datasetIds.length; i++) { for (let i = 0; i < this.datasetIds.length; i++) {
let datasetId = this.datasetIds[i]; let datasetId = this.datasetIds[i];
let datasetOptions = this.datasetOptions.get(datasetId); let datasetOption = this.datasetOptions.get(datasetId);
// this.internalId = this.internalIdHandler.resolveInternalId(datasetId); // this.internalId = this.internalIdHandler.resolveInternalId(datasetId);
this.addDatasetByInternalId(datasetOptions.internalId); this.addDatasetByInternalId(datasetOption.internalId);
} }
// let firstDatasetId = this.datasetIds[0]; // let firstDatasetId = this.datasetIds[0];
@ -161,6 +219,14 @@ export class GeomonTimeseriesChartComponent implements AfterViewInit, DoCheck {
// 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) {
// this.preparedData.forEach((dataEntry: InternalDataEntry, index) => {
// this.processData(dataEntry, index);
// });
let test = changes.datasetOptions;
}
} }
public getDataset(internalId: string) { public getDataset(internalId: string) {
@ -191,8 +257,19 @@ export class GeomonTimeseriesChartComponent implements AfterViewInit, DoCheck {
this.loadDatasetData(dataset, false); this.loadDatasetData(dataset, false);
} }
protected datasetOptionsChanged(internalId: string, options: DatasetOptions, firstChange: boolean): void {
if (!firstChange && this.datasetMap.has(internalId)) {
const internalEntry = this.preparedData.find((e) => e.internalId === internalId);
if (internalEntry) {
internalEntry.visible = options.visible;
}
this.processData(internalEntry, internalEntry.datasetIndex)
}
}
// load data of dataset // load data of dataset
private loadDatasetData(dataset: GeomonTimeseries, fprce: boolean): void { private loadDatasetData(dataset: GeomonTimeseries, force: boolean): void {
// const datasetOptions = this.datasetOptions.get(dataset.internalId); // const datasetOptions = this.datasetOptions.get(dataset.internalId);
// https://github.com/52North/helgoland-toolbox/blob/9ff9a42b34cd3deb181d56d76d48eba7c101554e/libs/core/src/lib/api-communication/connectors/dataset-api-v3-connector/dataset-api-v3-connector.ts#L270 // https://github.com/52North/helgoland-toolbox/blob/9ff9a42b34cd3deb181d56d76d48eba7c101554e/libs/core/src/lib/api-communication/connectors/dataset-api-v3-connector/dataset-api-v3-connector.ts#L270
@ -244,17 +321,17 @@ export class GeomonTimeseriesChartComponent implements AfterViewInit, DoCheck {
function groupBy(list: Array<[number, number]>, keyGetter: any): Map<string, TimeValueTuple[]> { function groupBy(list: Array<[number, number]>, keyGetter: any): Map<string, TimeValueTuple[]> {
const map = new Map(); const map = new Map();
list.forEach((item: any) => { list.forEach((item: any) => {
const key = keyGetter(item); const key = keyGetter(item);
const collection = map.get(key); const collection = map.get(key);
if (!collection) { if (!collection) {
map.set(key, [item]); map.set(key, [item]);
} else { } else {
collection.push(item); collection.push(item);
} }
}); });
return map; return map;
} }
function findMinMax(values: TimeValueTuple[]) { function findMinMax(values: TimeValueTuple[]) {
var res = { min: values[0], max: values[0] }; var res = { min: values[0], max: values[0] };
@ -267,7 +344,7 @@ export class GeomonTimeseriesChartComponent implements AfterViewInit, DoCheck {
return res; return res;
} }
let values = Array.from( grouped_items.values() ); let values = Array.from(grouped_items.values());
values = [].concat(...values); values = [].concat(...values);
let xLabels = values.map(function (label) { let xLabels = values.map(function (label) {
let date = moment(label[0]).format("DD/MM HH:mm"); let date = moment(label[0]).format("DD/MM HH:mm");
@ -323,7 +400,7 @@ export class GeomonTimeseriesChartComponent implements AfterViewInit, DoCheck {
datasetOptions.color = color; datasetOptions.color = color;
let dataEntry: InternalDataEntry = { let dataEntry: InternalDataEntry = {
internalId: dataset.internalId, internalId: dataset.internalId,
selected: this.selectedDatasetIds.indexOf(dataset.internalId) >= 0, selected: this.selectedDatasetIds.indexOf(dataset.internalId) >= 0,
// data: datasetOptions.visible ? data.values.map(d => ({ timestamp: d[0], value: d[1] })) : [], // data: datasetOptions.visible ? data.values.map(d => ({ timestamp: d[0], value: d[1] })) : [],
data: values, data: values,
@ -342,7 +419,7 @@ export class GeomonTimeseriesChartComponent implements AfterViewInit, DoCheck {
} }
}, },
referenceValueData: [], referenceValueData: [],
visible: datasetOptions.visible, visible: true //datasetOptions.visible,
// bar: barConfig // bar: barConfig
}; };
@ -380,7 +457,7 @@ export class GeomonTimeseriesChartComponent implements AfterViewInit, DoCheck {
// chart.options.scales.y.ticks.callback = (value, index, values) => { // chart.options.scales.y.ticks.callback = (value, index, values) => {
// return value + '°'; // return value + '°';
// } // }
chart.update(); chart.update();
this.width = this.calculateWidth(); this.width = this.calculateWidth();
} }
@ -393,9 +470,9 @@ export class GeomonTimeseriesChartComponent implements AfterViewInit, DoCheck {
dataset = this.lineChart.data.datasets[datasetIndex]; dataset = this.lineChart.data.datasets[datasetIndex];
dataset.label = dataEntry.axisOptions.label; dataset.label = dataEntry.axisOptions.label;
dataset.borderWidth = dataEntry.selected ? 4 : 1; dataset.borderWidth = dataEntry.selected ? 4 : 1;
// dataset.hidden = dataEntry.selected; dataset.hidden = !dataEntry.visible;
} else { } else {
dataset = { dataset = {
label: dataEntry.axisOptions.label, label: dataEntry.axisOptions.label,
// selected: dataEntry.selected, // selected: dataEntry.selected,
// backgroundColor: 'rgba(99, 255, 132, 0.2)', // backgroundColor: 'rgba(99, 255, 132, 0.2)',
@ -405,31 +482,40 @@ export class GeomonTimeseriesChartComponent implements AfterViewInit, DoCheck {
data: dataEntry.data, data: dataEntry.data,
}; };
this.lineChart.data.datasets.push(dataset); this.lineChart.data.datasets.push(dataset);
dataEntry.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`
// this.lineChart.data.datasets.push(newDataset); // this.lineChart.data.datasets.push(newDataset);
this.lineChart.options.scales.x.ticks.callback = (val, index) => { this.lineChart.options.scales.x.ticks.callback = (val, index) => {
// // Hide the label of every 2nd dataset // // Hide the label of every 2nd dataset
// return xLabels.includes(val.toString()) ? val : null; // return xLabels.includes(val.toString()) ? val : null;
// return index % 2 === 0 ? (val) : ''; // return index % 2 === 0 ? (val) : '';
let valTime = moment(val, "DD/MM HH:mm").format("HH:mm"); let valTime = moment(val, "DD/MM HH:mm").format("HH:mm");
if (valTime == "08:00" || valTime == "18:00"){ if (valTime == "08:00" || valTime == "18:00") {
return val; return val;
} else { } else {
return null; return null;
} }
} }
this.lineChart.options.scales.y.ticks.callback = (value, index, values) => { this.lineChart.options.scales.y.ticks.callback = (value, index, values) => {
return value + '°'; return value + '°';
} }
} }
// public reloadDataForDatasets(datasetIds: string[]): void {
// datasetIds.forEach(id => {
// if (this.datasetMap.has(id)) {
// this.loadDatasetData(this.datasetMap.get(id), true);
// }
// });
// }
private redrawCompleteGraph(): void { private redrawCompleteGraph(): void {
this.preparedData.forEach((dataEntry: InternalDataEntry, index) => { this.preparedData.forEach((dataEntry: InternalDataEntry, index) => {
this.processData(dataEntry, index); this.processData(dataEntry, dataEntry.datasetIndex);
}); });
this.lineChart.update(); this.lineChart.update();
} }
@ -479,18 +565,18 @@ export class GeomonTimeseriesChartComponent implements AfterViewInit, DoCheck {
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
} }
}, },
scales: { scales: {
y: { y: {
@ -514,10 +600,10 @@ export class GeomonTimeseriesChartComponent implements AfterViewInit, DoCheck {
year: "yyyy", year: "yyyy",
} }
}, },
ticks: { ticks: {
// callback: function(val, index) { // callback: function(val, index) {
// // Hide the label of every 2nd dataset // // Hide the label of every 2nd dataset
// return index % 2 === 0 ? (val) : ''; // return index % 2 === 0 ? (val) : '';

View file

@ -10,6 +10,7 @@ export interface DataEntry {
export interface InternalDataEntry { export interface InternalDataEntry {
internalId: string; internalId: string;
datasetIndex?: number;
// hoverId: string; // hoverId: string;
data: number[]; data: number[];
selected?: boolean; selected?: boolean;

View file

@ -73,6 +73,7 @@ export class DatasetOptions {
) { ) {
this.internalId = internalId; this.internalId = internalId;
this.color = color; this.color = color;
this.visible = true;
} }
} }