From efa08a3819b324bced437a288f888233b4431882 Mon Sep 17 00:00:00 2001 From: danmgs Date: Thu, 10 Dec 2020 13:29:46 +0100 Subject: [PATCH] Refactoring --- .env | 2 + .gitignore | 3 + .vscode/settings.json | 11 +- Dockerrun.aws.json | 8 + docker-compose-release.yml | 2 + docker-compose.yml | 12 ++ launch.bat | 1 + package-lock.json | 3 + public/default.conf | 9 + public/src/app/Shared/GeoData.ts | 16 +- public/src/app/Shared/ServerHealthData.ts | 7 + public/src/app/app.module.ts | 80 ++++---- public/src/app/services/geo.service.ts | 8 +- public/src/app/services/news.service.ts | 4 +- public/src/app/services/quote.service.ts | 4 +- .../src/app/services/serverhealth.service.ts | 27 +++ public/src/app/services/weather.service.ts | 27 ++- .../src/app/views/header/header.component.css | 5 + .../app/views/header/header.component.html | 7 +- .../src/app/views/header/header.component.ts | 18 +- public/src/app/views/header/header.module.ts | 19 ++ .../weather-list/weather-list.component.html | 168 +++++++++------- .../weather-list/weather-list.component.ts | 11 + .../src/app/views/weather/weather.module.ts | 54 ++--- .../environments/environment.development.ts | 3 +- public/src/environments/environment.prod.ts | 3 +- .../src/environments/environment.staging.ts | 3 +- public/src/environments/environment.ts | 3 +- server/.env | 13 +- server/README.md | 17 +- server/src/app.js | 10 +- server/src/controllers/news_controller.js | 2 +- .../controllers/server_health_controller.js | 2 - server/src/controllers/weather_controller.js | 188 +++++++++--------- sonar-project.properties | 18 ++ 35 files changed, 480 insertions(+), 288 deletions(-) create mode 100644 package-lock.json create mode 100644 public/src/app/Shared/ServerHealthData.ts create mode 100644 public/src/app/services/serverhealth.service.ts create mode 100644 public/src/app/views/header/header.module.ts create mode 100644 sonar-project.properties diff --git a/.env b/.env index 9924893..b035a38 100644 --- a/.env +++ b/.env @@ -4,6 +4,8 @@ NODE_ENV=production ENV_SERVER_API_MONGODB_URI=mongodb://mongo-service:27017 ENV_SERVER_API_ALLOW_HOSTS=* ENV_SERVER_API_PORT=30001 +ENV_API_KEY_DARKSKY= +ENV_API_KEY_NEWS= ENV_WEBAPP_NODE_ENV=prod ENV_WEBAPP_PORT=80 diff --git a/.gitignore b/.gitignore index a35ef50..23bc95d 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ # dependencies /node_modules + # IDEs and editors /.idea .project @@ -46,3 +47,5 @@ Thumbs.db # Output log log server/package-lock.json + +/.scannerwork diff --git a/.vscode/settings.json b/.vscode/settings.json index 106f856..c530de3 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,3 +1,8 @@ -{ - "files.autoSave": "onFocusChange" -} \ No newline at end of file +{ + "files.autoSave": "onFocusChange", + "sonarlint.connectedMode.project": { + "connectionId": "mysonarqube", + "projectKey": "My-weather-app" + }, + "git.ignoreLimitWarning": true +} diff --git a/Dockerrun.aws.json b/Dockerrun.aws.json index b40622d..92b5ebb 100644 --- a/Dockerrun.aws.json +++ b/Dockerrun.aws.json @@ -42,6 +42,14 @@ { "name": "ENV_SERVER_API_PORT", "value": "30001" + }, + { + "name": "ENV_API_KEY_DARKSKY", + "value": "" + }, + { + "name": "ENV_API_KEY_NEWS", + "value": "" } ], "essential": true, diff --git a/docker-compose-release.yml b/docker-compose-release.yml index cfef55e..6cdd684 100644 --- a/docker-compose-release.yml +++ b/docker-compose-release.yml @@ -16,6 +16,8 @@ services: ENV_SERVER_API_MONGODB_URI: mongodb://mongo-service:27017 ENV_SERVER_API_ALLOW_HOSTS: "*" ENV_SERVER_API_PORT: 30001 + ENV_API_KEY_DARKSKY: + ENV_API_KEY_NEWS: ports: - "30001:30001" depends_on: diff --git a/docker-compose.yml b/docker-compose.yml index bc35c87..b9f7b37 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -8,6 +8,16 @@ services: - mongodata:/data/db restart: always + mongo-express: + image: mongo-express + restart: always + ports: + - 8081:8081 + environment: + # ME_CONFIG_MONGODB_ADMINUSERNAME: root + # ME_CONFIG_MONGODB_ADMINPASSWORD: example + ME_CONFIG_MONGODB_SERVER: mongo-service + app-backend: build: context: ./server @@ -19,6 +29,8 @@ services: ENV_SERVER_API_MONGODB_URI: ${ENV_SERVER_API_MONGODB_URI} ENV_SERVER_API_ALLOW_HOSTS: ${ENV_SERVER_API_ALLOW_HOSTS} ENV_SERVER_API_PORT: ${ENV_SERVER_API_PORT} + ENV_API_KEY_DARKSKY: ${ENV_API_KEY_DARKSKY} + ENV_API_KEY_NEWS: ${ENV_API_KEY_NEWS} ports: - ${ENV_SERVER_API_PORT}:${ENV_SERVER_API_PORT} depends_on: diff --git a/launch.bat b/launch.bat index 3e965c2..32437c7 100644 --- a/launch.bat +++ b/launch.bat @@ -35,6 +35,7 @@ IF "%1"=="up" ( timeout /t 10 /nobreak > NUL START "" http://localhost START "" http://localhost:30001/api/serverhealth + START "" http://localhost:8081 GOTO End ) diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..48e341a --- /dev/null +++ b/package-lock.json @@ -0,0 +1,3 @@ +{ + "lockfileVersion": 1 +} diff --git a/public/default.conf b/public/default.conf index b7f2f6c..59869eb 100644 --- a/public/default.conf +++ b/public/default.conf @@ -6,4 +6,13 @@ server { index index.html index.htm; try_files $uri $uri/ /index.html =404; } + + location /api { + proxy_pass http://app-backend:30001; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $http_connection; + proxy_set_header Host $host; + proxy_cache_bypass $http_upgrade; + } } diff --git a/public/src/app/Shared/GeoData.ts b/public/src/app/Shared/GeoData.ts index d37cbc9..0610359 100644 --- a/public/src/app/Shared/GeoData.ts +++ b/public/src/app/Shared/GeoData.ts @@ -1,8 +1,8 @@ -export class GeoData { - - constructor( - public lat: number, - public lng: number, - public formatted_address: String - ) { } -} +export class GeoData { + + constructor( + public lat: Number, + public lng: Number, + public formatted_address: String + ) { } +} diff --git a/public/src/app/Shared/ServerHealthData.ts b/public/src/app/Shared/ServerHealthData.ts new file mode 100644 index 0000000..cda6571 --- /dev/null +++ b/public/src/app/Shared/ServerHealthData.ts @@ -0,0 +1,7 @@ +export class ServerHealthData { + + constructor( + public status: String, + public text: String + ) { } +} diff --git a/public/src/app/app.module.ts b/public/src/app/app.module.ts index a2d697d..88262b7 100644 --- a/public/src/app/app.module.ts +++ b/public/src/app/app.module.ts @@ -1,40 +1,40 @@ -import { BrowserModule } from '@angular/platform-browser'; -import { NgModule } from '@angular/core'; -import { HttpModule } from '@angular/http'; -import { FormsModule } from '@angular/forms'; -import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; - -/** Modules by feature **/ -import { WeatherModule } from './views/weather/weather.module'; -import { NewsModule } from './views/news/news.module'; -import { QuoteModule } from './views/quote-list/quote.module'; -import { PrimeNgModule } from './primeng.module'; -import { CustomFiltersModule } from './customfilters.module'; - -import { AppComponent } from './app.component'; -import { HeaderComponent } from './views/header/header.component'; -import { FooterComponent } from './views/footer/footer.component'; - -import { AppRoutingModule } from './app-routing.module'; - -@NgModule({ - declarations: [ - AppComponent, - HeaderComponent, - FooterComponent - ], - imports: [ - BrowserModule, - AppRoutingModule, - HttpModule, - FormsModule, - BrowserAnimationsModule, - CustomFiltersModule, - PrimeNgModule, - WeatherModule, - NewsModule, - QuoteModule - ], - bootstrap: [AppComponent] -}) -export class AppModule { } +import { BrowserModule } from '@angular/platform-browser'; +import { NgModule } from '@angular/core'; +import { HttpModule } from '@angular/http'; +import { FormsModule } from '@angular/forms'; +import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; + +/** Modules by feature **/ +import { HeaderModule } from './views/header/header.module'; +import { WeatherModule } from './views/weather/weather.module'; +import { NewsModule } from './views/news/news.module'; +import { QuoteModule } from './views/quote-list/quote.module'; +import { PrimeNgModule } from './primeng.module'; +import { CustomFiltersModule } from './customfilters.module'; + +import { AppComponent } from './app.component'; +import { FooterComponent } from './views/footer/footer.component'; + +import { AppRoutingModule } from './app-routing.module'; + +@NgModule({ + declarations: [ + AppComponent, + FooterComponent + ], + imports: [ + BrowserModule, + AppRoutingModule, + HttpModule, + FormsModule, + BrowserAnimationsModule, + CustomFiltersModule, + PrimeNgModule, + HeaderModule, + WeatherModule, + NewsModule, + QuoteModule + ], + bootstrap: [AppComponent] +}) +export class AppModule { } diff --git a/public/src/app/services/geo.service.ts b/public/src/app/services/geo.service.ts index 3a40311..30b0ff2 100644 --- a/public/src/app/services/geo.service.ts +++ b/public/src/app/services/geo.service.ts @@ -6,8 +6,6 @@ import { Observable } from 'rxjs/Observable'; import { GeoData } from '../Shared/GeoData'; -import { environment } from '../../environments/environment'; - @Injectable() export class GeoService { @@ -15,11 +13,7 @@ export class GeoService { getGeoCode(address: String) { -<<<<<<< HEAD - const url = `${environment.serverUrl}/api/geo?address=${address}`; -======= - const url = `http://${environment.apiUrl}:${environment.apiPort}/api/geo?address=${address}`; ->>>>>>> dockerization-branch + const url = `${environment.apiUrl}/api/geo?address=${address}`; // console.log('getGeoCode', url); return this.http.get(url) .map( diff --git a/public/src/app/services/news.service.ts b/public/src/app/services/news.service.ts index 2657c9b..1318740 100644 --- a/public/src/app/services/news.service.ts +++ b/public/src/app/services/news.service.ts @@ -17,7 +17,7 @@ export class NewsService { getSources(language: String, category: String, country: String) { - const url = `${environment.serverUrl}/api/news/sources?language=${language}&category=${category}&country=${country}`; + const url = `${environment.apiUrl}/api/news/sources?language=${language}&category=${category}&country=${country}`; console.log('getSources', url); return this.http.get(url) .map( @@ -42,7 +42,7 @@ export class NewsService { getArticles(source: String, sortBy: String) { - const url = `${environment.serverUrl}/api/news/articles?source=${source}&sortBy=${sortBy}`; + const url = `${environment.apiUrl}/api/news/articles?source=${source}&sortBy=${sortBy}`; console.log('getArticles', url); return this.http.get(url) .map( diff --git a/public/src/app/services/quote.service.ts b/public/src/app/services/quote.service.ts index 903f7de..4f53c66 100644 --- a/public/src/app/services/quote.service.ts +++ b/public/src/app/services/quote.service.ts @@ -16,7 +16,7 @@ export class QuoteService { getQuotes(symbol: String, from: String, to: String) { - const url = `${environment.serverUrl}/api/finance/quotes?symbol=${symbol}&from=${from}&to=${to}`; + const url = `${environment.apiUrl}/api/finance/quotes?symbol=${symbol}&from=${from}&to=${to}`; // console.log('getQuotes', url); return this.http.get(url) .map( @@ -41,7 +41,7 @@ export class QuoteService { getCompanyNews(symbol: String) { - const url = `${environment.serverUrl}/api/finance/companynews?symbol=${symbol}`; + const url = `${environment.apiUrl}/api/finance/companynews?symbol=${symbol}`; // console.log('getCompanyNews', url); return this.http.get(url) .map( diff --git a/public/src/app/services/serverhealth.service.ts b/public/src/app/services/serverhealth.service.ts new file mode 100644 index 0000000..ea04576 --- /dev/null +++ b/public/src/app/services/serverhealth.service.ts @@ -0,0 +1,27 @@ +import { Injectable } from '@angular/core'; +import { Http, Response } from '@angular/http'; +import { environment } from '../../environments/environment'; +import 'rxjs/Rx'; + +import { ServerHealthData } from '../Shared/ServerHealthData'; + +@Injectable() +export class ServerHealthService { + + constructor(private http: Http) { } + + check() { + + const url = `${environment.apiUrl}/api/serverhealth`; + return this.http.get(url) + .map( + (response: Response) => { + const res = response.json(); + return new ServerHealthData( + res.status, + res.text); + } + ); + } + +} diff --git a/public/src/app/services/weather.service.ts b/public/src/app/services/weather.service.ts index 57a0855..1f47f8c 100644 --- a/public/src/app/services/weather.service.ts +++ b/public/src/app/services/weather.service.ts @@ -43,9 +43,20 @@ export class WeatherService { ); } + getForecastByGeoCode(geodata: GeoData) { + + this.getForecastInfos(geodata) + .subscribe( + (weatherdata: WeatherData) => { + this.weatherChanged.next(weatherdata); + }, + (error) => console.log(error) + ); + } + private getForecastInfos(geodata: GeoData) { - const url = `${environment.serverUrl}/api/weather/${geodata.lat}/${geodata.lng}`; + const url = `${environment.apiUrl}/api/weather/${geodata.lat}/${geodata.lng}`; return this.http.post(url, {}/*, options */) .map( @@ -66,7 +77,7 @@ export class WeatherService { getFavorites() { - const url = `${environment.serverUrl}/api/weather/favorites`; + const url = `${environment.apiUrl}/api/weather/favorites`; console.log('getFavorites', url); return this.http.get(url) .subscribe( @@ -79,7 +90,7 @@ export class WeatherService { getFavorite(address: String) { - const url = `${environment.serverUrl}/api/weather/favorites/${address}`; + const url = `${environment.apiUrl}/api/weather/favorites/${address}`; console.log('getFavorite', url); return this.http.get(url) .map( @@ -96,7 +107,7 @@ export class WeatherService { addFavoriteWithCheck(address: String) { - const url = `${environment.serverUrl}/api/weather/favorites/check`; + const url = `${environment.apiUrl}/api/weather/favorites/check`; // console.log(`Calling addFavoriteWithCheck with ${url} ${address}`); return this.http.post(url, { address }) .map( @@ -112,7 +123,7 @@ export class WeatherService { addFavorite(address: String) { - const url = `${environment.serverUrl}/api/weather/favorites`; + const url = `${environment.apiUrl}/api/weather/favorites`; // console.log(`Calling getFavorites with ${url} ${address}`); return this.http.post(url, { address }) .map( @@ -124,7 +135,7 @@ export class WeatherService { deleteFromFavorites(id: String) { - const url = `${environment.serverUrl}/api/weather/favorites/${id}`; + const url = `${environment.apiUrl}/api/weather/favorites/${id}`; // console.log(`Calling deleteFromFavorites with ${url}`); return this.http.delete(url); } @@ -133,7 +144,7 @@ export class WeatherService { this.weatherFavoritesResponse = []; - const url = `${environment.serverUrl}/api/weather/favorites/active/true`; + const url = `${environment.apiUrl}/api/weather/favorites/active/true`; // console.log(`Calling getForecastForFavoritesActive with ${url}`); this.http.get(url) .subscribe( @@ -153,7 +164,7 @@ export class WeatherService { editFavoriteStatus(id: String, activeStatus: Boolean) { - const url = `${environment.serverUrl}/api/weather/favorites/${id}`; + const url = `${environment.apiUrl}/api/weather/favorites/${id}`; // console.log(`Calling editFavoriteStatus with ${id} ${activeStatus}`); return this.http.put(url, { active: activeStatus }) .subscribe( diff --git a/public/src/app/views/header/header.component.css b/public/src/app/views/header/header.component.css index a558933..4a21e78 100644 --- a/public/src/app/views/header/header.component.css +++ b/public/src/app/views/header/header.component.css @@ -10,3 +10,8 @@ .env-css-prod { color: red; } + +.api-status { + text-align: right; +} + diff --git a/public/src/app/views/header/header.component.html b/public/src/app/views/header/header.component.html index c2b3335..0fb95a1 100644 --- a/public/src/app/views/header/header.component.html +++ b/public/src/app/views/header/header.component.html @@ -1,6 +1,6 @@
-
+
+
+ +
{{environmentName}}
diff --git a/public/src/app/views/header/header.component.ts b/public/src/app/views/header/header.component.ts index a58f98e..e462beb 100644 --- a/public/src/app/views/header/header.component.ts +++ b/public/src/app/views/header/header.component.ts @@ -1,6 +1,9 @@ import { Component, OnInit } from '@angular/core'; import { environment } from '../../../environments/environment'; +import { ServerHealthService } from '../../services/serverhealth.service'; +import { ServerHealthData } from '../../Shared/ServerHealthData'; + @Component({ selector: 'app-header', templateUrl: './header.component.html', @@ -8,13 +11,22 @@ import { environment } from '../../../environments/environment'; }) export class HeaderComponent implements OnInit { - environmentName: string; + environmentName: String; + checkApiHealthResponse: ServerHealthData; - constructor() { } + constructor(private serverHealthService: ServerHealthService) { } ngOnInit() { this.environmentName = environment.name; - console.log(`Connecting to API URL: ${environment.apiUrl} | ENVIRONMENT: ${this.environmentName}`); + console.log(`Connecting to API URL: ${environment.apiUrl} | ENVIRONMENT: ${this.environmentName}`); + this.checkApiStatus(); } + checkApiStatus() { + this.serverHealthService.check() + .subscribe((data: ServerHealthData) => { + console.log(data); + this.checkApiHealthResponse = data; + }, () => this.checkApiHealthResponse = new ServerHealthData("KO", "server is down")); + } } diff --git a/public/src/app/views/header/header.module.ts b/public/src/app/views/header/header.module.ts new file mode 100644 index 0000000..14f4f3e --- /dev/null +++ b/public/src/app/views/header/header.module.ts @@ -0,0 +1,19 @@ +import { NgModule } from "@angular/core"; +import { CommonModule } from "@angular/common"; +// import { FormsModule } from '@angular/forms'; + +import { HeaderComponent } from './header.component'; + +import { ServerHealthService } from '../../services/serverhealth.service'; + +@NgModule({ + declarations: [ + HeaderComponent + ], + imports: [ + CommonModule, + ], + exports: [HeaderComponent], + providers: [ServerHealthService] +}) +export class HeaderModule {} diff --git a/public/src/app/views/weather/weather-list/weather-list.component.html b/public/src/app/views/weather/weather-list/weather-list.component.html index 2634cf6..a136e07 100644 --- a/public/src/app/views/weather/weather-list/weather-list.component.html +++ b/public/src/app/views/weather/weather-list/weather-list.component.html @@ -1,73 +1,95 @@ -
-
-

- Forecast

-
-
-
-
-
- -
-
- -
-
-
-
-
- -
-
- - {{ weatherResponse?.geodata.formatted_address | uppercase }} - -
{{weatherResponse?.temperature | convertToDegre | number:'1.0-2' }} degres | - -
{{ weatherResponse.dailySummary }} -   -
-
-
-
-
-

- FAVORITES -

-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - -
#LOCATIONTEMPERATUREPRECIP. PROBAHUMIDITYWINDSPEEDCLOUD COVERICONDAILY SUMMARY
{{ ind + 1 }}{{ elt.geodata.formatted_address | uppercase }}{{ elt.temperature | convertToDegre | number:'1.0-2' }} degres{{ elt.precipProbability }}{{ elt.humidity }}{{ elt.windSpeed }}{{ elt.cloudCover }} - - - {{ elt.dailySummary }}
-
\ No newline at end of file +
+
+

+ Forecast

+
+
+
+
+
+ +
+
+ +
+
+
+
+
+ +
+
+
+
+ +
+
+ +
+
+ +
+
+
+
+
+ +
+
+ + {{ weatherResponse?.geodata.formatted_address | uppercase }} + +
{{weatherResponse?.temperature | convertToDegre | number:'1.0-2' }} degres | + +
{{ weatherResponse.dailySummary }} +   +
+
+
+
+
+

+ FAVORITES +

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
#LOCATIONTEMPERATUREPRECIP. PROBAHUMIDITYWINDSPEEDCLOUD COVERICONDAILY SUMMARY
{{ ind + 1 }}{{ elt.geodata.formatted_address | uppercase }}{{ elt.temperature | convertToDegre | number:'1.0-2' }} degres{{ elt.precipProbability }}{{ elt.humidity }}{{ elt.windSpeed }}{{ elt.cloudCover }} + + + {{ elt.dailySummary }}
+
diff --git a/public/src/app/views/weather/weather-list/weather-list.component.ts b/public/src/app/views/weather/weather-list/weather-list.component.ts index eb6b09f..b0b5a2a 100644 --- a/public/src/app/views/weather/weather-list/weather-list.component.ts +++ b/public/src/app/views/weather/weather-list/weather-list.component.ts @@ -7,10 +7,12 @@ import { WeatherService } from '../../../services/weather.service'; import { WeatherData } from '../../../Shared/WeatherData'; import { WeatherFav } from '../../../Shared/WeatherFav'; +import { GeoData } from '../../../Shared/GeoData'; import * as _ from 'lodash'; import { OnDestroy } from '@angular/core/src/metadata/lifecycle_hooks'; + @Component({ selector: 'app-weather-list', templateUrl: './weather-list.component.html', @@ -25,12 +27,15 @@ export class WeatherListComponent implements OnInit, OnDestroy { elseBlock: any; weatherFavoritesResponse: WeatherData[] = []; defaultAddress: String = 'Paris'; + defaultLatitude: Number = Number("48.8534"); + defaultLongitude: Number = Number("2.3488"); constructor(private weatherService: WeatherService) { } ngOnInit() { this.getForecast(this.defaultAddress); + this.getForecastByGeoCode(this.defaultLatitude, this.defaultLongitude); this.getForecastForFavoritesActive(); this.subscriptionGetForecast = this.weatherService.weatherChanged @@ -56,6 +61,12 @@ export class WeatherListComponent implements OnInit, OnDestroy { this.weatherService.getForecast(address); } + getForecastByGeoCode(addressLatitude: Number, addressLongitude: Number) { + this.show = false; + console.log('getForecastByGeoCode', addressLatitude, addressLongitude); + this.weatherService.getForecastByGeoCode(new GeoData(addressLatitude, addressLongitude, `City with coordinates (${addressLatitude},${addressLongitude})`)); + } + getForecastForFavoritesActive() { this.weatherFavoritesResponse = []; this.weatherService.getForecastForFavoritesActive(); diff --git a/public/src/app/views/weather/weather.module.ts b/public/src/app/views/weather/weather.module.ts index 1ea7b5d..c5837be 100644 --- a/public/src/app/views/weather/weather.module.ts +++ b/public/src/app/views/weather/weather.module.ts @@ -1,27 +1,27 @@ -import { NgModule } from "@angular/core"; -import { CommonModule } from "@angular/common"; -import { FormsModule } from '@angular/forms'; -import { CustomFiltersModule } from '../../customfilters.module'; -import { PrimeNgModule } from '../../primeng.module'; - -import { WeatherListComponent } from './weather-list/weather-list.component'; -import { WeatherFavAddressListComponent } from './weather-fav-address-list/weather-fav-address-list.component'; - -import { WeatherService } from '../../services/weather.service'; -import { GeoService } from '../../services/geo.service'; - -@NgModule({ - declarations: [ - WeatherListComponent, - WeatherFavAddressListComponent - ], - imports: [ - CommonModule, - FormsModule, - CustomFiltersModule, - PrimeNgModule - ], - exports: [], - providers: [WeatherService, GeoService] -}) -export class WeatherModule { } \ No newline at end of file +import { NgModule } from "@angular/core"; +import { CommonModule } from "@angular/common"; +import { FormsModule } from '@angular/forms'; +import { CustomFiltersModule } from '../../customfilters.module'; +import { PrimeNgModule } from '../../primeng.module'; + +import { WeatherListComponent } from './weather-list/weather-list.component'; +import { WeatherFavAddressListComponent } from './weather-fav-address-list/weather-fav-address-list.component'; + +import { WeatherService } from '../../services/weather.service'; +import { GeoService } from '../../services/geo.service'; + +@NgModule({ + declarations: [ + WeatherListComponent, + WeatherFavAddressListComponent + ], + imports: [ + CommonModule, + FormsModule, + CustomFiltersModule, + PrimeNgModule + ], + exports: [], + providers: [WeatherService, GeoService] +}) +export class WeatherModule { } diff --git a/public/src/environments/environment.development.ts b/public/src/environments/environment.development.ts index 51cba54..a5241ed 100644 --- a/public/src/environments/environment.development.ts +++ b/public/src/environments/environment.development.ts @@ -6,6 +6,5 @@ export const environment = { production: false, name: 'development', - apiUrl: 'localhost', - apiPort: '30001' + apiUrl: 'http://localhost:30001' }; diff --git a/public/src/environments/environment.prod.ts b/public/src/environments/environment.prod.ts index f3afc54..853771e 100644 --- a/public/src/environments/environment.prod.ts +++ b/public/src/environments/environment.prod.ts @@ -1,4 +1,5 @@ export const environment = { production: true, - serverUrl: 'http://localhost:3000' + name: 'production', + apiUrl: 'http://app-backend:30001' }; diff --git a/public/src/environments/environment.staging.ts b/public/src/environments/environment.staging.ts index 96e405d..e7b026b 100644 --- a/public/src/environments/environment.staging.ts +++ b/public/src/environments/environment.staging.ts @@ -6,6 +6,5 @@ export const environment = { production: false, name: 'staging', - apiUrl: 'localhost', - apiPort: '30001' + apiUrl: 'http://localhost:30001' }; diff --git a/public/src/environments/environment.ts b/public/src/environments/environment.ts index f44bdb9..d8ca436 100644 --- a/public/src/environments/environment.ts +++ b/public/src/environments/environment.ts @@ -5,5 +5,6 @@ export const environment = { production: false, - serverUrl: 'http://localhost:3000' + name: 'development', + apiUrl: 'http://localhost:30001' }; diff --git a/server/.env b/server/.env index ef4352a..5c6dca5 100644 --- a/server/.env +++ b/server/.env @@ -1,9 +1,18 @@ # https://newsapi.org # https://npm.runkit.com/node-news +# default values when running locally for dev purpose: + +NODE_ENV=production ENV_SERVER_API_PORT=30001 ENV_SERVER_API_MONGODB_URI=mongodb://localhost:27017 -API_KEY_DARKSKY=3ef106162ed142fc3dc78e058263e0e8 -API_KEY_NEWS=a81b9a7c23394dcd9c6fc4a5bcf478ef NEWS_ARTICLES= NEWS_SOURCES=the-next-web + + + +# These keys are mandatory +#ENV_API_KEY_DARKSKY= +#ENV_API_KEY_NEWS= +ENV_API_KEY_DARKSKY=3ef106162ed142fc3dc78e058263e0e8 +ENV_API_KEY_NEWS=a81b9a7c23394dcd9c6fc4a5bcf478ef diff --git a/server/README.md b/server/README.md index c7d21c0..0eddcf2 100644 --- a/server/README.md +++ b/server/README.md @@ -22,19 +22,20 @@ npm install 3. Generate and configure API keys: -- Google Map API +Before using these templates, you need to generate some API keys: -- News API -https://newsapi.org -- Weather API - https://darksky.net/ +| API | Options | Link | +| :--------------: | --------------------- | ----------------------------------------------------- | ----------- +| Google Map API | | | Mandatory +| News API | ENV_API_KEY_DARKSKY | [https://newsapi.org](https://newsapi.org) | Mandatory +| Weather API | ENV_API_KEY_NEWS | [https://darksky.net/dev](https://darksky.net/dev) | Mandatory -Put these key into the **.env** file +Configure your key's values into the **\server\\.env** file ``` -API_KEY_DARKSKY=xxxxxx -API_KEY_NEWS=yyyyyy +ENV_API_KEY_DARKSKY= +ENV_API_KEY_NEWS= ``` 4. To start backend server: diff --git a/server/src/app.js b/server/src/app.js index 58d3689..f06f42a 100644 --- a/server/src/app.js +++ b/server/src/app.js @@ -24,11 +24,19 @@ const nodeEnv = process.env.NODE_ENV || 'test'; const mongodbUri = process.env.ENV_SERVER_API_MONGODB_URI || 'mongodb://localhost:27017'; const allowHosts = process.env.ENV_SERVER_API_ALLOW_HOSTS || '*'; const port = process.env.ENV_SERVER_API_PORT || '30001'; +const apiKeyDarksky = process.env.ENV_API_KEY_DARKSKY || ''; +const apiKeyNews = process.env.ENV_API_KEY_NEWS || ''; console.log(` > process.env.NODE_ENV = '${process.env.NODE_ENV}', use '${nodeEnv}'`); console.log(` > process.env.ENV_SERVER_API_MONGODB_URI = '${process.env.ENV_SERVER_API_MONGODB_URI}', use '${mongodbUri}'`); console.log(` > process.env.ENV_SERVER_API_ALLOW_HOSTS = '${process.env.ENV_SERVER_API_ALLOW_HOSTS}', use '${allowHosts}'`); console.log(` > process.env.ENV_SERVER_API_PORT = '${process.env.ENV_SERVER_API_PORT}', use '${port}'`); +console.log(` > process.env.ENV_API_KEY_DARKSKY = '${process.env.ENV_API_KEY_DARKSKY}'`); +console.log(` > process.env.ENV_API_KEY_NEWS = '${process.env.ENV_API_KEY_NEWS}'`); + +if (apiKeyDarksky === '') console.error(' > ENV_API_KEY_DARKSKY is empty'); +if (apiKeyNews === '') console.error(' > ENV_API_KEY_NEWS is empty'); + console.log(' *************************************'); if (nodeEnv.trim() !== 'production') { @@ -38,7 +46,7 @@ if (nodeEnv.trim() !== 'production') { const url = `${mongodbUri.trim()}/weatherapp`; mongoose.connect(url, { useMongoClient: true }, (error) => { if (!error) console.log(`Connect to mongodb with success with url : ${url} !`); - else console.log(`Error connecting to mongodb with url : ${url} !`); + else console.error(`Error connecting to mongodb with url : ${url} !`); }); } diff --git a/server/src/controllers/news_controller.js b/server/src/controllers/news_controller.js index 57d36bb..ff5a3b1 100644 --- a/server/src/controllers/news_controller.js +++ b/server/src/controllers/news_controller.js @@ -5,7 +5,7 @@ module.exports = { getArticles(req, res, next) { const { source, sortBy } = req.query; - const apiKey = `${process.env.API_KEY_NEWS}`; + const apiKey = `${process.env.ENV_API_KEY_NEWS}`; const url = `https://newsapi.org/v1/articles?source=${source}&sortBy=${sortBy}&apiKey=${apiKey}`; // console.log(url); diff --git a/server/src/controllers/server_health_controller.js b/server/src/controllers/server_health_controller.js index 5cd7fc5..4d6f34b 100644 --- a/server/src/controllers/server_health_controller.js +++ b/server/src/controllers/server_health_controller.js @@ -1,5 +1,3 @@ -const request = require('request'); - module.exports = { check(req, res) { diff --git a/server/src/controllers/weather_controller.js b/server/src/controllers/weather_controller.js index 975d5be..3a4d976 100644 --- a/server/src/controllers/weather_controller.js +++ b/server/src/controllers/weather_controller.js @@ -1,94 +1,94 @@ -const WeatherFavAddress = require('../models/weatherFavAddress'); - -const request = require('request'); - -module.exports = { - - getForecast(req, res, next) { - const { lat, lng } = req.params; - const url = `https://api.darksky.net/forecast/${process.env.API_KEY_DARKSKY}/${lat},${lng}`; - // console.log('getForecast', url); - - request({ - url, - json: true - }, (error, response, body) => { - if (error) { - console.log('Unable to connect to Forecast.io server.'); - } else if (response.statusCode === 400) { - console.log('Unable to fetch weather.'); - } else if (response.statusCode === 200) { - // console.log(`=> temperature : ${body.currently.temperature}`); - } - res.send(response); - }); - }, - - getFavorites(req, res, next) { - // console.log(`index with req.params.address=${req.params.address}`); - - if (req.params.address != null) { - WeatherFavAddress.findOne({ address: req.params.address }) - .then(item => res.send(item)) - .catch(next); - } else { - WeatherFavAddress.find({}) - .then(items => res.send(items)) - .catch(next); - } - }, - - getActive(req, res, next) { - WeatherFavAddress.find({ active: req.params.active }) - .then(items => res.send(items)) - .catch(next); - }, - - create(req, res, next) { - const itemProps = req.body; - WeatherFavAddress.create(itemProps) - .then(item => res.send(item)) - .catch(next); - }, - - createIfNotExist(req, res, next) { - const itemProps = req.body; - - WeatherFavAddress.findOne(itemProps) - .then((item) => { - // console.log('found ? ' + item); - // console.log(item); - if (item === null) { - WeatherFavAddress.create(itemProps) - .then(itemcreated => res.send(itemcreated)) - .catch(next); - } else { - res.send(null); - } - }) - .catch(next); - }, - - edit(req, res, next) { - const itemId = req.params.id; - const itemProps = req.body; - - // console.log(`edit with ${itemId} ${itemProps}`); - - WeatherFavAddress.findByIdAndUpdate({ _id: itemId }, itemProps) - .then(() => WeatherFavAddress.findById({ _id: itemId })) - .then(item => res.send(item)) - .catch(next); - }, - - delete(req, res, next) { - const itemId = req.params.id; - - // console.log('delete is called with ' + itemId); - - WeatherFavAddress.findByIdAndRemove({ _id: itemId }) - .then(item => res.status(204).send(item)) - .catch(next); - }, - -}; +const WeatherFavAddress = require('../models/weatherFavAddress'); + +const request = require('request'); + +module.exports = { + + getForecast(req, res, next) { + const { lat, lng } = req.params; + const url = `https://api.darksky.net/forecast/${process.env.ENV_API_KEY_DARKSKY}/${lat},${lng}`; + // console.log('getForecast', url); + + request({ + url, + json: true + }, (error, response, body) => { + if (error) { + console.log('Unable to connect to Forecast.io server.'); + } else if (response.statusCode === 400) { + console.log('Unable to fetch weather.'); + } else if (response.statusCode === 200) { + // console.log(`=> temperature : ${body.currently.temperature}`); + } + res.send(response); + }); + }, + + getFavorites(req, res, next) { + // console.log(`index with req.params.address=${req.params.address}`); + + if (req.params.address != null) { + WeatherFavAddress.findOne({ address: req.params.address }) + .then(item => res.send(item)) + .catch(next); + } else { + WeatherFavAddress.find({}) + .then(items => res.send(items)) + .catch(next); + } + }, + + getActive(req, res, next) { + WeatherFavAddress.find({ active: req.params.active }) + .then(items => res.send(items)) + .catch(next); + }, + + create(req, res, next) { + const itemProps = req.body; + WeatherFavAddress.create(itemProps) + .then(item => res.send(item)) + .catch(next); + }, + + createIfNotExist(req, res, next) { + const itemProps = req.body; + + WeatherFavAddress.findOne(itemProps) + .then((item) => { + // console.log('found ? ' + item); + // console.log(item); + if (item === null) { + WeatherFavAddress.create(itemProps) + .then(itemcreated => res.send(itemcreated)) + .catch(next); + } else { + res.send(null); + } + }) + .catch(next); + }, + + edit(req, res, next) { + const itemId = req.params.id; + const itemProps = req.body; + + // console.log(`edit with ${itemId} ${itemProps}`); + + WeatherFavAddress.findByIdAndUpdate({ _id: itemId }, itemProps) + .then(() => WeatherFavAddress.findById({ _id: itemId })) + .then(item => res.send(item)) + .catch(next); + }, + + delete(req, res, next) { + const itemId = req.params.id; + + // console.log('delete is called with ' + itemId); + + WeatherFavAddress.findByIdAndRemove({ _id: itemId }) + .then(item => res.status(204).send(item)) + .catch(next); + }, + +}; diff --git a/sonar-project.properties b/sonar-project.properties new file mode 100644 index 0000000..fdfb0a5 --- /dev/null +++ b/sonar-project.properties @@ -0,0 +1,18 @@ +# must be unique in a given SonarQube instance +sonar.projectKey=My-weather-app +sonar.sources=. + +# --- optional properties --- + +# defaults to project key +#sonar.projectName=My project +# defaults to 'not provided' +sonar.projectVersion=V2 + +# Path is relative to the sonar-project.properties file. Defaults to . +#sonar.sources=. + +# Encoding of the source code. Default is default system encoding +#sonar.sourceEncoding=UTF-8 + +sonar.exclusions=**/node_modules/**