diff --git a/angular.json b/angular.json index 64ccb1d3e8afb31161751d7557add12e6027903c..b81fd06fd589b07d081ed824bafbcae59ef452e6 100644 --- a/angular.json +++ b/angular.json @@ -34,6 +34,7 @@ "src/assets" ], "styles": [ + "./node_modules/@angular/material/prebuilt-themes/indigo-pink.css", "src/styles.scss" ], "scripts": [] @@ -102,6 +103,7 @@ "src/assets" ], "styles": [ + "./node_modules/@angular/material/prebuilt-themes/indigo-pink.css", "src/styles.scss" ], "scripts": [] diff --git a/package-lock.json b/package-lock.json index a18d2d33d5a37a29543a2606fdc0ddccb3ce489a..0b70bdae1d79cb0e889297624aa8f767626e52e7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,13 +9,17 @@ "version": "0.0.0", "dependencies": { "@angular/animations": "~12.2.0", + "@angular/cdk": "^12.2.9", "@angular/common": "~12.2.0", "@angular/compiler": "~12.2.0", "@angular/core": "~12.2.0", "@angular/forms": "~12.2.0", + "@angular/material": "^12.2.9", "@angular/platform-browser": "~12.2.0", "@angular/platform-browser-dynamic": "~12.2.0", "@angular/router": "~12.2.0", + "@asymmetrik/ngx-leaflet": "^8.1.0", + "leaflet": "^1.7.1", "rxjs": "~6.6.0", "tslib": "^2.3.0", "zone.js": "~0.11.4" @@ -25,6 +29,7 @@ "@angular/cli": "~12.2.9", "@angular/compiler-cli": "~12.2.0", "@types/jasmine": "~3.8.0", + "@types/leaflet": "^1.7.5", "@types/node": "^12.11.1", "jasmine-core": "~3.8.0", "karma": "~6.3.0", @@ -289,6 +294,28 @@ "@angular/core": "12.2.9" } }, + "node_modules/@angular/cdk": { + "version": "12.2.9", + "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-12.2.9.tgz", + "integrity": "sha512-9Wgj69iGAZ4teQqW/zPbVg2RGna+m9i3v0zkWGx/+Uo95rikJCUZBQM4bfeOe+bSJrS77jV5EisBWG7ayNUSzQ==", + "dependencies": { + "tslib": "^2.2.0" + }, + "optionalDependencies": { + "parse5": "^5.0.0" + }, + "peerDependencies": { + "@angular/common": "^12.0.0 || ^13.0.0-0", + "@angular/core": "^12.0.0 || ^13.0.0-0", + "rxjs": "^6.5.3 || ^7.0.0" + } + }, + "node_modules/@angular/cdk/node_modules/parse5": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz", + "integrity": "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==", + "optional": true + }, "node_modules/@angular/cli": { "version": "12.2.9", "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-12.2.9.tgz", @@ -427,6 +454,22 @@ "rxjs": "^6.5.3 || ^7.0.0" } }, + "node_modules/@angular/material": { + "version": "12.2.9", + "resolved": "https://registry.npmjs.org/@angular/material/-/material-12.2.9.tgz", + "integrity": "sha512-+eM67RF038S56m3wsj37h0PyyRD18cQ8V2zmKG1UezH0nnosbmCAwzH9BfcNiIB+/V+k5QMJ/JVu5MjDQqX37w==", + "dependencies": { + "tslib": "^2.2.0" + }, + "peerDependencies": { + "@angular/animations": "^12.0.0 || ^13.0.0-0", + "@angular/cdk": "12.2.9", + "@angular/common": "^12.0.0 || ^13.0.0-0", + "@angular/core": "^12.0.0 || ^13.0.0-0", + "@angular/forms": "^12.0.0 || ^13.0.0-0", + "rxjs": "^6.5.3 || ^7.0.0" + } + }, "node_modules/@angular/platform-browser": { "version": "12.2.9", "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-12.2.9.tgz", @@ -488,6 +531,17 @@ "integrity": "sha512-H71nDOOL8Y7kWRLqf6Sums+01Q5msqBW2KhDUTemh1tvY04eSkSXrK0uj/4mmY0Xr16/3zyZmsrxN7CKuRbNRg==", "dev": true }, + "node_modules/@asymmetrik/ngx-leaflet": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@asymmetrik/ngx-leaflet/-/ngx-leaflet-8.1.0.tgz", + "integrity": "sha512-lq7LduBP/vXcaSEmKnx7mzCR8WsoYqh9pB6BNnq53yeCwsqRbG3GdKye1/i8VvoRzjDsmQBPQsIFZ9uclXrtgg==", + "peerDependencies": { + "@angular/common": ">=10", + "@angular/core": ">=10", + "leaflet": "1", + "tslib": "2" + } + }, "node_modules/@babel/code-frame": { "version": "7.15.8", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.15.8.tgz", @@ -2486,6 +2540,12 @@ "integrity": "sha512-C6N5s2ZFtuZRj54k2/zyRhNDjJwwcViAM3Nbm8zjBpbqAdZ00mr0CFxvSKeO8Y/e03WVFLpQMdHYVfUd6SB+Hw==", "dev": true }, + "node_modules/@types/geojson": { + "version": "7946.0.8", + "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.8.tgz", + "integrity": "sha512-1rkryxURpr6aWP7R786/UQOkJ3PcpQiWkAXBmdWc7ryFWqN6a4xfK7BtjXvFBKO9LjQ+MWQSWxYeZX1OApnArA==", + "dev": true + }, "node_modules/@types/glob": { "version": "7.1.4", "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.4.tgz", @@ -2508,6 +2568,15 @@ "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==", "dev": true }, + "node_modules/@types/leaflet": { + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/@types/leaflet/-/leaflet-1.7.5.tgz", + "integrity": "sha512-+Myo00Yb5OuvUyrH+vUwn9DRgOaBJsF/etIMdMcNhWGBMo58Mo1cxLInvCd0ZpvItju/AeDYFB/Od2pLiHB3VA==", + "dev": true, + "dependencies": { + "@types/geojson": "*" + } + }, "node_modules/@types/minimatch": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz", @@ -8326,6 +8395,11 @@ "node": ">= 8" } }, + "node_modules/leaflet": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.7.1.tgz", + "integrity": "sha512-/xwPEBidtg69Q3HlqPdU3DnrXQOvQU/CCHA1tcDQVzOwm91YMYaILjNp7L4Eaw5Z4sOYdbBz6koWyibppd8Zqw==" + }, "node_modules/less": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/less/-/less-4.1.1.tgz", @@ -16055,6 +16129,23 @@ "tslib": "^2.2.0" } }, + "@angular/cdk": { + "version": "12.2.9", + "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-12.2.9.tgz", + "integrity": "sha512-9Wgj69iGAZ4teQqW/zPbVg2RGna+m9i3v0zkWGx/+Uo95rikJCUZBQM4bfeOe+bSJrS77jV5EisBWG7ayNUSzQ==", + "requires": { + "parse5": "^5.0.0", + "tslib": "^2.2.0" + }, + "dependencies": { + "parse5": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz", + "integrity": "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==", + "optional": true + } + } + }, "@angular/cli": { "version": "12.2.9", "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-12.2.9.tgz", @@ -16144,6 +16235,14 @@ "tslib": "^2.2.0" } }, + "@angular/material": { + "version": "12.2.9", + "resolved": "https://registry.npmjs.org/@angular/material/-/material-12.2.9.tgz", + "integrity": "sha512-+eM67RF038S56m3wsj37h0PyyRD18cQ8V2zmKG1UezH0nnosbmCAwzH9BfcNiIB+/V+k5QMJ/JVu5MjDQqX37w==", + "requires": { + "tslib": "^2.2.0" + } + }, "@angular/platform-browser": { "version": "12.2.9", "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-12.2.9.tgz", @@ -16174,6 +16273,12 @@ "integrity": "sha512-H71nDOOL8Y7kWRLqf6Sums+01Q5msqBW2KhDUTemh1tvY04eSkSXrK0uj/4mmY0Xr16/3zyZmsrxN7CKuRbNRg==", "dev": true }, + "@asymmetrik/ngx-leaflet": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@asymmetrik/ngx-leaflet/-/ngx-leaflet-8.1.0.tgz", + "integrity": "sha512-lq7LduBP/vXcaSEmKnx7mzCR8WsoYqh9pB6BNnq53yeCwsqRbG3GdKye1/i8VvoRzjDsmQBPQsIFZ9uclXrtgg==", + "requires": {} + }, "@babel/code-frame": { "version": "7.15.8", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.15.8.tgz", @@ -17625,6 +17730,12 @@ "integrity": "sha512-C6N5s2ZFtuZRj54k2/zyRhNDjJwwcViAM3Nbm8zjBpbqAdZ00mr0CFxvSKeO8Y/e03WVFLpQMdHYVfUd6SB+Hw==", "dev": true }, + "@types/geojson": { + "version": "7946.0.8", + "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.8.tgz", + "integrity": "sha512-1rkryxURpr6aWP7R786/UQOkJ3PcpQiWkAXBmdWc7ryFWqN6a4xfK7BtjXvFBKO9LjQ+MWQSWxYeZX1OApnArA==", + "dev": true + }, "@types/glob": { "version": "7.1.4", "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.4.tgz", @@ -17647,6 +17758,15 @@ "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==", "dev": true }, + "@types/leaflet": { + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/@types/leaflet/-/leaflet-1.7.5.tgz", + "integrity": "sha512-+Myo00Yb5OuvUyrH+vUwn9DRgOaBJsF/etIMdMcNhWGBMo58Mo1cxLInvCd0ZpvItju/AeDYFB/Od2pLiHB3VA==", + "dev": true, + "requires": { + "@types/geojson": "*" + } + }, "@types/minimatch": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz", @@ -22188,6 +22308,11 @@ "integrity": "sha512-ZRbnvdg/NxqzC7L9Uyqzf4psi1OM4Cuc+sJAkQPjO6XkQIJTNbfK2Rsmbw8fx1p2mkZdp2FZYo2+LwXYY/uwIA==", "dev": true }, + "leaflet": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.7.1.tgz", + "integrity": "sha512-/xwPEBidtg69Q3HlqPdU3DnrXQOvQU/CCHA1tcDQVzOwm91YMYaILjNp7L4Eaw5Z4sOYdbBz6koWyibppd8Zqw==" + }, "less": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/less/-/less-4.1.1.tgz", diff --git a/package.json b/package.json index d5b79a2d836277a1553a35a943c03d775d8768bc..349ac8144b9cc3baf8634eb3c885627c4a3c182b 100644 --- a/package.json +++ b/package.json @@ -11,13 +11,17 @@ "private": true, "dependencies": { "@angular/animations": "~12.2.0", + "@angular/cdk": "^12.2.9", "@angular/common": "~12.2.0", "@angular/compiler": "~12.2.0", "@angular/core": "~12.2.0", "@angular/forms": "~12.2.0", + "@angular/material": "^12.2.9", "@angular/platform-browser": "~12.2.0", "@angular/platform-browser-dynamic": "~12.2.0", "@angular/router": "~12.2.0", + "@asymmetrik/ngx-leaflet": "^8.1.0", + "leaflet": "^1.7.1", "rxjs": "~6.6.0", "tslib": "^2.3.0", "zone.js": "~0.11.4" @@ -27,6 +31,7 @@ "@angular/cli": "~12.2.9", "@angular/compiler-cli": "~12.2.0", "@types/jasmine": "~3.8.0", + "@types/leaflet": "^1.7.5", "@types/node": "^12.11.1", "jasmine-core": "~3.8.0", "karma": "~6.3.0", diff --git a/src/app/app.component.html b/src/app/app.component.html index 0680b43f9c6ae05df91c576141f20ed411d07c7d..e355942728719d67ca168d95bb59d85e5862511f 100644 --- a/src/app/app.component.html +++ b/src/app/app.component.html @@ -1 +1,8 @@ +<div class="wrapper"> + <h1>Consumer</h1> +</div> + + +<app-map class="wrapper"></app-map> + <router-outlet></router-outlet> diff --git a/src/app/app.component.scss b/src/app/app.component.scss index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..11343d6aaab51e1f55c84f3561a8ef0c1eb6fb38 100644 --- a/src/app/app.component.scss +++ b/src/app/app.component.scss @@ -0,0 +1,5 @@ +@import './src/variables.scss'; + +.wrapper { + padding: 0 calc((100% - #{$break-large})/2); +} \ No newline at end of file diff --git a/src/app/app.module.ts b/src/app/app.module.ts index b1c6c96a9de8f091f39b3b8feb7e29cfcfb1ed81..b3911649ab532de15c28c800667b3ea031e29c57 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -1,18 +1,43 @@ import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; -import { AppRoutingModule } from './app-routing.module'; +// --- Map +import { LeafletModule } from '@asymmetrik/ngx-leaflet'; + +// --- WS +// import * as SockJS from 'sockjs-client'; + +// --- Modules +import { SharedModule } from './shared/shared.module'; +import { CoreModule } from './core/core.module'; + +// --- Services +import { ApiService } from "./core/api.service"; +// import { StompService, StompConfig } from '@stomp/ng2-stompjs'; +import { environment } from './../environments/environment'; + +// --- Components import { AppComponent } from './app.component'; +import { MapComponent } from './components/map/map.component'; +import { AppRoutingModule } from './app-routing.module'; +import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; + + @NgModule({ declarations: [ - AppComponent + AppComponent, + MapComponent ], imports: [ BrowserModule, - AppRoutingModule + AppRoutingModule, + SharedModule, + CoreModule, + LeafletModule, + BrowserAnimationsModule ], - providers: [], + providers: [ApiService], bootstrap: [AppComponent] }) export class AppModule { } diff --git a/src/app/components/map/map.component.html b/src/app/components/map/map.component.html new file mode 100644 index 0000000000000000000000000000000000000000..2da3bd7a5c4412170d7849fc993266781fe285f7 --- /dev/null +++ b/src/app/components/map/map.component.html @@ -0,0 +1,5 @@ +<div style="height: 80vh;" + leaflet + [leafletOptions]="options" + (leafletMapReady)="onMapReady($event)"> +</div> \ No newline at end of file diff --git a/src/app/components/map/map.component.scss b/src/app/components/map/map.component.scss new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/app/components/map/map.component.spec.ts b/src/app/components/map/map.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..449dba05078e4b01d37c7b5c39c65eee88582e04 --- /dev/null +++ b/src/app/components/map/map.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { MapComponent } from './map.component'; + +describe('MapComponent', () => { + let component: MapComponent; + let fixture: ComponentFixture<MapComponent>; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ MapComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(MapComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/components/map/map.component.ts b/src/app/components/map/map.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..6a9ca6e87e9c0f93ee6065c3faba5c3f9ecfbab8 --- /dev/null +++ b/src/app/components/map/map.component.ts @@ -0,0 +1,122 @@ +import { NONE_TYPE } from '@angular/compiler'; +import { Component, OnInit } from '@angular/core'; +import * as L from "leaflet"; + +class Location { + id: string; + type = 'position'; + lat: Float32Array; + lng: Float32Array; + + constructor(obj: any, id: any) { + this.id = id + this.lat = obj.lat + this.lng = obj.lng + } +} + +class Measurements { + id: string + type = 'measurements' + data: number[]; + + constructor(dist: any, id: any) { + this.id = id + this.data = dist + } +} + +@Component({ + selector: 'app-map', + templateUrl: './map.component.html', + styleUrls: ['./map.component.scss'] +}) +export class MapComponent implements OnInit { + + _stompService: any; + map: L.Map; + + constructor() { + this.map = L.map('map', { + center: [51.505, -0.09], + zoom: 13 + }); + } + + ngOnInit(): void { + // wait on new Location + this._stompService.watch('/topic/locations').subscribe((message: any) => { + let payload = JSON.parse(message.body); + this.addNewMarker(payload) + }); + + // wait on new measurements + this._stompService.watch('/topic/positions').subscribe((message: any) => { + let payload = JSON.parse(message.body); + console.log('positions', payload) + this.addPosition(payload) + }); + } + + addPosition(point: any) { + let marker = L.marker(point.position, { + icon: L.icon({ + iconSize: [25, 41], + iconAnchor: [13, 41], + iconUrl: 'assets/marker-icon-red.png', + iconRetinaUrl: 'assets/marker-icon-2x-red.png', + shadowUrl: 'assets/marker-shadow.png' + }) + }).bindPopup(point.id).openPopup(); + marker.addTo(this.map); + } + + // --- Controllers + + // @https://asymmetrik.com/ngx-leaflet-tutorial-angular-cli/ + // --- Layers: Define base layers so we can reference them multiple times + streetMaps = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { + detectRetina: true, + attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors' + }); + wMaps = L.tileLayer('http://maps.wikimedia.org/osm-intl/{z}/{x}/{y}.png', { + detectRetina: true, + attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors' + }); + + satelliteMaps = L.tileLayer('https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}', { + id: 'mapbox.streets', + attribution: 'Tiles © Esri — Source: Esri, i-cubed, USDA, USGS, AEX, GeoEye, Getmapping, Aerogrid, IGN, IGP, UPR-EGP, and the GIS User Community' + }); + + options = { + layers: [this.streetMaps], + zoom: 15, + center: L.latLng([51.037845, 13.762852]) + }; + + onMapReady(map: L.Map) { + this.map = map + + // Layers control object with our two base layers and the three overlay layers + let baseLayers = { + 'Street Maps': this.streetMaps, + 'Wikimedia Maps': this.wMaps, + 'Satellite': this.satelliteMaps + } + L.control.layers(baseLayers).addTo(this.map); + } + + addNewMarker(obj: any) { + let marker = L.marker([obj.lat, obj.lng], { + icon: L.icon({ + iconSize: [25, 41], + iconAnchor: [13, 41], + iconUrl: 'assets/marker-icon-grey.png', + iconRetinaUrl: 'assets/marker-icon-2x-grey.png', + shadowUrl: 'assets/marker-shadow.png' + }) + }).bindPopup(obj.id).openPopup(); + marker.addTo(this.map); + } +} diff --git a/src/app/core/api.service.spec.ts b/src/app/core/api.service.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..77286123bbf2073af05b68dcf53b8e2ff54b8925 --- /dev/null +++ b/src/app/core/api.service.spec.ts @@ -0,0 +1,23 @@ +import {HttpClientTestingModule, HttpTestingController} from '@angular/common/http/testing'; +import {TestBed} from '@angular/core/testing'; + +import {ApiService} from './api.service'; + +describe('ApiService', () => { + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [HttpClientTestingModule], + providers: [ApiService] + }); + }); + + afterEach(() => { + const httpMock = TestBed.get(HttpTestingController); + httpMock.verify(); + }); + + it('should be created', () => { + const service: ApiService = TestBed.get(ApiService); + expect(service).toBeTruthy(); + }); +}); diff --git a/src/app/core/api.service.ts b/src/app/core/api.service.ts new file mode 100644 index 0000000000000000000000000000000000000000..a81e3f8eaf1bc9525686bff18c55988c6438f7b0 --- /dev/null +++ b/src/app/core/api.service.ts @@ -0,0 +1,41 @@ +import {HttpClient} from '@angular/common/http'; +import {Injectable} from '@angular/core'; +import {Observable, throwError} from 'rxjs'; +import {catchError} from 'rxjs/operators'; + +export interface ApiError { + code: string; + message: string; +} + +@Injectable({ + providedIn: 'root' +}) +export class ApiService { + + private locationsUrl: string; + + constructor(private httpClient: HttpClient) { + this.locationsUrl = 'http://localhost:8080/locations'; + } + + getXml(url: string): Observable<string> { + return this.httpClient + .get(url, {responseType: 'text'}) + .pipe(catchError(this._handleError)); + } + + + public findAll(): Observable<string[]> { + return this.httpClient.get<string[]>(this.locationsUrl); + } + + public save(loc: string) { + return this.httpClient.post<string>(this.locationsUrl, loc); + } + + private _handleError(error: ApiError) { + return throwError(error.message || 'Could not complete your request; please try again later.'); + } + +} diff --git a/src/app/core/core.module.ts b/src/app/core/core.module.ts new file mode 100644 index 0000000000000000000000000000000000000000..339a9110e79cdfebc90753a22a569599404ada29 --- /dev/null +++ b/src/app/core/core.module.ts @@ -0,0 +1,12 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; + + + +@NgModule({ + declarations: [], + imports: [ + CommonModule + ] +}) +export class CoreModule { } diff --git a/src/app/shared/shared.module.ts b/src/app/shared/shared.module.ts new file mode 100644 index 0000000000000000000000000000000000000000..57e3890402079692045dcd74b346c0386009c2d8 --- /dev/null +++ b/src/app/shared/shared.module.ts @@ -0,0 +1,73 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; + +// --- @angular/flex-layout : Layout for Angular applications; using Flexbox and a Responsive API +// import { FlexLayoutModule } from '@angular/flex-layout'; + +// --- Forms +import { FormsModule, ReactiveFormsModule } from '@angular/forms'; + +// --- material.angular.io : Material Design components for Angular +import { MatButtonModule } from '@angular/material/button'; +import { MatIconModule } from '@angular/material/icon'; +import { MatInputModule } from '@angular/material/input'; +import { MatMenuModule } from '@angular/material/menu'; +import { MatTabsModule } from '@angular/material/tabs'; +import { MatToolbarModule } from '@angular/material/toolbar'; +import { MatFormFieldModule } from '@angular/material/form-field'; +import { MatDialogModule } from '@angular/material/dialog'; +import { MatSnackBarModule } from '@angular/material/snack-bar'; +import { MatSelectModule } from '@angular/material/select'; +import { MatCardModule } from '@angular/material/card'; +import { MatExpansionModule } from '@angular/material/expansion'; +import { MatSidenavModule } from '@angular/material/sidenav'; +import { MatTooltipModule } from '@angular/material/tooltip'; +// Animation +import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; + + + +@NgModule({ + declarations: [], + imports: [ + FormsModule, + ReactiveFormsModule, + CommonModule, + MatButtonModule, + MatIconModule, + MatInputModule, + MatMenuModule, + MatTabsModule, + MatToolbarModule, + BrowserAnimationsModule, + MatFormFieldModule, + MatDialogModule, + MatSnackBarModule, + MatSelectModule, + MatCardModule, + MatExpansionModule, + MatSidenavModule, + MatTooltipModule + ], + exports: [ + FormsModule, + ReactiveFormsModule, + CommonModule, + MatButtonModule, + MatIconModule, + MatInputModule, + MatMenuModule, + MatTabsModule, + MatToolbarModule, + BrowserAnimationsModule, + MatFormFieldModule, + MatDialogModule, + MatSnackBarModule, + MatSelectModule, + MatCardModule, + MatExpansionModule, + MatSidenavModule, + MatTooltipModule + ] +}) +export class SharedModule { } diff --git a/src/index.html b/src/index.html index 586887e69a92979676e7e2b1f03828721f35540a..7de67b6cc5d22f2152bd478b93f3fc20bd8d0f0c 100644 --- a/src/index.html +++ b/src/index.html @@ -6,6 +6,9 @@ <base href="/"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="icon" type="image/x-icon" href="favicon.ico"> + <link rel="preconnect" href="https://fonts.gstatic.com"> + <link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500&display=swap" rel="stylesheet"> + <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet"> </head> <body> <app-root></app-root> diff --git a/src/styles.scss b/src/styles.scss index eb7dc01531e395daadfaf0c2a8378ded0066a412..c1378aee2ad3d3d83377ec5194a1695a857ee0d9 100644 --- a/src/styles.scss +++ b/src/styles.scss @@ -15,3 +15,6 @@ app-root { flex-wrap: nowrap; min-height: 100vh; } + +html, body { height: 100%; } +body { margin: 0; font-family: Roboto, "Helvetica Neue", sans-serif; }