- add bulma style

- add components: messages, locate-button
- move index.html into src folder
- move to angular build tools
- styles.css -> styles.scss
This commit is contained in:
Arno Kaimbacher 2021-09-07 08:36:17 +02:00
parent 220944b115
commit df3561235d
37 changed files with 12724 additions and 645 deletions

2
.vscode/launch.json vendored
View file

@ -8,7 +8,7 @@
"type": "pwa-chrome", "type": "pwa-chrome",
"request": "launch", "request": "launch",
"name": "Launch Chrome against localhost", "name": "Launch Chrome against localhost",
"url": "http://localhost:8080", "url": "http://localhost:4200",
"webRoot": "${workspaceFolder}" "webRoot": "${workspaceFolder}"
} }
] ]

View file

@ -48,7 +48,7 @@
"src/assets" "src/assets"
], ],
"styles": [ "styles": [
"src/styles.css" "src/styles.scss"
], ],
"scripts": [] "scripts": []
}, },
@ -115,7 +115,7 @@
"src/assets" "src/assets"
], ],
"styles": [ "styles": [
"src/styles.css" "src/styles.scss"
], ],
"scripts": [] "scripts": []
} }

View file

@ -12,8 +12,12 @@ npm install --save-dev @babel/plugin-proposal-decorators
npm install --save @angular/core @angular/platform-browser-dynamic @angular/platform-browser npm install --save @angular/core @angular/platform-browser-dynamic @angular/platform-browser
zusätzlich routing:
npm install --save @angular/router npm install --save @angular/router
wieder löschen:+ tsconfig.json + tsconfig.app.json
npm install --save-dev @angular-devkit/build-angular
npm install --save leaflet@latest npm install --save leaflet@latest
# Polyfills for angular # Polyfills for angular
@ -25,7 +29,7 @@ siehe https://medium.com/@sahayatanakul2867/configuration-of-webpack4-and-angula
npm install --save-dev html-loader style-loader angular2-template-loader css-loader to-string-loader npm install --save-dev html-loader style-loader angular2-template-loader css-loader to-string-loader
npm install --save-dev raw-loader npm install --save-dev raw-loader
npm install --save-dev sass-loader node-sass
test map: test map:
npm install --save-dev @angular/cli npm install --save-dev @angular/cli
@ -56,6 +60,15 @@ npx @angular/cli generate service http --skip-tests
npx @angular/cli generate component dashboard --skip-tests npx @angular/cli generate component dashboard --skip-tests
ng g c messages --skip-tests
CREATE src/app/messages/messages.component.html (23 bytes)
CREATE src/app/messages/messages.component.ts (283 bytes)
CREATE src/app/messages/messages.component.css (0 bytes)
UPDATE src/app/app.module.ts (2468 bytes)
create service:
npx @angular/cli generate service message --skip-tests
========================================= ExtractTextPlugin ================================================== ========================================= ExtractTextPlugin ==================================================
@ -131,6 +144,7 @@ Install dependencies
npm install --save rxjs npm install --save rxjs
für mergen der config files:
npm install --save-dev webpack-merge npm install --save-dev webpack-merge
========================= cretae html file for production ========================= cretae html file for production
@ -158,3 +172,15 @@ This will generate a file dist/index.html containing the following:
npx @angular/cli generate service popup --skip-tests npx @angular/cli generate service popup --skip-tests
CREATE src/app/popup.service.ts (134 bytes) CREATE src/app/popup.service.ts (134 bytes)
npm install --save bulma
// "ng": "ng",
// "start": "ng serve",
// "build": "ng build",
// "watch": "ng build --watch --configuration development",

12561
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -6,7 +6,9 @@
"scripts": { "scripts": {
"test": "echo \"Error: no test specified\" && exit 1", "test": "echo \"Error: no test specified\" && exit 1",
"prod": "rm -rf dist && webpack --progress --config webpack.production.js", "prod": "rm -rf dist && webpack --progress --config webpack.production.js",
"dev": "webpack serve --config webpack.development.js --content-base=./ --hot --progress --port 8080" "dev": "webpack serve --config webpack.development.js --content-base=./ --hot --progress --port 4200"
}, },
"keywords": [ "keywords": [
"geomonitoring", "geomonitoring",
@ -18,6 +20,7 @@
"author": "Arno Kaimbacher", "author": "Arno Kaimbacher",
"license": "MIT", "license": "MIT",
"devDependencies": { "devDependencies": {
"@angular-devkit/build-angular": "^12.2.4",
"@angular/cli": "^12.1.4", "@angular/cli": "^12.1.4",
"@babel/plugin-proposal-class-properties": "^7.14.5", "@babel/plugin-proposal-class-properties": "^7.14.5",
"@babel/plugin-proposal-decorators": "^7.14.5", "@babel/plugin-proposal-decorators": "^7.14.5",
@ -32,7 +35,9 @@
"html-webpack-plugin": "^5.3.2", "html-webpack-plugin": "^5.3.2",
"img-loader": "^4.0.0", "img-loader": "^4.0.0",
"mini-css-extract-plugin": "^2.1.0", "mini-css-extract-plugin": "^2.1.0",
"node-sass": "^6.0.1",
"raw-loader": "^4.0.2", "raw-loader": "^4.0.2",
"sass-loader": "^12.1.0",
"style-loader": "^3.2.1", "style-loader": "^3.2.1",
"terser-webpack-plugin": "^5.1.4", "terser-webpack-plugin": "^5.1.4",
"url-loader": "^4.1.1", "url-loader": "^4.1.1",
@ -53,6 +58,7 @@
"@helgoland/selector": "^12.0.0-beta.1", "@helgoland/selector": "^12.0.0-beta.1",
"@ngx-translate/http-loader": "^6.0.0", "@ngx-translate/http-loader": "^6.0.0",
"babel-plugin-transform-typescript-metadata": "^0.3.2", "babel-plugin-transform-typescript-metadata": "^0.3.2",
"bulma": "^0.9.3",
"core-js": "^3.16.0", "core-js": "^3.16.0",
"leaflet": "^1.7.1", "leaflet": "^1.7.1",
"rxjs": "^7.3.0", "rxjs": "^7.3.0",

View file

@ -2,7 +2,7 @@
h1 { h1 {
margin-bottom: 0; margin-bottom: 0;
} }
nav a { /* nav a {
padding: 1rem; padding: 1rem;
text-decoration: none; text-decoration: none;
margin-top: 10px; margin-top: 10px;
@ -19,4 +19,4 @@ h1 {
nav a.active { nav a.active {
background-color: black; background-color: black;
} }
*/

View file

@ -1,18 +1,93 @@
<app-map [mapId]="'map'" [mapOptions]="mapOptions" [serviceUrl]="providerUrl" [baseMaps]="baseMaps" <!-- <nav class="navbar">
(onSelected)="onStationSelected($event)" (onMapInitializedEvent)="onMapInitialized($event)"></app-map> <div class="navbar-brand">
<a class="navbar-item">
<img src="https://bulma.io/images/bulma-logo.png">
</a>
</div>
</nav> -->
<nav class="navbar has-shadow" role="navigation" aria-label="main navigation">
<div class="navbar-brand">
<a class="" href="http://geomon.geologie.ac.at/" target="_blank">
<img src="assets/Tethys-icon.png">
</a>
<a role="button" id="menu-icon" class="navbar-burger" aria-label="menu" aria-expanded="false"
data-target="navbarBasicExample">
<span aria-hidden="true"></span>
<span aria-hidden="true"></span>
<span aria-hidden="true"></span>
</a>
</div>
<div id="navbarBasicExample" class="navbar-menu">
<div class="navbar-start">
<span id='map-title' class="navbar-item">
</span>
<a class="navbar-item">
Documentation
</a>
</div>
<div class="navbar-end">
<div class="navbar-item">
<div class="buttons">
<a class="button is-light">
Log in
</a>
</div>
</div>
</div>
</div>
</nav>
<!-- <span>{{ name }} app is running!</span> --> <section id="app" class="hero">
<!-- <div>
<div class="main columns">
<div class="canvas-area is-8 column">
<div id="div-map">
<app-map [mapId]="'map'" [mapOptions]="mapOptions" [serviceUrl]="providerUrl" [baseMaps]="baseMaps"
(onSelected)="onStationSelected($event)" (onMapInitializedEvent)="onMapInitialized($event)">
</app-map>
<!-- <router-outlet></router-outlet> -->
</div>
</div>
<div class="input-area is-4 column">
<div class="columns">
<app-messages></app-messages>
</div>
</div>
</div>
<!-- <app-dashboard></app-dashboard> -->
<!-- <span>{{ name }} app is running!</span> -->
<!-- <div>
<n52-station-map-selector [mapId]="'timeseries'" [serviceUrl]="providerUrl" <n52-station-map-selector [mapId]="'timeseries'" [serviceUrl]="providerUrl"
[mapOptions]="mapOptions"></n52-station-map-selector> [mapOptions]="mapOptions"></n52-station-map-selector>
</div> </div>
<div>Is loading: {{loadingStations}}</div> --> <div>Is loading: {{loadingStations}}</div> -->
<!-- <h1>{{ name }}</h1> <!-- <h1>{{ name }}</h1>
<nav> <nav>
<a routerLink="/dashboard">Dashboard</a> <a routerLink="/dashboard">Dashboard</a>
<a routerLink="/map">Map</a> <a routerLink="/map">Map</a>
</nav> </nav>-->
<router-outlet></router-outlet> --> <!-- <router-outlet></router-outlet> -->
<!-- <app-messages></app-messages> -->
</section>
<!-- footer -->
<!-- <footer class="footer">
<div class="container">
<div class="content has-text-centered">
<p>
Made with <3 by
</p>
</div>
</div>
</footer> -->

View file

@ -1,5 +1,5 @@
import { Component, VERSION } from "@angular/core"; import { Component, VERSION } from "@angular/core";
import '../styles.css'; import '../styles.scss';
// import '../../node_modules/leaflet/dist/leaflet.css'; // import '../../node_modules/leaflet/dist/leaflet.css';
import { ParameterFilter, Phenomenon, Station } from '@helgoland/core'; import { ParameterFilter, Phenomenon, Station } from '@helgoland/core';
@ -23,12 +23,6 @@ Marker.prototype.options.icon = icon({
selector: "app-component", selector: "app-component",
templateUrl: "./app.component.html", templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"] styleUrls: ["./app.component.css"]
// template: `
// <div>
// <h1>{{name}}</h1>
// <div>The number: {{x}}</div>
// </div>
// `,
}) })
export class AppComponent { export class AppComponent {
@ -54,11 +48,11 @@ export class AppComponent {
public statusIntervals = false; public statusIntervals = false;
public mapOptions: MapOptions = { dragging: true, zoomControl: false }; public mapOptions: MapOptions = { dragging: true, zoomControl: false };
private onStationSelected(station: Station) { public onStationSelected(station: Station) {
console.log('Clicked station: ' + station.properties.label); console.log('Clicked station: ' + station.properties.label);
} }
private onMapInitialized(newItem: string) { public onMapInitialized(newItem: string) {
// alert(newItem); console.log(newItem);
} }
} }

View file

@ -7,12 +7,19 @@ import { AppComponent } from './app.component';
import { MapComponent } from './map/map.component'; import { MapComponent } from './map/map.component';
import { DashboardComponent } from './dashboard/dashboard.component'; import { DashboardComponent } from './dashboard/dashboard.component';
import { ComponentsModule } from '../../src/common/components/components.module';
import { HttpClientModule, HttpClient } from '@angular/common/http'; //for http requests import { HttpClientModule, HttpClient } from '@angular/common/http'; //for http requests
import { MarkerService } from './services/marker.service'; import { MarkerService } from './services/marker.service';
import { PopupService } from './services/popup.service'; import { PopupService } from './services/popup.service';
import { DatasetApiService } from "./services/dataset-api.service"; import { DatasetApiService } from "./services/dataset-api.service";
import { HttpService } from "./services/http.service"; import { HttpService } from "./services/http.service";
import { StationService } from "./services/station.service"; import { StationService } from "./services/station.service";
import { MessagesComponent } from './messages/messages.component';
import { MessageService } from "./services/message.service";
// import { HelgolandMapModule } from '@helgoland/map';
// import { LocateService } from '@helgoland/map';
// siehe https://52north.github.io/helgoland-toolbox/additional-documentation/how-tos/integrate-a-map-component.html // 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 // https://52north.github.io/helgoland-toolbox/components/LocateControlComponent.html#source
@ -26,11 +33,11 @@ import { StationService } from "./services/station.service";
@NgModule({ @NgModule({
// declarations: The components, directives, and pipes that belong to this NgModule. // declarations: The components, directives, and pipes that belong to this NgModule.
declarations: [AppComponent, MapComponent, DashboardComponent], declarations: [AppComponent, MapComponent, DashboardComponent, MessagesComponent],
// imports: Other modules whose exported classes are needed by component templates declared in this NgModule. // imports: Other modules whose exported classes are needed by component templates declared in this NgModule.
imports: [BrowserModule, HttpClientModule, AppRoutingModule], imports: [BrowserModule, HttpClientModule, AppRoutingModule, ComponentsModule],
providers: [ providers: [
MarkerService, PopupService, HttpService, DatasetApiService, StationService MarkerService, PopupService, HttpService, DatasetApiService, StationService, MessageService
// { // {
// provide: DatasetApiInterface, // provide: DatasetApiInterface,
// useClass: SplittedDataDatasetApiInterface, // useClass: SplittedDataDatasetApiInterface,

View file

@ -4,7 +4,7 @@ h2 {
text-align: center; text-align: center;
} }
.heroes-menu { .stations-menu {
padding: 0; padding: 0;
margin: auto; margin: auto;
max-width: 1000px; max-width: 1000px;
@ -18,7 +18,7 @@ h2 {
align-items: flex-start; align-items: flex-start;
} }
a { a.station {
background-color: #3f525c; background-color: #3f525c;
border-radius: 2px; border-radius: 2px;
padding: 1rem; padding: 1rem;

View file

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

View file

@ -1,5 +1,6 @@
import { Component, OnInit } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import { StationService } from '../services/station.service'; // import { StationService } from '../services/station.service';
import { DatasetApiService } from '../services/dataset-api.service';
import { Station } from '../../shared/models/station'; import { Station } from '../../shared/models/station';
@Component({ @Component({
@ -11,15 +12,19 @@ export class DashboardComponent implements OnInit {
public stations: Station[] = []; public stations: Station[] = [];
constructor(private stationService: StationService) { } constructor(private datasetApiService: DatasetApiService) { }
ngOnInit() { ngOnInit() {
this.getStations(); this.getStations();
} }
getStations(): void { getStations(): void {
this.stationService.getStations() // this.stationService.getStations()
.subscribe(stations => this.stations = stations); // .subscribe(stations => this.stations = stations);
this.datasetApiService.getStations('https://geomon.geologie.ac.at/52n-sos-webapp/api/')
.subscribe((stations) => {
this.stations = stations
});
} }
} }

View file

@ -1,5 +1,5 @@
import { Directive, OnChanges, SimpleChanges, EventEmitter, Input, Output, OnInit } from '@angular/core'; import { Directive, OnChanges, SimpleChanges, EventEmitter, Input, Output, OnInit } from '@angular/core';
import { Map, Control, MapOptions, LatLngBoundsExpression, tileLayer } from 'leaflet'; import { Map, Control, MapOptions, LatLngBoundsExpression, tileLayer, TileLayer } from 'leaflet';
// import { MarkerService } from '../services/marker.service'; // import { MarkerService } from '../services/marker.service';
import { LayerOptions, LayerMap } from './map-options'; import { LayerOptions, LayerMap } from './map-options';
@ -114,15 +114,20 @@ export abstract class BaseMapComponent implements OnChanges, OnInit {
layerOptions = { layerOptions = {
label: DEFAULT_BASE_LAYER_NAME, label: DEFAULT_BASE_LAYER_NAME,
visible: true, visible: true,
layer: tileLayer(DEFAULT_BASE_LAYER_URL, { layer: tileLayer.wms('https://ows.terrestris.de/osm-gray/service', {
attribution: DEFAULT_BASE_LAYER_ATTRIBUTION format: 'image/png',
attribution: DEFAULT_BASE_LAYER_ATTRIBUTION,
layers: 'OSM-WMS'
}) })
// layer: new TileLayer(DEFAULT_BASE_LAYER_URL, {
// attribution: DEFAULT_BASE_LAYER_ATTRIBUTION
// })
}; };
} }
if (!this.oldBaseLayer.hasOwnProperty[layerOptions.label]) { // if (!this.oldBaseLayer.hasOwnProperty[layerOptions.label]) {
this.oldBaseLayer[layerOptions.label] = layerOptions.layer; this.oldBaseLayer[layerOptions.label] = layerOptions.layer;
if (layerOptions.visible) { layerOptions.layer.addTo(this.map); } if (layerOptions.visible) { layerOptions.layer.addTo(this.map); }
} // }
} }
} }

View file

@ -1,11 +1,11 @@
import * as L from 'leaflet'; import { Layer } from "leaflet";
// https://github.com/52North/helgoland-toolbox/blob/develop/libs/map/src/lib/base/map-options.ts // https://github.com/52North/helgoland-toolbox/blob/develop/libs/map/src/lib/base/map-options.ts
export interface LayerOptions { export interface LayerOptions {
label: string; label: string;
visible: boolean; visible: boolean;
layer: L.Layer; layer: Layer;
} }
// export type LayerMap = Map<string, LayerOptions>; // export type LayerMap = Map<string, LayerOptions>;

View file

@ -1,4 +1,4 @@
.map-container { /* .map-container {
position: absolute; position: absolute;
top: 0; top: 0;
left: 0; left: 0;
@ -14,4 +14,5 @@
#map { #map {
height: 100%; height: 100%;
} } */

View file

@ -1,5 +1,7 @@
<div class="map-container"> <!-- <div class="map-container mapDesktop">
<div class="map-frame"> <div class="map-frame">
<div [attr.id]="mapId" class="map-viewer"></div> <div [attr.id]="mapId" class="map-viewer"></div>
</div> </div>
</div> -->
<div [attr.id]="mapId" class="map-container mapDesktop">
</div> </div>

View file

@ -1,6 +1,6 @@
// https://github.com/52North/helgoland-toolbox/blob/c2c2eda20353c469a7aa4a6a118a810723af6622/libs/map/src/lib/selector/station-map-selector/station-map-selector.component.ts // 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 } from '@angular/core';
import { Map, Control, FeatureGroup, geoJSON, circleMarker, FitBoundsOptions, LatLngBoundsExpression } from 'leaflet'; import { Control, FeatureGroup, geoJSON, circleMarker, FitBoundsOptions, LatLngBoundsExpression } from 'leaflet';
import { MarkerService } from '../services/marker.service'; import { MarkerService } from '../services/marker.service';
import { DatasetApiService } from '../services/dataset-api.service'; import { DatasetApiService } from '../services/dataset-api.service';
import { BaseMapComponent } from './base-map.component'; import { BaseMapComponent } from './base-map.component';
@ -21,8 +21,8 @@ export class MapComponent
/** /**
* @input The serviceUrl, where the selection should be loaded. * @input The serviceUrl, where the selection should be loaded.
*/ */
@Input() // @Input()
public serviceUrl: string; // public serviceUrl: string;
@Output() @Output()
public onSelected: EventEmitter<any> = new EventEmitter<any>(); public onSelected: EventEmitter<any> = new EventEmitter<any>();
@ -37,8 +37,8 @@ export class MapComponent
public fitBoundsMarkerOptions: FitBoundsOptions; public fitBoundsMarkerOptions: FitBoundsOptions;
protected oldBaseLayer: Control.LayersObject = {}; protected oldBaseLayer: Control.LayersObject = {};
protected map: Map; // protected map: Map;
protected zoomControl: Control.Zoom; // protected zoomControl: Control.Zoom;
protected markerFeatureGroup: FeatureGroup; protected markerFeatureGroup: FeatureGroup;
// constructor() { } // constructor() { }
@ -47,6 +47,8 @@ export class MapComponent
private popupService: PopupService, private popupService: PopupService,
protected datasetApiService: DatasetApiService) { protected datasetApiService: DatasetApiService) {
super(); super();
this.markerFeatureGroup = new FeatureGroup();
} }
ngAfterViewInit(): void { ngAfterViewInit(): void {
@ -55,7 +57,7 @@ export class MapComponent
// this.markerService.makeCapitalCircleMarkers(this.map); // this.markerService.makeCapitalCircleMarkers(this.map);
this.datasetApiService.getStations('https://geomon.geologie.ac.at/52n-sos-webapp/api/') this.datasetApiService.getStations('https://geomon.geologie.ac.at/52n-sos-webapp/api/')
.subscribe((res) => { .subscribe((res) => {
this.markerFeatureGroup = new FeatureGroup(); // this.markerFeatureGroup = new FeatureGroup();
if (res instanceof Array && res.length > 0) { if (res instanceof Array && res.length > 0) {
res.forEach((station) => { res.forEach((station) => {
//const marker = this.createDefaultGeometry(entry); //const marker = this.createDefaultGeometry(entry);

View file

@ -0,0 +1,19 @@
/* MessagesComponent's private CSS styles */
h2 {
color: #A80000;
font-family: Arial, Helvetica, sans-serif;
font-weight: lighter;
}
.clear {
color: #333;
background-color: #eee;
margin-bottom: 12px;
padding: 1rem;
border-radius: 4px;
font-size: 1rem;
}
.clear:hover {
color: #fff;
background-color: #42545C;
}

View file

@ -0,0 +1,9 @@
<!-- <p>messages works!</p> -->
<div *ngIf="messageService.messages.length">
<h2>Messages</h2>
<button class="clear"
(click)="messageService.clear()">Clear messages</button>
<div *ngFor="let message of messageService.messages"> {{message}} </div>
</div>

View file

@ -0,0 +1,20 @@
import { Component, OnInit } from '@angular/core';
import { MessageService } from '../services/message.service';
@Component({
selector: 'app-messages',
templateUrl: './messages.component.html',
styleUrls: ['./messages.component.css']
})
export class MessagesComponent implements OnInit {
public messageService;
constructor(messageService: MessageService) {
this.messageService = messageService;
}
ngOnInit(): void {
}
}

View file

@ -10,6 +10,7 @@ import { Station } from '../../shared/models/station';
import { HttpService } from './http.service'; import { HttpService } from './http.service';
import { HttpRequestOptions } from '../../shared/models/http-requests'; import { HttpRequestOptions } from '../../shared/models/http-requests';
import { HttpParams } from '@angular/common/http'; import { HttpParams } from '@angular/common/http';
import { MessageService } from './message.service';
// @Injectable({ // @Injectable({
@ -22,17 +23,20 @@ export class DatasetApiService {
// constructor() { } // constructor() { }
constructor( constructor(
private httpClient: HttpClient, private httpClient: HttpClient,
protected httpService: HttpService,) { protected httpService: HttpService,
private messageService: MessageService) {
} }
public getPhenomena(apiUrl: string, params?, options?) { public getPhenomena(apiUrl: string, params?: any, options?: any) {
const url = this.createRequestUrl(apiUrl, 'phenomena'); const url = this.createRequestUrl(apiUrl, 'phenomena');
return this.requestApi<Phenomenon[]>(url, params, options); return this.requestApi<Phenomenon[]>(url, params, options);
} }
public getStations(apiUrl: string, params?, options?: HttpRequestOptions): Observable<Station[]> { public getStations(apiUrl: string, params?: any, options?: HttpRequestOptions): Observable<Station[]> {
const url = this.createRequestUrl(apiUrl, 'features'); const url = this.createRequestUrl(apiUrl, 'features');
return this.requestApi<Station[]>(url, params, options); let stations = this.requestApi<Station[]>(url, params, options);
this.messageService.add('StationService: fetched stations');
return stations;
} }
@ -43,13 +47,12 @@ export class DatasetApiService {
return requestUrl; return requestUrl;
} }
protected requestApi<T>( protected requestApi<T>(url: string, params: HttpParams = new HttpParams(), options: HttpRequestOptions = {}
url: string, params: HttpParams = new HttpParams(), options: HttpRequestOptions = {}
): Observable<T> { ): Observable<T> {
return this.httpService.client(options).get<T>(url, return this.httpService.client(options).get<T>(url,
{ {
params, params,
headers: this.createBasicAuthHeader(options.basicAuthToken) headers: this.createBasicAuthHeader(options.basicAuthToken as string)
} }
); );
} }

View file

@ -36,7 +36,7 @@ export class MarkerService {
makeCapitalCircleMarkers(map: Map): void { makeCapitalCircleMarkers(map: Map): void {
this.http.get(this.capitalsUrl).subscribe((res: any) => { this.http.get(this.capitalsUrl).subscribe((res: any) => {
let maxPop = Math.max(...res.features.map(x => x.properties.population), 0); let maxPop = Math.max(...res.features.map((x: any) => x.properties.population), 0);
for (const c of res.features) { for (const c of res.features) {
const lon = c.geometry.coordinates[0]; const lon = c.geometry.coordinates[0];

View file

@ -0,0 +1,19 @@
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class MessageService {
constructor() { }
messages: string[] = [];
add(message: string) {
this.messages.push(message);
}
clear() {
this.messages = [];
}
}

View file

@ -1,72 +1,73 @@
import { Station } from '../../shared/models/station'; import { Station } from '../../shared/models/station';
export const STATIONS: Station[] = [ export const STATIONS: Station[] = [];
{ // export const STATIONS: Station[] = [
id: '11', // {
label: 'Dr Nice', // id: '11',
geometry: { // label: 'Dr Nice',
"type": "Point", // geometry: {
"coordinates": [125.6, 10.1] // "type": "Point",
} // "coordinates": [125.6, 10.1]
}, // }
{ // },
id: '12', label: 'Narco', geometry: { // {
"type": "Point", // id: '12', label: 'Narco', geometry: {
"coordinates": [125.6, 10.1] // "type": "Point",
} // "coordinates": [125.6, 10.1]
}, // }
{ // },
id: '13', label: 'Bombasto', geometry: { // {
"type": "Point", // id: '13', label: 'Bombasto', geometry: {
"coordinates": [125.6, 10.1] // "type": "Point",
} // "coordinates": [125.6, 10.1]
}, // }
{ // },
id: '14', label: 'Celeritas', geometry: { // {
"type": "Point", // id: '14', label: 'Celeritas', geometry: {
"coordinates": [125.6, 10.1] // "type": "Point",
} // "coordinates": [125.6, 10.1]
}, // }
{ // },
id: '15', label: 'Magneta', geometry: { // {
"type": "Point", // id: '15', label: 'Magneta', geometry: {
"coordinates": [125.6, 10.1] // "type": "Point",
} // "coordinates": [125.6, 10.1]
}, // }
{ // },
id: '16', label: 'RubberMan', geometry: { // {
"type": "Point", // id: '16', label: 'RubberMan', geometry: {
"coordinates": [125.6, 10.1] // "type": "Point",
}, // "coordinates": [125.6, 10.1]
}, // },
{ // },
id: '16', label: 'RubberMan', geometry: { // {
"type": "Point", // id: '16', label: 'RubberMan', geometry: {
"coordinates": [125.6, 10.1] // "type": "Point",
}, // "coordinates": [125.6, 10.1]
}, // },
{ // },
id: '17', label: 'Dynama', geometry: { // {
"type": "Point", // id: '17', label: 'Dynama', geometry: {
"coordinates": [125.6, 10.1] // "type": "Point",
}, // "coordinates": [125.6, 10.1]
}, // },
{ // },
id: '18', label: 'Dr IQ', geometry: { // {
"type": "Point", // id: '18', label: 'Dr IQ', geometry: {
"coordinates": [125.6, 10.1] // "type": "Point",
}, // "coordinates": [125.6, 10.1]
}, // },
{ // },
id: '19', label: 'Magma', geometry: { // {
"type": "Point", // id: '19', label: 'Magma', geometry: {
"coordinates": [125.6, 10.1] // "type": "Point",
}, // "coordinates": [125.6, 10.1]
}, // },
{ // },
id: '20', label: 'Tornado', geometry: { // {
"type": "Point", // id: '20', label: 'Tornado', geometry: {
"coordinates": [125.6, 10.1] // "type": "Point",
}, // "coordinates": [125.6, 10.1]
} // },
]; // }
// ];

View file

@ -1,18 +1,22 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { Observable, of } from 'rxjs'; import { Observable, of } from 'rxjs';
import { Station } from 'shared/models/station'; import { Station } from '../../shared/models/station';
import { MessageService } from './message.service';
import { STATIONS } from './mock-stations'; import { STATIONS } from './mock-stations';
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
}) })
export class StationService { export class StationService {
private messageService;
constructor() { } constructor(messageService: MessageService) {
this.messageService = messageService;
}
getStations(): Observable<Station[]> { getStations(): Observable<Station[]> {
const stations = of(STATIONS); const stations = of(STATIONS);
// this.messageService.add('HeroService: fetched heroes'); this.messageService.add('StationService: fetched stations');
return stations; return stations;
} }
@ -20,7 +24,7 @@ export class StationService {
// For now, assume that a hero with the specified `id` always exists. // For now, assume that a hero with the specified `id` always exists.
// Error handling will be added in the next step of the tutorial. // Error handling will be added in the next step of the tutorial.
const station = STATIONS.find(h => h.id === id)!; const station = STATIONS.find(h => h.id === id)!;
// this.messageService.add(`HeroService: fetched hero id=${id}`); this.messageService.add(`StationService: fetched station id=${id}`);
return of(station); return of(station);
} }
} }

BIN
src/assets/Tethys-icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

View file

@ -0,0 +1,21 @@
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { LocateButtonComponent } from './locate-button/locate-button.component';
// import { HelgolandMapModule, LocateService } from '@helgoland/map';
@NgModule({
imports: [
CommonModule,
],
declarations: [
LocateButtonComponent,
],
exports: [
LocateButtonComponent,
],
providers: [
]
})
export class ComponentsModule { }

View file

@ -0,0 +1,9 @@
<!-- <div class="btn-group-vertical btn-group-sm map-control">
<button type="button" class="btn btn-sm">
<i class="fa fa-map-marker-alt"></i>
</button>
</div> -->
<button (click)="test()">
</button>

View file

@ -0,0 +1,25 @@
import { Component, Input } from '@angular/core';
import { Required } from '@helgoland/core';
@Component({
selector: 'helgoland-locate-button',
templateUrl: './locate-button.component.html',
styleUrls: ['./locate-button.component.scss']
})
export class LocateButtonComponent {
/**
* Connect map id.
*/
@Input() @Required public mapId: string;
constructor(
) { }
test() {}
}

View file

@ -31,7 +31,7 @@
<app-component></app-component> <app-component></app-component>
<!-- <script src="dist/polyfills.js" defer></script> --> <!-- <script src="dist/polyfills.js" defer></script> -->
<script src="dist/main.js"></script> <!-- <script src="dist/main.js"></script> -->
</body> </body>
</html> </html>

View file

@ -1,10 +1,10 @@
export class Station { export interface Station {
public id: string; id: string;
public label: string; label: string;
public geometry: GeoJSON.GeometryObject; geometry: GeoJSON.GeometryObject;
public properties?: StationProperties; properties: StationProperties;
} }
export interface StationProperties { export interface StationProperties {
@ -17,18 +17,18 @@ export interface StationProperties {
// [key: string]: ParameterConstellation; // [key: string]: ParameterConstellation;
// } // }
class Timeseries { interface Timeseries {
public id: string; id: string;
public label: string; label: string;
public url: string; url: string;
public uom: string; uom: string;
public internalId: string; internalId: string;
public firstValue; // firstValue;
public lastValue; // lastValue;
public referenceValues; // referenceValues;
public station: Station; station: Station;
public parameters; // parameters;
public statusIntervals?; // statusIntervals?;
public hasData = false; // hasData = false;
public renderingHints; // public renderingHints;
} }

View file

@ -1,4 +0,0 @@
/* You can add global styles to this file, and also import other style files */
/* @import '../node_modules/leaflet/dist/leaflet.css'; */
@import '~leaflet/dist/leaflet.css';

150
src/styles.scss Normal file
View file

@ -0,0 +1,150 @@
/* You can add global styles to this file, and also import other style files */
/* @import '../node_modules/leaflet/dist/leaflet.css'; */
@import '~leaflet/dist/leaflet.css';
// Import a Google Font
@import url('https://fonts.googleapis.com/css?family=Nunito:400,700');
// @import "~bulma/css/bulma.css";
// 1. Import the initial variables
@import "~bulma/sass/utilities/_all.sass";
// 2. Set your own initial (brand) variables
// Update the blue shade, used for links
$blue: #06bcef;
// Add pink and its invert
$pink: #FA7C91;
$pink-invert: #fff;
$purple: #8A4D76;
$brown: #757763;
$beige-light: #D0D1CD;
$beige-lighter: #EFF0EB;
$mouse-grey: #6c6e6b;
$select-green: #03a678;
// Update Bulma's global variables
// Update the sans-serif font family
$family-sans-serif: "Nunito", sans-serif;
// 3. Set the derived variables
$grey-dark: $brown;
$is-dark: $mouse-grey;
// $grey-light: $beige-light;
// $primary: $purple;
// $link: $mouse-grey;
$widescreen-enabled: false;
$fullhd-enabled: false;
$tabs-link-active-border-bottom-color: $select-green;
$tabs-link-active-color: $select-green;
// Update some of Bulma's component variables
// $body-background-color: $beige-lighter;
$control-border-width: 2px;
$input-border-color: transparent;
// $input-shadow: none;
.main.columns:last-child {
margin-bottom: 0;
}
.navbar-brand img {
height: 51px;
}
.main.columns:last-child {
margin-bottom: 0;
}
.navbar-brand img {
height: 51px;
}
html,
body {
height: 100%;
width: 100%;
line-height: 1.6;
font-weight: 400;
font-family: "Raleway", "HelveticaNeue", "Helvetica Neue", Helvetica, Arial, sans-serif;
color: #222;
}
ol,
ul {
list-style: none;
padding: 0;
}
.main {
padding-top: 51px;
// display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: space-around;
/* height: 100%; */
position: absolute;
overflow: hidden;
left: 0;
right: 0;
top: 0;
bottom: 0;
overflow-y: scroll;
}
.canvas-area {
/* flex: 2;
display: flex;
align-items: center;
justify-content: center; */
height: 100%;
}
.input-area {
// flex: 1;
// display: flex;
// flex-direction: column;
align-items: center;
justify-content: center;
}
#div-map {
position: relative;
height: 100%;
width: 100%;
}
.mapDesktop {
overflow: hidden;
position: absolute;
bottom: 30px;
top: 30px;
left: 30px;
right: 30px;
}
.locate-control button{
position: absolute;
right: 5px;
top: 5px;
z-index: 1000;
}
// 4. Import the rest of bulma, only what you need from Bulma
@import "~bulma/sass/grid/_all.sass";
@import "~bulma/sass/base/_all.sass";
@import "~bulma/sass/elements/box.sass";
@import "~bulma/sass/elements/button.sass";
@import "~bulma/sass/elements/container.sass";
@import "~bulma/sass/elements/title.sass";
@import "~bulma/sass/elements/icon.sass";
@import "~bulma/sass/form/_all.sass";
@import "~bulma/sass/components/navbar.sass";
// @import "~bulma/sass/components/tabs.sass";
@import "~bulma/sass/components/media.sass";
@import "~bulma/sass/components/modal.sass";
@import "~bulma/sass/layout/hero.sass";
@import "~bulma/sass/layout/section.sass";

15
tsconfig.app.json Normal file
View file

@ -0,0 +1,15 @@
/* To learn more about this file see: https://angular.io/config/tsconfig. */
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "./out-tsc/app",
"types": []
},
"files": [
"src/main.ts",
"src/polyfills.ts"
],
"include": [
"src/**/*.d.ts"
]
}

33
tsconfig.json Normal file
View file

@ -0,0 +1,33 @@
/* To learn more about this file see: https://angular.io/config/tsconfig. */
{
"compileOnSave": false,
"compilerOptions": {
"baseUrl": "./",
"outDir": "./dist/out-tsc",
"strictPropertyInitialization": false,
"allowSyntheticDefaultImports": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"sourceMap": true,
"declaration": false,
"downlevelIteration": true,
"experimentalDecorators": true,
"moduleResolution": "node",
"importHelpers": true,
"target": "es2017",
"module": "es2020",
"lib": [
"es2018",
"dom"
]
},
"angularCompilerOptions": {
"enableI18nLegacyMessageIdFormat": false,
"strictInjectionParameters": true,
"strictInputAccessModifiers": true,
"strictTemplates": true,
"strictNullChecks": false,
}
}

View file

@ -63,7 +63,7 @@ module.exports = {
{ {
test: /\.(png|svg|jpg|gif)$/, test: /\.(png|svg|jpg|gif)$/,
use: [{ use: [{
loader: 'file-loader', loader: 'url-loader',
options: { options: {
name: '[name].[ext]', name: '[name].[ext]',
outputPath: './assets/' outputPath: './assets/'
@ -151,6 +151,13 @@ module.exports = {
options: { options: {
sourceMap: true sourceMap: true
} }
},
// Compiles Sass to CSS
{
loader: "sass-loader",
options: {
sourceMap: true
}
} }
] ]