- npm updates
- add legend-entry-component files - add DatasetOptions class
This commit is contained in:
parent
dbf8aa495e
commit
91cd763da0
15 changed files with 1043 additions and 534 deletions
980
package-lock.json
generated
980
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -29,6 +29,7 @@ import { DiagramViewComponent } from './views/diagram-view/diagram-view.componen
|
|||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { MatDialogModule } from '@angular/material/dialog';
|
||||
import { DatasetByStationSelectorComponent } from './components/dataset-by-station-selector/dataset-by-station-selector.component';
|
||||
import { LegendEntryComponent } from './components/legend-entry/legend-entry.component';
|
||||
// import { MAT_DIALOG_DEFAULT_OPTIONS } from '@angular/material';
|
||||
import { MatListModule } from '@angular/material/list';
|
||||
import {MatBadgeModule} from '@angular/material/badge';
|
||||
|
@ -38,7 +39,7 @@ import { InternalIdHandler } from '../common/components/services/internal-id-han
|
|||
|
||||
@NgModule({
|
||||
// declarations: The components, directives, and pipes that belong to this NgModule.
|
||||
declarations: [AppComponent, MapComponent, DashboardComponent, MessagesComponent, MapViewComponent, DiagramViewComponent, DatasetByStationSelectorComponent],
|
||||
declarations: [AppComponent, MapComponent, DashboardComponent, MessagesComponent, MapViewComponent, DiagramViewComponent, DatasetByStationSelectorComponent, LegendEntryComponent],
|
||||
// entryComponents: [
|
||||
// DatasetByStationSelectorComponent
|
||||
// ],
|
||||
|
|
|
@ -10,6 +10,7 @@ import { MatSelectionListChange } from '@angular/material/list';
|
|||
|
||||
import { DatasetService } from '../../services/dataset.service';
|
||||
import { AppRouterService } from './../../services/app-router.service';
|
||||
import { DatasetOptions } from './../../../shared/models/options';
|
||||
|
||||
// https://material.angular.io/components/dialog/overview
|
||||
// https://blog.angular-university.io/angular-material-dialog/
|
||||
|
@ -51,7 +52,7 @@ export class DatasetByStationSelectorComponent implements OnInit {
|
|||
constructor(
|
||||
protected datasetApiService: DatasetApiService,
|
||||
private dialogRef: MatDialogRef<DatasetByStationSelectorComponent>,
|
||||
public datasetService : DatasetService<GeomonTimeseries>,
|
||||
public datasetService : DatasetService<DatasetOptions>,
|
||||
public appRouter: AppRouterService,
|
||||
) { }
|
||||
|
||||
|
@ -112,7 +113,7 @@ export class DatasetByStationSelectorComponent implements OnInit {
|
|||
|
||||
const id = (change.option.value as SelectableDataset).internalId;
|
||||
if (change.option.selected) {
|
||||
this.datasetService.addDataset(id, change.option.value as GeomonTimeseries);
|
||||
this.datasetService.addDataset(id, change.option.value as DatasetOptions);
|
||||
} else {
|
||||
this.datasetService.removeDataset(id);
|
||||
}
|
||||
|
|
42
src/app/components/legend-entry/legend-entry.component.html
Normal file
42
src/app/components/legend-entry/legend-entry.component.html
Normal file
|
@ -0,0 +1,42 @@
|
|||
|
||||
<div id="geomon-legend-entry" class="legendItem" style="position: relative;" [ngStyle]="{'border-color': datasetOption?.color}"
|
||||
[ngClass]="{'selected': selected}" (click)="toggleVisibility(); $event.stopPropagation();">
|
||||
<!-- <div class="loading-overlay" *ngIf="loading" [ngStyle]="{'background-color': datasetOption?.color}">
|
||||
<div class="fa fa-refresh fa-spin fa-3x fa-fw"></div>
|
||||
</div> -->
|
||||
|
||||
<div>
|
||||
<div class="legendItemheader" [ngClass]="{'highlight': highlight}">
|
||||
|
||||
<div class="legendItemLabel" [ngStyle]="{'color': datasetOption?.color}">
|
||||
<label>Plattform: {{platformLabel}} </label>
|
||||
</div>
|
||||
|
||||
<div class="noDataWarning firstLastEntry" *ngIf="!hasData">
|
||||
<div>
|
||||
<span class="fa fa-exclamation-triangle red"></span>
|
||||
<span class="small-label">Keine Daten verfügbar</span>
|
||||
</div>
|
||||
<div class="additionalLegendEntry">
|
||||
<span class="fa fa-chevron-right"></span>
|
||||
<span class="small-label">Springe zur letzten Messung</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="small-label">
|
||||
<label> {{phenomenonLabel}} </label>
|
||||
<span *ngIf="uom">
|
||||
<span>[</span>
|
||||
<label>{{uom}}</label>
|
||||
<span>]</span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="small-label">
|
||||
<label>Sensor: {{procedureLabel}}</label>
|
||||
</div>
|
||||
<div class="small-label" *ngIf="categoryLabel != phenomenonLabel">
|
||||
<label>{{categoryLabel}}</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
74
src/app/components/legend-entry/legend-entry.component.scss
Normal file
74
src/app/components/legend-entry/legend-entry.component.scss
Normal file
|
@ -0,0 +1,74 @@
|
|||
#geomon-legend-entry.legendItem {
|
||||
background-color: white;
|
||||
padding: 5px;
|
||||
border-radius: 5px;
|
||||
margin-bottom: 5px;
|
||||
.small-label {
|
||||
font-size: 90%;
|
||||
word-break: break-all;
|
||||
}
|
||||
&.selected {
|
||||
padding: 0px;
|
||||
border-width: 5px;
|
||||
border-style: solid;
|
||||
}
|
||||
.legendItemheader {
|
||||
cursor: pointer;
|
||||
&.highlight {
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
.legendicons {
|
||||
span {
|
||||
margin: 0 4%;
|
||||
font-size: 150%;
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
.delete {
|
||||
z-index: 5;
|
||||
}
|
||||
}
|
||||
.noDataWarning {
|
||||
border: red solid 2px;
|
||||
border-radius: 5px;
|
||||
padding: 3px;
|
||||
.red {
|
||||
color: red;
|
||||
}
|
||||
}
|
||||
.additionalLegendEntry {
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
&.selected {
|
||||
font-weight: bolder;
|
||||
}
|
||||
}
|
||||
.refEntry.selected {
|
||||
border-style: solid;
|
||||
border-width: 2px;
|
||||
border-radius: 2px;
|
||||
margin: 2px 0;
|
||||
}
|
||||
.loading-overlay {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
opacity: 0.5;
|
||||
z-index: 1;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
.fa-spin {
|
||||
$icon-size: 25px;
|
||||
color: white;
|
||||
font-size: $icon-size;
|
||||
width: $icon-size;
|
||||
height: $icon-size;
|
||||
}
|
||||
}
|
||||
}
|
141
src/app/components/legend-entry/legend-entry.component.ts
Normal file
141
src/app/components/legend-entry/legend-entry.component.ts
Normal file
|
@ -0,0 +1,141 @@
|
|||
import { Component, EventEmitter, Input, OnChanges, Output, SimpleChanges } from '@angular/core';
|
||||
|
||||
|
||||
import { GeomonTimeseries, DatasetFilter, DatasetType } from '../../../shared/models/dataset';
|
||||
import { TimeInterval } from '../../../shared/models/timespan';
|
||||
import { DatasetApiService } from '../../services/dataset-api.service';
|
||||
import { InternalIdHandler, InternalDatasetId } from '../../../common/components/services/internal-id-handler.service';
|
||||
import { DatasetOptions } from '../../../shared/models/options';
|
||||
@Component({
|
||||
selector: 'geomon-legend-entry',
|
||||
templateUrl: './legend-entry.component.html',
|
||||
styleUrls: ['./legend-entry.component.scss']
|
||||
})
|
||||
export class LegendEntryComponent {
|
||||
@Input()
|
||||
public timeInterval: TimeInterval;
|
||||
|
||||
@Output()
|
||||
public onSelectDate: EventEmitter<Date> = new EventEmitter();
|
||||
|
||||
// public firstValue: FirstLastValue;
|
||||
// public lastValue: FirstLastValue;
|
||||
public hasData = true;
|
||||
|
||||
public informationVisible = false;
|
||||
// public referenceValues: ReferenceValue[];
|
||||
|
||||
|
||||
@Input()
|
||||
public datasetOption: DatasetOptions;
|
||||
|
||||
@Input()
|
||||
public highlight: boolean;
|
||||
|
||||
@Output()
|
||||
public onUpdateOptions: EventEmitter<DatasetOptions> = new EventEmitter();
|
||||
|
||||
// @Output()
|
||||
// public onEditOptions: EventEmitter<DatasetOptions> = new EventEmitter();
|
||||
|
||||
@Output()
|
||||
public onShowGeometry: EventEmitter<GeoJSON.GeoJsonObject> = new EventEmitter();
|
||||
|
||||
public dataset: GeomonTimeseries;
|
||||
public platformLabel: string;
|
||||
public phenomenonLabel: string;
|
||||
public procedureLabel: string;
|
||||
public categoryLabel: string;
|
||||
public uom: string;
|
||||
public error: any;
|
||||
|
||||
|
||||
|
||||
@Input()
|
||||
public datasetId: string;
|
||||
|
||||
@Input()
|
||||
public selected: boolean;
|
||||
|
||||
@Output()
|
||||
public onDeleteDataset: EventEmitter<boolean> = new EventEmitter();
|
||||
|
||||
@Output()
|
||||
public onSelectDataset: EventEmitter<boolean> = new EventEmitter();
|
||||
|
||||
public loading: boolean;
|
||||
protected internalId: InternalDatasetId;
|
||||
// private langChangeSubscription: Subscription;
|
||||
|
||||
constructor(
|
||||
private internalIdHandler: InternalIdHandler,
|
||||
private datasetApiService: DatasetApiService) { }
|
||||
|
||||
public ngOnInit(): void {
|
||||
if (this.datasetId) {
|
||||
this.internalId = this.internalIdHandler.resolveInternalId(this.datasetId);
|
||||
this.loadDataset();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
protected loadDataset(locale?: string): void {
|
||||
const params: DatasetFilter = {};
|
||||
if (locale) { params.locale = locale; }
|
||||
this.loading = true;
|
||||
// this.servicesConnector.getDataset(this.internalId, { ...params, type: DatasetType.Timeseries })
|
||||
// .subscribe(
|
||||
// dataset => this.setDataset(dataset),
|
||||
// error => this.handleError(error)
|
||||
// );
|
||||
this.datasetApiService.getDataset(this.internalId.id, this.internalId.url, { type: 'timeseries' }).subscribe({
|
||||
next: (res: GeomonTimeseries) => this.setDataset(res),
|
||||
error: (err: any) => this.handleError(err),
|
||||
complete: () => console.log('HTTP request completed.')
|
||||
// error => this.errorHandler.handleDatasetLoadError(error)
|
||||
});
|
||||
}
|
||||
|
||||
protected handleError(error: any) {
|
||||
this.loading = false;
|
||||
this.error = error;
|
||||
}
|
||||
|
||||
public removeDataset() {
|
||||
this.onDeleteDataset.emit(true);
|
||||
}
|
||||
|
||||
protected setDataset(timeseries: GeomonTimeseries) {
|
||||
this.dataset = timeseries;
|
||||
this.setParameters();
|
||||
this.loading = false;
|
||||
}
|
||||
|
||||
private setParameters() {
|
||||
this.platformLabel = this.dataset.parameters.platform.label;
|
||||
this.phenomenonLabel = this.dataset.parameters.phenomenon.label;
|
||||
this.procedureLabel = this.dataset.parameters.procedure.label;
|
||||
this.categoryLabel = this.dataset.parameters.category.label;
|
||||
this.uom = this.dataset.uom;
|
||||
}
|
||||
|
||||
public toggleSelection() {
|
||||
this.selected = !this.selected;
|
||||
this.onSelectDataset.emit(this.selected);
|
||||
}
|
||||
|
||||
public toggleVisibility() {
|
||||
this.datasetOption.visible = !this.datasetOption.visible;
|
||||
this.onUpdateOptions.emit(this.datasetOption);
|
||||
}
|
||||
|
||||
public editDatasetOptions() {
|
||||
// this.onEditOptions.emit(this.datasetOptions);
|
||||
}
|
||||
|
||||
public showGeometry() {
|
||||
this.onShowGeometry.emit(this.dataset.platform.geometry);
|
||||
}
|
||||
|
||||
}
|
|
@ -9,12 +9,13 @@ const TIME_CACHE_PARAM = 'timeseriesTime';
|
|||
// https://github.com/52North/helgoland-toolbox/blob/fe6af1b9df0e5d78eeec236e4690aeb7dc92119b/apps/helgoland/src/app/services/timeseries-service.service.ts#L22
|
||||
|
||||
import { TimeService } from '../../common/core/time/time.service';
|
||||
import { DatasetOptions } from '../../shared/models/options';
|
||||
|
||||
@Injectable()
|
||||
export class DatasetService<T> {
|
||||
export class DatasetService<T extends DatasetOptions> {
|
||||
|
||||
public datasetIds: string[] = [];
|
||||
public datasetService: Map<string, T> = new Map();
|
||||
public datasetOptions: Map<string, T> = new Map();
|
||||
|
||||
private _timespan: Timespan;
|
||||
|
||||
|
@ -57,7 +58,7 @@ export class DatasetService<T> {
|
|||
// options.forEach((e) => temp.push(e));
|
||||
// // this.saveState();
|
||||
// }
|
||||
this.datasetService.set(internalId, options);
|
||||
this.datasetOptions.set(internalId, options);
|
||||
|
||||
this.datasetIdsChanged.emit(this.datasetIds);
|
||||
return true;
|
||||
|
@ -65,7 +66,7 @@ export class DatasetService<T> {
|
|||
|
||||
public removeAllDatasets() {
|
||||
this.datasetIds.length = 0;
|
||||
this.datasetService.clear();
|
||||
this.datasetOptions.clear();
|
||||
this.datasetIdsChanged.emit(this.datasetIds);
|
||||
// this.saveState();
|
||||
}
|
||||
|
@ -74,7 +75,7 @@ export class DatasetService<T> {
|
|||
const datasetIdx = this.datasetIds.indexOf(internalId);
|
||||
if (datasetIdx > -1) {
|
||||
this.datasetIds.splice(datasetIdx, 1);
|
||||
this.datasetService.delete(internalId);
|
||||
this.datasetOptions.delete(internalId);
|
||||
}
|
||||
this.datasetIdsChanged.emit(this.datasetIds);
|
||||
// this.saveState();
|
||||
|
@ -86,11 +87,11 @@ export class DatasetService<T> {
|
|||
|
||||
public hasDataset(id: string): boolean {
|
||||
// return this.datasetIds.indexOf(id) >= 0;
|
||||
return this.datasetService.has(id);
|
||||
return this.datasetOptions.has(id);
|
||||
}
|
||||
|
||||
public updateDatasetOptions(options: T, internalId: string) {
|
||||
this.datasetService.set(internalId, options);
|
||||
this.datasetOptions.set(internalId, options);
|
||||
// this.saveState();
|
||||
}
|
||||
|
||||
|
|
|
@ -1,16 +1,18 @@
|
|||
|
||||
<div class="main columns">
|
||||
|
||||
<div class="canvas-area is-8 column">
|
||||
<!-- <h2>Bar Chart</h2>
|
||||
<canvas id="line-chart" width="800" height="450"></canvas> -->
|
||||
<geomon-timeseries-chart [datasetOptions]="datasetOptions"
|
||||
[datasetIds]="datasetIds" [timeInterval]="datasetService.timespan"></geomon-timeseries-chart>
|
||||
<geomon-timeseries-chart [datasetOptions]="datasetOptions" [datasetIds]="datasetIds"
|
||||
[timeInterval]="datasetService.timespan" [selectedDatasetIds]="selectedIds"></geomon-timeseries-chart>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="input-area is-4 column">
|
||||
Test
|
||||
<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>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
|
@ -3,7 +3,8 @@ import { Component, OnInit } from '@angular/core';
|
|||
|
||||
import { DatasetService } from '../../services/dataset.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';
|
||||
|
||||
@Component({
|
||||
selector: 'app-bar',
|
||||
|
@ -16,7 +17,7 @@ export class DiagramViewComponent implements OnInit {
|
|||
|
||||
public selectedIds: string[] = [];
|
||||
|
||||
public datasetOptions: Map<string, GeomonTimeseries> = new Map();
|
||||
public datasetOptions: Map<string, DatasetOptions> = new Map();
|
||||
|
||||
public diagramLoading: boolean;
|
||||
public overviewLoading: boolean;
|
||||
|
@ -29,7 +30,7 @@ export class DiagramViewComponent implements OnInit {
|
|||
// };
|
||||
|
||||
constructor(
|
||||
public datasetService: DatasetService<GeomonTimeseries>,
|
||||
public datasetService: DatasetService<DatasetOptions>,
|
||||
public appRouter: AppRouterService,) { }
|
||||
|
||||
ngOnInit(): void {
|
||||
|
@ -41,11 +42,7 @@ export class DiagramViewComponent implements OnInit {
|
|||
|
||||
private setDatasets() {
|
||||
this.datasetIds = this.datasetService.datasetIds;
|
||||
this.datasetOptions = this.datasetService.datasetService;
|
||||
}
|
||||
|
||||
public clearSelection() {
|
||||
this.selectedIds = [];
|
||||
this.datasetOptions = this.datasetService.datasetOptions;
|
||||
}
|
||||
|
||||
public removeAllTimeseries() {
|
||||
|
@ -56,6 +53,21 @@ export class DiagramViewComponent implements OnInit {
|
|||
this.datasetService.removeDataset(internalId);
|
||||
}
|
||||
|
||||
public onSelectDataset(selected: boolean, internalId: string) {
|
||||
if (selected) {
|
||||
this.selectedIds.push(internalId);
|
||||
} else {
|
||||
this.selectedIds.splice(this.selectedIds.findIndex(entry => entry === internalId), 1);
|
||||
}
|
||||
}
|
||||
|
||||
public clearSelection() {
|
||||
this.selectedIds = [];
|
||||
}
|
||||
|
||||
public onUpdateOptions(options: DatasetOptions, internalId: string) {
|
||||
this.datasetService.updateDatasetOptions(options, internalId);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -3,10 +3,10 @@ import { IDataset } from '../../../shared/models/dataset';
|
|||
|
||||
const INTERNAL_ID_SEPERATOR = '_';
|
||||
|
||||
// export interface InternalDatasetId {
|
||||
// id: string;
|
||||
// url: string;
|
||||
// }
|
||||
export interface InternalDatasetId {
|
||||
id: string;
|
||||
url: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Service to generate or resolve internal dataset IDs
|
||||
|
@ -31,4 +31,33 @@ export class InternalIdHandler {
|
|||
return url + INTERNAL_ID_SEPERATOR + id;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Resolves the internal ID to the url and the API specific dataset id.
|
||||
* @param internalId The internal id as string
|
||||
* @returns Construct of url and API id
|
||||
*/
|
||||
public resolveInternalId(internalId: string | InternalDatasetId): InternalDatasetId {
|
||||
if (typeof (internalId) === 'string') {
|
||||
if (internalId.indexOf(INTERNAL_ID_SEPERATOR) > 0) {
|
||||
const url = internalId.substring(0, internalId.indexOf(INTERNAL_ID_SEPERATOR));
|
||||
const id = internalId.substring(internalId.indexOf(INTERNAL_ID_SEPERATOR) + INTERNAL_ID_SEPERATOR.length);
|
||||
return { url, id };
|
||||
} else {
|
||||
console.error('InternalID ' + internalId + ' is not resolvable');
|
||||
return {url: "", id: ""};
|
||||
}
|
||||
} else if (this.instanceOfInternalDatasetId(internalId)) {
|
||||
return internalId;
|
||||
} else {
|
||||
return {url: "", id: ""};
|
||||
}
|
||||
}
|
||||
|
||||
private instanceOfInternalDatasetId(object: any): object is InternalDatasetId {
|
||||
return 'id' in object && 'url' in object;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,3 +1,3 @@
|
|||
<div class="d3" #geomon_timeseries>
|
||||
<canvas id="line-chart" width="100%" height="80%"></canvas>
|
||||
<div class="chart-container">
|
||||
<canvas #chart id="line-chart"></canvas>
|
||||
</div>
|
|
@ -0,0 +1,20 @@
|
|||
// :host {
|
||||
// position: relative;
|
||||
// margin: auto;
|
||||
// width: 100%;
|
||||
// height: 100%;
|
||||
// }
|
||||
|
||||
|
||||
|
||||
.chart-container {
|
||||
position: relative;
|
||||
margin: 5px auto;
|
||||
width: 100%;
|
||||
height: 80%;
|
||||
}
|
||||
|
||||
#line-chart {
|
||||
|
||||
border: 1px solid black;
|
||||
}
|
|
@ -1,12 +1,13 @@
|
|||
import { Input, Component, AfterViewInit, ViewChild, ElementRef, SimpleChanges } from '@angular/core';
|
||||
import { Input, Component, AfterViewInit, ViewChild, ElementRef, SimpleChanges, DoCheck, IterableDiffer} from '@angular/core';
|
||||
// import * as d3 from 'd3';
|
||||
import { Chart, LogarithmicScale, registerables } from 'chart.js';
|
||||
import { Chart, registerables } from 'chart.js';
|
||||
|
||||
import { GeomonTimeseries, DataConst, GeomonTimeseriesData } from '../../../shared/models/dataset';
|
||||
import { DatasetApiService } from '../../../app/services/dataset-api.service';
|
||||
import { DatasetService } from '../../../app/services/dataset.service';
|
||||
|
||||
import { Timespan } from '../../../shared/models/timespan';
|
||||
import { DatasetOptions } from '../../../shared/models/options';
|
||||
import { TimeService } from '../../core/time/time.service';
|
||||
import * as moment from 'moment';
|
||||
// import 'moment-duration-format';
|
||||
|
@ -14,27 +15,36 @@ import { TimeValueTuple, Data } from '../../../shared/models/dataset';
|
|||
import 'chartjs-adapter-moment';
|
||||
|
||||
import zoomPlugin from 'chartjs-plugin-zoom';
|
||||
|
||||
Chart.register(zoomPlugin);
|
||||
import { InternalIdHandler, InternalDatasetId } from '../../../common/components/services/internal-id-handler.service';
|
||||
|
||||
// interface Color {
|
||||
// borderColor: string,
|
||||
// pointBackgroundColor: string
|
||||
// }
|
||||
|
||||
@Component({
|
||||
selector: 'geomon-timeseries-chart',
|
||||
templateUrl: './geomon-timeseries-chart.component.html',
|
||||
styleUrls: ['./geomon-timeseries-chart.component.scss']
|
||||
})
|
||||
export class GeomonTimeseriesChartComponent implements AfterViewInit {
|
||||
export class GeomonTimeseriesChartComponent implements AfterViewInit, DoCheck {
|
||||
|
||||
|
||||
|
||||
// @ViewChild('geomon_timeseries', { static: true })
|
||||
// public chartElem: ElementRef;
|
||||
|
||||
|
||||
@ViewChild('geomon_timeseries') public chartElem: ElementRef;
|
||||
@ViewChild('chart') private chartElem: ElementRef;
|
||||
|
||||
lineChart: Chart;
|
||||
private lineChart: Chart;
|
||||
/**
|
||||
* The corresponding dataset options.
|
||||
*/
|
||||
@Input()
|
||||
public datasetOptions: Map<string, GeomonTimeseries>;
|
||||
public datasetOptions: Map<string, DatasetOptions>;
|
||||
|
||||
/**
|
||||
* List of presented dataset ids.
|
||||
|
@ -43,6 +53,13 @@ export class GeomonTimeseriesChartComponent implements AfterViewInit {
|
|||
public datasetIds: string[] = [];
|
||||
|
||||
|
||||
/**
|
||||
* List of presented selected dataset ids.
|
||||
*/
|
||||
@Input()
|
||||
public selectedDatasetIds: string[] = [];
|
||||
|
||||
|
||||
/**
|
||||
* The time interval in which the data should presented.
|
||||
*/
|
||||
|
@ -66,12 +83,39 @@ export class GeomonTimeseriesChartComponent implements AfterViewInit {
|
|||
left: 10
|
||||
};
|
||||
|
||||
// private datasetIdsDiffer: IterableDiffer<string>;
|
||||
private selectedDatasetIdsDiffer: IterableDiffer<string>;
|
||||
|
||||
constructor(
|
||||
protected datasetIdResolver: InternalIdHandler,
|
||||
protected datasetApiService: DatasetApiService,
|
||||
protected timeService: TimeService,
|
||||
public datasetService: DatasetService<GeomonTimeseries>,
|
||||
public datasetService: DatasetService<DatasetOptions>,
|
||||
) { }
|
||||
|
||||
public ngDoCheck(): void {
|
||||
// const selectedDatasetIdsChanges = this.selectedDatasetIdsDiffer.diff(this.selectedDatasetIds);
|
||||
// if (selectedDatasetIdsChanges) {
|
||||
// selectedDatasetIdsChanges.forEachAddedItem((addedItem) => {
|
||||
// this.setSelectedId(addedItem.item);
|
||||
// });
|
||||
// selectedDatasetIdsChanges.forEachRemovedItem((removedItem) => {
|
||||
// this.removeSelectedId(removedItem.item);
|
||||
// });
|
||||
// }
|
||||
}
|
||||
|
||||
protected setSelectedId(internalId: string): void {
|
||||
// const internalEntry = this.preparedData.find((e) => e.internalId === internalId);
|
||||
// if (internalEntry) { internalEntry.selected = true; }
|
||||
// this.redrawCompleteGraph();
|
||||
}
|
||||
|
||||
protected removeSelectedId(internalId: string): void {
|
||||
// const internalEntry = this.preparedData.find((e) => e.internalId === internalId);
|
||||
// if (internalEntry) { internalEntry.selected = false; }
|
||||
}
|
||||
|
||||
ngAfterViewInit(): void { // this.createSvg();
|
||||
|
||||
this.canvas = document.getElementById("line-chart") as HTMLCanvasElement;
|
||||
|
@ -83,8 +127,9 @@ export class GeomonTimeseriesChartComponent implements AfterViewInit {
|
|||
|
||||
for (let i = 0; i < this.datasetIds.length; i++) {
|
||||
let datasetId = this.datasetIds[i];
|
||||
let dataset = this.datasetOptions.get(datasetId);
|
||||
this.addDataset(dataset.id, 'https://geomon.geologie.ac.at/52n-sos-webapp/api/');
|
||||
let datasetOptions = this.datasetOptions.get(datasetId);
|
||||
// this.internalId = this.internalIdHandler.resolveInternalId(datasetId);
|
||||
this.addDatasetByInternalId(datasetOptions.internalId);
|
||||
}
|
||||
|
||||
// let firstDatasetId = this.datasetIds[0];
|
||||
|
@ -108,11 +153,17 @@ export class GeomonTimeseriesChartComponent implements AfterViewInit {
|
|||
return this.datasetMap.get(internalId);
|
||||
}
|
||||
|
||||
protected addDatasetByInternalId(internalId: string) {
|
||||
const internalIdObj = this.datasetIdResolver.resolveInternalId(internalId);
|
||||
this.addDataset(internalIdObj.id, internalIdObj.url);
|
||||
}
|
||||
|
||||
protected addDataset(id: string, url: string): void {
|
||||
// this.servicesConnector.getDataset({ id, url }, { locale: this.translateService.currentLang, type: DatasetType.Timeseries }).subscribe(
|
||||
// res => this.loadAddedDataset(res),
|
||||
// error => this.errorHandler.handleDatasetLoadError(error)
|
||||
// );
|
||||
|
||||
this.datasetApiService.getDataset(id, url).subscribe({
|
||||
next: (res: GeomonTimeseries) => this.loadAddedDataset(res),
|
||||
error: (err: any) => console.error('Observer got an error: ' + err),
|
||||
|
@ -252,6 +303,8 @@ export class GeomonTimeseriesChartComponent implements AfterViewInit {
|
|||
for (let i = 0; i < 6; i++) {
|
||||
color += letters[Math.floor(Math.random() * 16)];
|
||||
}
|
||||
let datasetOptions = this.datasetOptions.get(dataset.internalId);
|
||||
datasetOptions.color = color;
|
||||
var newDataset = {
|
||||
label: dataset.label,
|
||||
// backgroundColor: 'rgba(99, 255, 132, 0.2)',
|
||||
|
@ -284,7 +337,7 @@ export class GeomonTimeseriesChartComponent implements AfterViewInit {
|
|||
|
||||
private initChart(): void {
|
||||
|
||||
this.lineChart = new Chart(this.canvas, {
|
||||
this.lineChart = new Chart(this.chartElem.nativeElement, {
|
||||
type: 'line',
|
||||
data: {
|
||||
// labels: [1500, 1600, 1700, 1750, 1800, 1850, 1900, 1950, 1999, 2050],
|
||||
|
@ -319,6 +372,8 @@ export class GeomonTimeseriesChartComponent implements AfterViewInit {
|
|||
]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
plugins: {
|
||||
zoom: {
|
||||
pan: {
|
||||
|
@ -379,7 +434,8 @@ export class GeomonTimeseriesChartComponent implements AfterViewInit {
|
|||
// }
|
||||
// }
|
||||
});
|
||||
this.width = this.calculateWidth() - 20; // add buffer to the left to garantee visualization of last date (tick x-axis)
|
||||
|
||||
// this.width = this.calculateWidth() - 20; // add buffer to the left to garantee visualization of last date (tick x-axis)
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { GeomonPlatform } from "./platform";
|
||||
import { InternalIdHandler } from '../../common/components/services/internal-id-handler.service';
|
||||
|
||||
const INTERNAL_ID_SEPERATOR = '_';
|
||||
|
||||
|
@ -37,7 +38,7 @@ export class GeomonDataset {
|
|||
public url: string,
|
||||
public label: string
|
||||
) {
|
||||
// this.internalId = new InternalIdHandler().createInternalId(url, id);
|
||||
this.internalId = new InternalIdHandler().createInternalId(url, id);
|
||||
}
|
||||
// public get internalId(): string {
|
||||
// return this.url + INTERNAL_ID_SEPERATOR + this.id;
|
||||
|
@ -69,6 +70,7 @@ export class ParameterConstellation {
|
|||
public procedure: Parameter;
|
||||
public phenomenon: Parameter;
|
||||
public category: Parameter;
|
||||
public platform: Parameter;
|
||||
}
|
||||
interface Parameter {
|
||||
id: string;
|
||||
|
@ -100,6 +102,23 @@ export interface DataConst extends GeomonTimeseries {
|
|||
}
|
||||
|
||||
|
||||
export interface DatasetFilter {
|
||||
phenomenon?: string;
|
||||
category?: string;
|
||||
procedure?: string;
|
||||
feature?: string;
|
||||
offering?: string;
|
||||
service?: string;
|
||||
expanded?: boolean;
|
||||
locale?: string;
|
||||
type?: DatasetType;
|
||||
}
|
||||
|
||||
export enum DatasetType {
|
||||
Timeseries = 'timeseries',
|
||||
Trajectory = 'trajectory',
|
||||
Profile = 'profile'
|
||||
}
|
||||
|
||||
// export class TimeseriesData {
|
||||
// public id: string;
|
||||
|
|
111
src/shared/models/options.ts
Normal file
111
src/shared/models/options.ts
Normal file
|
@ -0,0 +1,111 @@
|
|||
export class DatasetOptions {
|
||||
|
||||
/**
|
||||
* internal dataset id
|
||||
*/
|
||||
public internalId: string;
|
||||
|
||||
/**
|
||||
* type to display the data
|
||||
* default is 'line'
|
||||
*/
|
||||
public type: 'line' | 'bar' = 'line';
|
||||
|
||||
/**
|
||||
* color of the dataset
|
||||
*/
|
||||
public color: string;
|
||||
|
||||
/**
|
||||
* show or hide in the graph
|
||||
*/
|
||||
public visible: boolean = true;
|
||||
|
||||
/**
|
||||
* separate y axis of datasets with same unit
|
||||
*/
|
||||
public separateYAxis?: boolean = false;
|
||||
|
||||
/**
|
||||
* align graph that zero y axis is visible
|
||||
*/
|
||||
public zeroBasedYAxis?: boolean = false;
|
||||
|
||||
/**
|
||||
* auto zoom when range selection
|
||||
*/
|
||||
public autoRangeSelection?: boolean = false;
|
||||
|
||||
/**
|
||||
* marker to request dataset data generalized
|
||||
*/
|
||||
public generalize?: boolean = false;
|
||||
|
||||
/**
|
||||
* list of visible reference values
|
||||
*/
|
||||
public showReferenceValues: ReferenceValueOption[] = [];
|
||||
|
||||
/**
|
||||
* radius of graphpoint
|
||||
* default is 0
|
||||
*/
|
||||
public pointRadius: number = 0;
|
||||
|
||||
/**
|
||||
* the start of, where to start with the bar chart
|
||||
* See also: https://momentjs.com/docs/#/manipulating/start-of/
|
||||
* default is 'hour'
|
||||
*/
|
||||
public barStartOf: string = 'hour';
|
||||
|
||||
|
||||
/**
|
||||
* width of graphline
|
||||
*/
|
||||
public lineWidth: number = 1;
|
||||
|
||||
/**
|
||||
* dasharray to structure the line or bar chart border
|
||||
* See also here: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray
|
||||
*/
|
||||
public lineDashArray: number | number[];
|
||||
|
||||
/**
|
||||
* color of the point border
|
||||
*/
|
||||
public pointBorderColor: string;
|
||||
|
||||
/**
|
||||
* width of the point border
|
||||
*/
|
||||
public pointBorderWidth: number = 0;
|
||||
|
||||
/**
|
||||
* min and max range of y axis
|
||||
*/
|
||||
public yAxisRange?: MinMaxRange;
|
||||
|
||||
constructor(
|
||||
internalId: string,
|
||||
color: string
|
||||
) {
|
||||
this.internalId = internalId;
|
||||
this.color = color;
|
||||
}
|
||||
}
|
||||
|
||||
export interface ReferenceValueOption {
|
||||
id: string;
|
||||
color: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* numbered range with a min and a max value
|
||||
*
|
||||
* @export
|
||||
*/
|
||||
export interface MinMaxRange {
|
||||
min?: number;
|
||||
max?: number;
|
||||
}
|
Loading…
Add table
Reference in a new issue