- add bar component wit d3.js

- new dataset-by-station-selector.component with angular/material/dialog
- zoom.componentn: disable button at lasst zoom level
This commit is contained in:
Arno Kaimbacher 2021-09-14 15:22:31 +02:00
parent 363cdb0681
commit 427b7b9c91
25 changed files with 1840 additions and 55 deletions

View file

@ -191,3 +191,23 @@ https://www.npmjs.com/package/@fortawesome/angular-fontawesome
npm install @fortawesome/fontawesome-svg-core
npm install @fortawesome/free-solid-svg-icons
npm install @fortawesome/angular-fontawesome@latest
=========================================== d3 ============================
npm install d3 --save
npm install @types/d3 --save-dev
npx @angular/cli generate component bar --skip-tests
CREATE src/app/bar/bar.component.html (18 bytes)
CREATE src/app/bar/bar.component.ts (263 bytes)
CREATE src/app/bar/bar.component.css (0 bytes)
UPDATE src/app/app.module.ts (3039 bytes)
========================================== dialog =========================
npm install --save @angular/material @angular/cdk

1319
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -24,6 +24,7 @@
"@babel/plugin-proposal-decorators": "^7.14.5",
"@babel/preset-env": "^7.14.8",
"@babel/preset-typescript": "^7.14.5",
"@types/d3": "^7.0.0",
"angular2-template-loader": "^0.6.2",
"babel-loader": "^8.2.2",
"css-loader": "^6.2.0",
@ -45,8 +46,10 @@
"webpack-merge": "^5.8.0"
},
"dependencies": {
"@angular/cdk": "^12.2.5",
"@angular/core": "^12.1.4",
"@angular/forms": "^12.1.4",
"@angular/material": "^12.2.5",
"@angular/platform-browser": "^12.1.4",
"@angular/platform-browser-dynamic": "^12.1.4",
"@angular/router": "^12.2.3",
@ -61,6 +64,7 @@
"babel-plugin-transform-typescript-metadata": "^0.3.2",
"bulma": "^0.9.3",
"core-js": "^3.16.0",
"d3": "^7.0.1",
"leaflet": "^1.7.1",
"rxjs": "^7.3.0",
"zone.js": "^0.11.4"

View file

@ -1,5 +1,6 @@
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { BarComponent } from './components/bar/bar.component';
//neu
import { DashboardComponent } from './dashboard/dashboard.component';
@ -12,7 +13,8 @@ const routes: Routes = [
{ path: '', redirectTo: '/map', pathMatch: 'full' },
{ path: 'dashboard', component: DashboardComponent },
// { path: 'detail/:id', component: HeroDetailComponent },
{ path: 'map', component: MapViewComponent }
{ path: 'map', component: MapViewComponent },
{ path: 'bar', component: BarComponent }
];
@NgModule({

View file

@ -27,6 +27,9 @@
<a class="navbar-item" routerLink="/map" routerLinkActive="is-active">
Map
</a>
<a class="navbar-item" routerLink="/bar" routerLinkActive="is-active">
Bar
</a>
</div>
<div class="navbar-end">
<!-- <div class="navbar-item">

View file

@ -19,27 +19,30 @@ import { StationService } from "./services/station.service";
import { MessagesComponent } from './messages/messages.component';
import { MessageService } from "./services/message.service";
import { MapService } from '../common/components/services/map.service';
import { BarComponent } from './components/bar/bar.component';
// import { LocateService } from '@helgoland/map';
// import { MapCache } from '@helgoland/map';
// siehe https://52north.github.io/helgoland-toolbox/additional-documentation/how-tos/integrate-a-map-component.html
// https://52north.github.io/helgoland-toolbox/components/LocateControlComponent.html#source
// import {
// DatasetApiInterface, ApiV3InterfaceService, SplittedDataDatasetApiInterface, DatasetApiV3Connector, HelgolandServicesConnector
// } from '@helgoland/core';
// import { HelgolandCoreModule } from "@helgoland/core";
// import { HelgolandMapModule } from '@helgoland/map';
// import 'core-js';
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 { MAT_DIALOG_DEFAULT_OPTIONS } from '@angular/material';
@NgModule({
// declarations: The components, directives, and pipes that belong to this NgModule.
declarations: [AppComponent, MapComponent, DashboardComponent, MessagesComponent, MapViewComponent],
declarations: [AppComponent, MapComponent, DashboardComponent, MessagesComponent, MapViewComponent, BarComponent, DatasetByStationSelectorComponent],
entryComponents: [
DatasetByStationSelectorComponent
],
// imports: Other modules whose exported classes are needed by component templates declared in this NgModule.
imports: [BrowserModule, HttpClientModule, AppRoutingModule, ComponentsModule],
imports: [BrowserModule, HttpClientModule, AppRoutingModule, ComponentsModule, BrowserAnimationsModule, MatDialogModule],
providers: [
MarkerService, PopupService, HttpService, DatasetApiService, StationService, MessageService, MapService
MarkerService, PopupService, HttpService, DatasetApiService, StationService, MessageService, MapService,
// {
// provide: DatasetApiInterface,
// useClass: SplittedDataDatasetApiInterface,

View file

View file

@ -0,0 +1,2 @@
<h2>Bar Chart</h2>
<figure id="bar"></figure>

View file

@ -0,0 +1,75 @@
import { Component, OnInit } from '@angular/core';
import * as d3 from 'd3';
@Component({
selector: 'app-bar',
templateUrl: './bar.component.html',
styleUrls: ['./bar.component.css']
})
export class BarComponent implements OnInit {
private data = [
{ "Framework": "Vue", "Stars": "166443", "Released": "2014" },
{ "Framework": "React", "Stars": "150793", "Released": "2013" },
{ "Framework": "Angular", "Stars": "62342", "Released": "2016" },
{ "Framework": "Backbone", "Stars": "27647", "Released": "2010" },
{ "Framework": "Ember", "Stars": "21471", "Released": "2011" },
];
private svg: any;
private margin = 50;
private width = 750 - (this.margin * 2);
private height = 400 - (this.margin * 2);
constructor() { }
ngOnInit(): void {
this.createSvg();
this.drawBars(this.data);
}
private createSvg(): void {
this.svg = d3.select("figure#bar")
.append("svg")
.attr("width", this.width + (this.margin * 2))
.attr("height", this.height + (this.margin * 2))
.append("g")
.attr("transform", "translate(" + this.margin + "," + this.margin + ")");
}
private drawBars(data: any[]): void {
// Create the X-axis band scale
const x = d3.scaleBand()
.range([0, this.width])
.domain(data.map(d => d.Framework))
.padding(0.2);
// Draw the X-axis on the DOM
this.svg.append("g")
.attr("transform", "translate(0," + this.height + ")")
.call(d3.axisBottom(x))
.selectAll("text")
.attr("transform", "translate(-10,0)rotate(-45)")
.style("text-anchor", "end");
// Create the Y-axis band scale
const y = d3.scaleLinear()
.domain([0, 200000])
.range([this.height, 0]);
// Draw the Y-axis on the DOM
this.svg.append("g")
.call(d3.axisLeft(y));
// Create and fill the bars
this.svg.selectAll("bars")
.data(data)
.enter()
.append("rect")
.attr("x", (d: any) => x(d.Framework))
.attr("y", (d: any) => y(d.Stars))
.attr("width", x.bandwidth())
.attr("height",(d: any) => this.height - y(d.Stars))
.attr("fill", "#d04a35");
}
}

View file

@ -0,0 +1,48 @@
<!-- <div class="item" *ngFor="let timeseries of phenomenonMatchedList" (click)="toggle(timeseries)">
<div *ngIf="counter">
{{counter}} timeseries are loading...
</div>
<div>
<span
*ngIf="timeseries.parameters.category.label && timeseries.parameters.category.label != timeseries.parameters.phenomenon.label">({{timeseries.parameters.category.label}})</span>
<div class="additionalInfo" *ngIf="timeseries.lastValue">
<span>{{timeseries.lastValue.value}}</span>
<span>{{timeseries.uom}}</span>
</div>
</div>
</div> -->
<!-- <h1 mat-dialog-title>{{platform?.label}}</h1>
<mat-dialog-content>
<span>test</span>
</mat-dialog-content>
<mat-dialog-actions>
<button mat-raised-button mat-dialog-close>close</button>
</mat-dialog-actions> -->
<h2 mat-dialog-title>{{platform?.label}}</h2>
<mat-dialog-content >
<input matInput
placeholder="Course Description"
formControlName="description">
</mat-dialog-content>
<mat-dialog-actions>
<button class="mat-raised-button"
(click)="close()">
Close
</button>
<button class="mat-raised-button mat-primary">Save</button>
</mat-dialog-actions>

View file

@ -0,0 +1,13 @@
:host {
.item {
&+.item {
padding-top: 10px;
}
&.error {
display: none;
}
label {
margin-bottom: 0;
}
}
}

View file

@ -0,0 +1,101 @@
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { GeomonPlatform } from './../../../shared/models/platform';
import { DatasetApiService } from './../../services/dataset-api.service';
// https://github.com/52North/helgoland-toolbox/blob/fe6af1b9df0e5d78eeec236e4690aeb7dc92119b/libs/selector/src/lib/dataset-by-station-selector/dataset-by-station-selector.component.ts#L20
import { GeomonTimeseries, GeomonDataset } from './../../../shared/models/dataset';
import { Station } from './../../../shared/models/station';
import { MatDialogRef } from '@angular/material/dialog';
// https://material.angular.io/components/dialog/overview
// https://blog.angular-university.io/angular-material-dialog/
// https://github.com/angular-university/angular-material-course/blob/3-dialog-finished/src/app/course-dialog/course-dialog.component.html
export class SelectableDataset extends GeomonTimeseries {
public selected: boolean;
}
@Component({
selector: 'gba-dataset-by-station-selector',
templateUrl: './dataset-by-station-selector.component.html',
styleUrls: ['./dataset-by-station-selector.component.scss']
})
export class DatasetByStationSelectorComponent implements OnInit {
@Input()
public station: Station;//GeomonPlatform;
public platform: GeomonPlatform;
@Input()
public url: string;
@Input()
public defaultSelected = false;
@Input()
public phenomenonId: string;
@Output()
public onSelectionChanged: EventEmitter<SelectableDataset[]> = new EventEmitter<SelectableDataset[]>();
public phenomenonMatchedList: SelectableDataset[] = [];
public othersList: SelectableDataset[] = [];
public counter: number;
constructor(
protected datasetApiService: DatasetApiService,
private dialogRef: MatDialogRef<DatasetByStationSelectorComponent>,
) { }
public ngOnInit() {
this.datasetApiService.getPlatform(this.station.id, 'https://geomon.geologie.ac.at/52n-sos-webapp/api/')
.subscribe((platform) => {
this.platform = platform;
this.counter = 0;
this.platform.datasetIds.forEach(id => {
this.counter++;
this.datasetApiService.getDataset( id, this.url, { type: 'timeseries' })
.subscribe((result) => {
this.prepareResult(result as SelectableDataset, this.defaultSelected);
this.counter--;
}, (error) => {
this.counter--;
});
});
});
}
public toggle(timeseriesDataset: SelectableDataset) {
timeseriesDataset.selected = !timeseriesDataset.selected;
this.updateSelection();
}
protected prepareResult(result: SelectableDataset, selection: boolean) {
result.selected = selection;
if (this.phenomenonId) {
if (result.parameters.phenomenon.id === this.phenomenonId) {
this.phenomenonMatchedList.push(result);
} else {
this.othersList.push(result);
}
} else {
this.phenomenonMatchedList.push(result);
}
this.updateSelection();
}
private updateSelection() {
const selection = this.phenomenonMatchedList.filter((entry) => entry.selected);
this.onSelectionChanged.emit(selection);
}
close() {
this.dialogRef.close();
}
}

View file

@ -2,7 +2,7 @@
<div class="stations-menu">
<h2>Stations</h2>
<a class="station" *ngFor="let station of stations" routerLink="/detail/{{station.id}}">
{{ station.properties.label }}
{{ station.label }}
</a>
</div>
</div>

View file

@ -2,6 +2,7 @@ import { Component, OnInit } from '@angular/core';
// import { StationService } from '../services/station.service';
import { DatasetApiService } from '../services/dataset-api.service';
import { Station } from '../../shared/models/station';
import { GeomonPlatform } from '../../shared/models/platform';
@Component({
selector: 'app-dashboard',
@ -10,7 +11,7 @@ import { Station } from '../../shared/models/station';
})
export class DashboardComponent implements OnInit {
public stations: Station[] = [];
public stations: GeomonPlatform[] = [];
constructor(private datasetApiService: DatasetApiService) { }
@ -21,9 +22,9 @@ export class DashboardComponent implements OnInit {
getStations(): void {
// this.stationService.getStations()
// .subscribe(stations => this.stations = stations);
this.datasetApiService.getStations('https://geomon.geologie.ac.at/52n-sos-webapp/api/')
this.datasetApiService.getPlatforms('https://geomon.geologie.ac.at/52n-sos-webapp/api/')
.subscribe((stations) => {
this.stations = stations
this.stations = stations;
});
}

View file

@ -6,5 +6,4 @@
<div [attr.id]="mapId" class="map-container mapDesktop">
<gba-locate-button [mapId]="mapId"></gba-locate-button>
<gba-zoom-control [mapId]="mapId"></gba-zoom-control>
</div>

View file

@ -1,11 +1,12 @@
// https://github.com/52North/helgoland-toolbox/blob/c2c2eda20353c469a7aa4a6a118a810723af6622/libs/map/src/lib/selector/station-map-selector/station-map-selector.component.ts
import { Component, AfterViewInit, OnChanges, SimpleChanges, EventEmitter, Input, Output } from '@angular/core';
import { Component, AfterViewInit, OnChanges, SimpleChanges, EventEmitter, Input, Output, ViewChild } from '@angular/core';
import { Control, FeatureGroup, geoJSON, circleMarker, FitBoundsOptions, LatLngBoundsExpression } from 'leaflet';
import { MarkerService } from '../services/marker.service';
import { DatasetApiService } from '../services/dataset-api.service';
import { BaseMapComponent } from './base-map.component';
import { PopupService } from '../services/popup.service';
import { MapService } from '../../common/components/services/map.service';
import { ZoomControlComponent } from '../../common/components/zoom-control/zoom.component';
@Component({
selector: 'app-map',
@ -17,6 +18,8 @@ export class MapComponent
extends BaseMapComponent
implements OnChanges, AfterViewInit {
@ViewChild(ZoomControlComponent) zoom:ZoomControlComponent;
/**
* @input The serviceUrl, where the selection should be loaded.
@ -54,6 +57,7 @@ export class MapComponent
ngAfterViewInit(): void {
this.initMap();
this.map.on("zoomend zoomlevelschange", this.zoom._updateDisabled, this.zoom);
// this.markerService.makeCapitalMarkers(this.map);
// this.markerService.makeCapitalCircleMarkers(this.map);
this.datasetApiService.getStations('https://geomon.geologie.ac.at/52n-sos-webapp/api/')
@ -74,7 +78,7 @@ export class MapComponent
marker.on('click', () => {
this.onSelected.emit(station);
});
marker.bindPopup(this.popupService.makeCapitalPopup(station.properties));
// marker.bindPopup(this.popupService.makeCapitalPopup(station.properties));
}
});
this.markerFeatureGroup.addTo(this.map);

View file

@ -11,7 +11,10 @@ import { HttpService } from './http.service';
import { HttpRequestOptions } from '../../shared/models/http-requests';
import { HttpParams } from '@angular/common/http';
import { MessageService } from './message.service';
import { GeomonPlatform } from '../../shared/models/platform';
import { Dataset, GeomonTimeseries } from '../../shared/models/dataset';
import { map } from 'rxjs/operators';
// @Injectable({
// providedIn: 'root'
@ -33,12 +36,60 @@ export class DatasetApiService {
}
public getStations(apiUrl: string, params?: any, options?: HttpRequestOptions): Observable<Station[]> {
const url = this.createRequestUrl(apiUrl, 'features');
const url = this.createRequestUrl(apiUrl, 'features'); //https://geomon.geologie.ac.at/52n-sos-webapp/api/features
let stations = this.requestApi<Station[]>(url, params, options);
this.messageService.add('StationService: fetched stations');
return stations;
}
public getFeature(
id: string,
apiUrl: string,
params?: any,
options?: HttpRequestOptions
): Observable<Station> {
const url = this.createRequestUrl(apiUrl, 'features', id);
return this.requestApi<Station>(url, params, options);
}
public getPlatforms(apiUrl: string, params?: any, options?: HttpRequestOptions): Observable<GeomonPlatform[]> {
// const url = this.createRequestUrl(apiUrl, 'platforms');
// return this.requestApi<GeomonPlatform[]>(url, params, options);
return this.getStations(apiUrl, params, options).pipe(map(res => res.map(f => this.createGeomonPlatform(f))));
}
public getPlatform(
id: string,
apiUrl: string,
params?: any,
options?: HttpRequestOptions
): Observable<GeomonPlatform> {
// const url = this.createRequestUrl(apiUrl, 'platforms', id);
// return this.requestApi<GeomonPlatform>(url, params, options);
return this.getFeature(id, apiUrl,params, options).pipe(map(res => this.createGeomonPlatform(res)));
}
public getDataset(id: string, apiUrl: string, params?: any, options?: HttpRequestOptions): Observable<GeomonTimeseries> {
const url = this.createRequestUrl(apiUrl, 'datasets', id);
return this.requestApi<GeomonTimeseries>(url, params, options);
//.pipe(
// map((res) => this.prepareDataset(res, apiUrl))
// );
}
//#region Helper method
protected createGeomonPlatform(feature: Station): GeomonPlatform {
const datasetIds = [];
for (const key in feature.properties.datasets) {
if (feature.properties.datasets.hasOwnProperty(key)) {
datasetIds.push(key);
}
}
return new GeomonPlatform(feature.id, feature.properties.label, datasetIds, feature.geometry);
}
protected createRequestUrl(apiUrl: string, endpoint: string, id?: string) {
// TODO Check whether apiUrl ends with slash
@ -63,4 +114,5 @@ export class DatasetApiService {
return headers;
}
//#endregion
}

View file

@ -1,10 +1,15 @@
import { Component, OnInit } from '@angular/core';
import { ParameterFilter, Station } from '@helgoland/core';
import { ParameterFilter } from '@helgoland/core';
import { GeomonPlatform } from './../../../shared/models/platform';
import { LayerOptions } from '@helgoland/map';
import { Marker, MapOptions, Control, icon, LatLngBoundsExpression } from 'leaflet';
// optional, to adapt leaflet markers
import { Station } from '../../../shared/models/station';
import { DatasetByStationSelectorComponent } from './../../components/dataset-by-station-selector/dataset-by-station-selector.component';
import { MatDialog } from '@angular/material/dialog';
// optional, to adapt leaflet markers
Marker.prototype.options.icon = icon({
iconRetinaUrl: 'assets/img/marker-icon-2x.png',
iconUrl: 'assets/img/marker-icon.png',
@ -16,6 +21,8 @@ Marker.prototype.options.icon = icon({
shadowSize: [41, 41]
});
const DIALOG_MAX_WIDTH = '95%';
@Component({
selector: 'gba-map-view',
templateUrl: './map-view.component.html',
@ -23,7 +30,9 @@ Marker.prototype.options.icon = icon({
})
export class MapViewComponent implements OnInit {
constructor() {
constructor(
private dialog: MatDialog,
) {
//
}
@ -56,7 +65,16 @@ export class MapViewComponent implements OnInit {
};
public onStationSelected(station: Station) {
console.log('Clicked station: ' + station.properties.label);
// console.log('Clicked station: ' + station.properties.label);
const dialogRef = this.dialog.open(DatasetByStationSelectorComponent, {
height: '400px',
width: '600px',
maxWidth: DIALOG_MAX_WIDTH ,
hasBackdrop: true, //Here line to add
// panelClass: 'custom-dialog-container'
});
dialogRef.componentInstance.station = station;
dialogRef.componentInstance.url = this.providerUrl;
}
public onMapInitialized(newItem: string) {

View file

@ -1,8 +1,8 @@
<div class="gba-control-zoom btn-group-vertical map-control">
<button type="button" class="button is-light is-small" (click)="zoomIn()">
<button #inputPlus type="button" class="button is-light is-small" (click)="zoomIn()">
<fa-icon [icon]="faPlus"></fa-icon>
</button>
<button type="button" class="button is-light is-small" (click)="zoomOut()">
<button #inputMinus type="button" class="button is-light is-small" (click)="zoomOut()">
<fa-icon [icon]="faMinus"></fa-icon>
</button>
</div>

View file

@ -1,4 +1,4 @@
import { Component, Input } from '@angular/core';
import { Component, Input, ElementRef, ViewChild } from '@angular/core';
import { MapService } from '../services/map.service';
import { faPlus, faMinus } from '@fortawesome/free-solid-svg-icons';
@ -17,6 +17,9 @@ export class ZoomControlComponent {
*/
@Input() public mapId: string;
@ViewChild('inputPlus') private _inputPlus:ElementRef;
@ViewChild('inputMinus') private _inpuMinus:ElementRef;
constructor(
protected mapService: MapService
) {
@ -31,4 +34,28 @@ export class ZoomControlComponent {
let map = this.mapService.getMap(this.mapId);
map.zoomOut();
}
_updateDisabled() {
let map = this.mapService.getMap(this.mapId);
// let className = 'leaflet-disabled';
// this._inputPlus.nativeElement.classList.remove(className);
this._inputPlus.nativeElement.disabled = false;
this._inputPlus.nativeElement.setAttribute('aria-disabled', 'false');
// this._inpuMinus.nativeElement.classList.remove(className);
this._inpuMinus.nativeElement.disabled = false;
this._inpuMinus.nativeElement.setAttribute('aria-disabled', 'false');
if (map.getZoom() === map.getMinZoom()) {
// this._inpuMinus.nativeElement.classList.add(className);
this._inpuMinus.nativeElement.disabled = true;
this._inpuMinus.nativeElement.setAttribute('aria-disabled', 'true');
}
if (map.getZoom() === map.getMaxZoom()) {
// this._inputPlus.nativeElement.classList.add(className);
this._inputPlus.nativeElement.disabled = true;
this._inputPlus.nativeElement.setAttribute('aria-disabled', 'true');
}
}
}

View file

@ -0,0 +1,80 @@
import { GeomonPlatform } from "./platform";
export class Dataset {
public id: string;
public label: string;
public url: string;
public uom: string;
public internalId: string;
public firstValue: FirstLastValue;
public lastValue: FirstLastValue;
public referenceValues: ReferenceValue[];
public datasetType: any;
public platformType: any;
public seriesParameters?: any;
public renderingHints: RenderingHints;
public parameters: any;
}
export class GeomonDataset {
public internalId: string;
constructor(
public id: string,
public url: string,
public label: string
) {
// this.internalId = new InternalIdHandler().createInternalId(url, id);
}
}
export class GeomonTimeseries extends GeomonDataset {
constructor(
public id: string,
public url: string,
public label: string,
public uom: string,
public platform: GeomonPlatform,
public firstValue: FirstLastValue,
public lastValue: FirstLastValue,
public referenceValues: ReferenceValue[],
public renderingHints: RenderingHints,
public parameters: ParameterConstellation,
) {
super(id, url, label);
}
}
export class ParameterConstellation {
public service: Parameter;
public offering: Parameter;
public feature: Parameter; //Feature;
public procedure: Parameter;
public phenomenon: Parameter;
public category: Parameter;
}
interface Parameter {
id: string;
label: string;
}
export class FirstLastValue {
public timestamp: number;
public value: number;
}
export class ReferenceValue {
public referenceValueId: string;
public label: string;
public lastValue: FirstLastValue;
public color?: string;
public visible?: boolean;
}
export interface RenderingHints {
chartType: string;
properties: {
color: string;
};
}

View file

@ -0,0 +1,10 @@
export class GeomonPlatform {
constructor(
public id: string,
public label: string,
public datasetIds: string[],
public geometry?: GeoJSON.GeometryObject
) { }
}

View file

@ -10,25 +10,32 @@ export interface Station {
export interface StationProperties {
id: string;
label: string;
// timeseries: TimeseriesCollection | Timeseries;
datasets: Dataset;
}
export interface Dataset
{
id: string;
label: string;
href: string,
domainId: string;
}
// export class TimeseriesCollection {
// [key: string]: ParameterConstellation;
// }
interface Timeseries {
id: string;
label: string;
url: string;
uom: string;
internalId: string;
// firstValue;
// lastValue;
// referenceValues;
station: Station;
// parameters;
// statusIntervals?;
// hasData = false;
// public renderingHints;
}
// interface Timeseries {
// id: string;
// label: string;
// url: string;
// uom: string;
// internalId: string;
// // firstValue;
// // lastValue;
// // referenceValues;
// station: Station;
// // parameters;
// // statusIntervals?;
// // hasData = false;
// // public renderingHints;
// }

View file

@ -1,3 +1,8 @@
// @import '~@angular/material';
// @import '~@angular/cdk/overlay-prebuilt.css';
@import '~@angular/material/prebuilt-themes/purple-green.css';
.leaflet-pane {
z-index: 28;
}