diff --git a/front-end/angular.json b/front-end/angular.json index c384268..ae6c443 100644 --- a/front-end/angular.json +++ b/front-end/angular.json @@ -15,12 +15,14 @@ "prefix": "app", "architect": { "build": { - "builder": "@angular-devkit/build-angular:application", + "builder": "@ngx-env/builder:application", "options": { "outputPath": "dist/regard-d-altitude", "index": "src/index.html", "browser": "src/main.ts", - "polyfills": ["zone.js"], + "polyfills": [ + "zone.js" + ], "tsConfig": "tsconfig.app.json", "inlineStyleLanguage": "scss", "assets": [ @@ -79,7 +81,7 @@ "defaultConfiguration": "production" }, "serve": { - "builder": "@angular-devkit/build-angular:dev-server", + "builder": "@ngx-env/builder:dev-server", "configurations": { "production": { "buildTarget": "regard-d-altitude:build:production" @@ -91,12 +93,15 @@ "defaultConfiguration": "development" }, "extract-i18n": { - "builder": "@angular-devkit/build-angular:extract-i18n" + "builder": "@ngx-env/builder:extract-i18n" }, "test": { - "builder": "@angular-devkit/build-angular:karma", + "builder": "@ngx-env/builder:karma", "options": { - "polyfills": ["zone.js", "zone.js/testing"], + "polyfills": [ + "zone.js", + "zone.js/testing" + ], "tsConfig": "tsconfig.spec.json", "inlineStyleLanguage": "scss", "assets": [ @@ -122,4 +127,4 @@ } } } -} +} \ No newline at end of file diff --git a/front-end/package-lock.json b/front-end/package-lock.json index 1925a86..61a9a4f 100644 --- a/front-end/package-lock.json +++ b/front-end/package-lock.json @@ -39,6 +39,7 @@ "@angular-devkit/build-angular": "^18.0.6", "@angular/cli": "^18.0.6", "@angular/compiler-cli": "^18.0.5", + "@ngx-env/builder": "^18.0.1", "@types/express": "^4.17.17", "@types/jasmine": "~5.1.0", "@types/leaflet": "^1.9.12", @@ -2652,6 +2653,194 @@ "node": ">=10.0.0" } }, + "node_modules/@dotenv-run/core": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@dotenv-run/core/-/core-1.3.5.tgz", + "integrity": "sha512-jwXSX/r4VIGUOd/xqRjD5QUYRhKhKOmhhFSPDaIOsajFL+LVYBGADTFcakZ5O9x2BOGxDjIVUJzIE8jTpJ29JA==", + "dev": true, + "dependencies": { + "chalk": "^4.1.0", + "dotenv": "^16.1.4", + "dotenv-expand": "^10.0.0", + "find-up": "^5.0.0" + } + }, + "node_modules/@dotenv-run/core/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@dotenv-run/core/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@dotenv-run/core/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@dotenv-run/core/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@dotenv-run/core/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@dotenv-run/core/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@dotenv-run/core/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@dotenv-run/core/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@dotenv-run/core/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@dotenv-run/core/node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@dotenv-run/core/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@dotenv-run/core/node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@dotenv-run/esbuild": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@dotenv-run/esbuild/-/esbuild-1.4.0.tgz", + "integrity": "sha512-pXT4qARGRtWtL+/8MVGNc+oatVeNjK5Y415IjxMnGfriMwYuAwz5cWHB4YHIUTpPjkVCxsnPVb4wwr888IuN3g==", + "dev": true, + "dependencies": { + "@dotenv-run/core": "~1.3.5" + }, + "peerDependencies": { + "esbuild": "0.21.3" + } + }, + "node_modules/@dotenv-run/webpack": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@dotenv-run/webpack/-/webpack-1.4.0.tgz", + "integrity": "sha512-gQKOdSWs4iYaJ628A3YpPbM0XJvdCg44Wck1kL+UuumRboGcPoq5M35KKmrBQ/abjGeawrZyYimD4T1PiZ9bCA==", + "dev": true, + "dependencies": { + "@dotenv-run/core": "^1.3.4" + }, + "peerDependencies": { + "webpack": "^5.0.0" + } + }, "node_modules/@esbuild/aix-ppc64": { "version": "0.21.3", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.3.tgz", @@ -4188,6 +4377,61 @@ "webpack": "^5.54.0" } }, + "node_modules/@ngx-env/builder": { + "version": "18.0.1", + "resolved": "https://registry.npmjs.org/@ngx-env/builder/-/builder-18.0.1.tgz", + "integrity": "sha512-zADxSVnhbRqRSWJI09481JNFdsApAwPynDY1UeHWp5BGFI7Qur1fyqjV8ZMqAHhzOv35Z0Wb4JEm8d1/ukQTIg==", + "dev": true, + "dependencies": { + "@dotenv-run/esbuild": "^1.4.0", + "@dotenv-run/webpack": "^1.4.0", + "glob": "^10.3.10" + } + }, + "node_modules/@ngx-env/builder/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@ngx-env/builder/node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "dev": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@ngx-env/builder/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -6988,6 +7232,27 @@ "url": "https://github.com/fb55/domutils?sponsor=1" } }, + "node_modules/dotenv": { + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", + "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/dotenv-expand": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-10.0.0.tgz", + "integrity": "sha512-GopVGCpVS1UKH75VKHGuQFqS1Gusej0z4FyQkPdwjil2gNIv+LNsqBlboOzpJFZKVT95GkCyWJbBSdFEFUWI2A==", + "dev": true, + "engines": { + "node": ">=12" + } + }, "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", diff --git a/front-end/package.json b/front-end/package.json index 62b9b0f..b6b9569 100644 --- a/front-end/package.json +++ b/front-end/package.json @@ -45,6 +45,7 @@ "@angular-devkit/build-angular": "^18.0.6", "@angular/cli": "^18.0.6", "@angular/compiler-cli": "^18.0.5", + "@ngx-env/builder": "^18.0.1", "@types/express": "^4.17.17", "@types/jasmine": "~5.1.0", "@types/leaflet": "^1.9.12", diff --git a/front-end/src/app/services/auth.service.ts b/front-end/src/app/services/auth.service.ts index 699d1cc..c883b9a 100644 --- a/front-end/src/app/services/auth.service.ts +++ b/front-end/src/app/services/auth.service.ts @@ -2,7 +2,6 @@ import { Injectable } from '@angular/core'; import { HttpClient, HttpHeaders } from '@angular/common/http'; import { inject } from '@angular/core'; import { BehaviorSubject } from 'rxjs'; -import { environment } from '../../environments/environment'; import { User } from '../types/types'; import { OfflineService } from './offline.service'; @@ -17,6 +16,7 @@ const httpOptions = { providedIn: 'root', }) export class AuthService { + apiUrl = (import.meta as any).env.NG_APP_API_URL; httpClient = inject(HttpClient); offlineService = inject(OfflineService); @@ -28,15 +28,12 @@ export class AuthService { } getAccount() { - return this.httpClient.get( - `${environment.apiUrl}/api/accounts/me/`, - httpOptions, - ); + return this.httpClient.get(`${this.apiUrl}/api/accounts/me/`, httpOptions); } login(account: { email: string; password: string }) { return this.httpClient.post( - `${environment.apiUrl}/api/token/`, + `${this.apiUrl}/api/token/`, account, httpOptions, ); @@ -56,7 +53,7 @@ export class AuthService { password: string; }) { return this.httpClient.post( - `${environment.apiUrl}/api/accounts/sign-up/`, + `${this.apiUrl}/api/accounts/sign-up/`, account, httpOptions, ); @@ -64,14 +61,14 @@ export class AuthService { deleteAccount() { return this.httpClient.delete( - `${environment.apiUrl}/api/accounts/me/`, + `${this.apiUrl}/api/accounts/me/`, httpOptions, ); } changePassword(password: string) { return this.httpClient.patch( - `${environment.apiUrl}/api/accounts/me/`, + `${this.apiUrl}/api/accounts/me/`, { password }, httpOptions, ); @@ -81,7 +78,7 @@ export class AuthService { refreshToken(refreshRoken: string) { return this.httpClient.post( - `${environment.apiUrl}/api/token/refresh/`, + `${this.apiUrl}/api/token/refresh/`, { refresh: refreshRoken, }, diff --git a/front-end/src/app/services/observations.service.ts b/front-end/src/app/services/observations.service.ts index cb66d81..d7056cf 100644 --- a/front-end/src/app/services/observations.service.ts +++ b/front-end/src/app/services/observations.service.ts @@ -1,6 +1,5 @@ import { HttpClient, HttpHeaders } from '@angular/common/http'; import { inject, Injectable } from '@angular/core'; -import { environment } from '../../environments/environment'; import { ObservationFeature } from '../types/types'; const httpOptions = { @@ -14,6 +13,7 @@ const httpOptions = { providedIn: 'root', }) export class ObservationsService { + apiUrl = (import.meta as any).env.NG_APP_API_URL; httpClient = inject(HttpClient); constructor() {} @@ -23,7 +23,7 @@ export class ObservationsService { startDate?: string, endDate?: string, ) { - let url = `${environment.apiUrl}/api/observations/`; + let url = `${this.apiUrl}/api/observations/`; if (observationTypesId) { for (let index = 0; index < observationTypesId.length; index++) { const observationTypeId = observationTypesId[index]; @@ -42,21 +42,21 @@ export class ObservationsService { getObservation(observationId: string) { return this.httpClient.get( - `${environment.apiUrl}/api/observations/${observationId}/`, + `${this.apiUrl}/api/observations/${observationId}/`, httpOptions, ); } getMyObservations() { return this.httpClient.get( - `${environment.apiUrl}/api/accounts/me/observations/`, + `${this.apiUrl}/api/accounts/me/observations/`, httpOptions, ); } sendObservation(observation: ObservationFeature) { return this.httpClient.post( - `${environment.apiUrl}/api/accounts/me/observations/`, + `${this.apiUrl}/api/accounts/me/observations/`, { ...observation }, httpOptions, ); @@ -67,7 +67,7 @@ export class ObservationsService { formData.append('media_file', file); formData.append('media_type', 'image'); return this.httpClient.post( - `${environment.apiUrl}/api/accounts/me/observations/${observationId}/medias/`, + `${this.apiUrl}/api/accounts/me/observations/${observationId}/medias/`, formData, ); } diff --git a/front-end/src/app/services/settings.service.ts b/front-end/src/app/services/settings.service.ts index 52fc901..15686ca 100644 --- a/front-end/src/app/services/settings.service.ts +++ b/front-end/src/app/services/settings.service.ts @@ -1,6 +1,5 @@ import { HttpClient, HttpHeaders } from '@angular/common/http'; import { inject, Injectable, PLATFORM_ID } from '@angular/core'; -import { environment } from '../../environments/environment'; import { BehaviorSubject, firstValueFrom } from 'rxjs'; import { Settings } from '../types/types'; import { OfflineService } from './offline.service'; @@ -21,6 +20,7 @@ const httpIconOptions = { providedIn: 'root', }) export class SettingsService { + apiUrl = (import.meta as any).env.NG_APP_API_URL; httpClient = inject(HttpClient); settings = new BehaviorSubject(null); offlineService = inject(OfflineService); @@ -32,10 +32,7 @@ export class SettingsService { } getSettings() { - return this.httpClient.get( - `${environment.apiUrl}/api/settings/`, - httpOptions, - ); + return this.httpClient.get(`${this.apiUrl}/api/settings/`, httpOptions); } async setSettings(settings: Settings) { diff --git a/front-end/src/env.d.ts b/front-end/src/env.d.ts new file mode 100644 index 0000000..f27c3a9 --- /dev/null +++ b/front-end/src/env.d.ts @@ -0,0 +1,27 @@ +// Define the type of the environment variables. +declare interface Env { + readonly NODE_ENV: string; + // Replace the following with your own environment variables. + // Example: NGX_VERSION: string; + [key: string]: any; +} + +// Choose how to access the environment variables. +// Remove the unused options. + +// 1. Use import.meta.env.YOUR_ENV_VAR in your code. (conventional) +declare interface ImportMeta { + readonly env: Env; +} + +// 2. Use _NGX_ENV_.YOUR_ENV_VAR in your code. (customizable) +// You can modify the name of the variable in angular.json. +// ngxEnv: { +// define: '_NGX_ENV_', +// } +declare const _NGX_ENV_: Env; + +// 3. Use process.env.YOUR_ENV_VAR in your code. (deprecated) +declare namespace NodeJS { + export interface ProcessEnv extends Env {} +} diff --git a/front-end/src/environments/environment.development.ts b/front-end/src/environments/environment.development.ts index 65eaecc..6d8c3b3 100644 --- a/front-end/src/environments/environment.development.ts +++ b/front-end/src/environments/environment.development.ts @@ -1,5 +1,4 @@ export const environment = { - apiUrl: '', baseMaps: { mainMap: { url: 'https://data.geopf.fr/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=GEOGRAPHICALGRIDSYSTEMS.PLANIGNV2&STYLE=normal&FORMAT=image/png&TILEMATRIXSET=PM&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}', diff --git a/front-end/src/environments/environment.ts b/front-end/src/environments/environment.ts index 65eaecc..6d8c3b3 100644 --- a/front-end/src/environments/environment.ts +++ b/front-end/src/environments/environment.ts @@ -1,5 +1,4 @@ export const environment = { - apiUrl: '', baseMaps: { mainMap: { url: 'https://data.geopf.fr/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=GEOGRAPHICALGRIDSYSTEMS.PLANIGNV2&STYLE=normal&FORMAT=image/png&TILEMATRIXSET=PM&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}',