Browse Source

Angular SSR

Fin de l'implémentation
henri carmelo 10 tháng trước cách đây
mục cha
commit
28026bc797

+ 206 - 145
Jenkinsfile

@@ -8,95 +8,16 @@ pipeline {
         PROD_URL = "prod.foodgame.fr"
     }
     stages {
-        stage('Setup Environment') {
-            steps {
-                script {
-                    echo "Environnement détecté : ${env.BRANCH_NAME}"
-                    if (env.BRANCH_NAME == 'test') {
-                        echo "Déploiement sur DEV (${DEV_URL})"
-                    } else if (env.BRANCH_NAME == 'dev') {
-                        echo "Déploiement sur PREPROD (${PREPROD_URL})"
-                    } else if (env.BRANCH_NAME == 'master') {
-                        echo "Déploiement sur PROD (${PROD_URL})"
-                    } else {
-                        error "Branche non prise en charge : ${env.BRANCH_NAME}"
-                    }
-                }
-                sh 'npm --version'
-            }
-        }
+        // ... (autres stages inchangés)
 
-        // stage('Checkout Code') {
-        //     steps {
-        //         deleteDir()
-        //         checkout scm
-        //     }
-        // }
-
-        // stage('SonarQube Analysis') {
-        //     steps {
-        //         script {
-        //             def scannerHome = tool name: 'SonarQube Scanner', type: 'hudson.plugins.sonar.SonarRunnerInstallation';
-        //             withSonarQubeEnv('SonarQube') { // Nom du serveur SonarQube configuré dans Jenkins
-        //                 sh """
-        //                 ${scannerHome}/bin/sonar-scanner \
-        //                 -Dsonar.projectKey=FatboarProject-${env.BRANCH_NAME} \
-        //                 -Dsonar.sources=. \
-        //                 -Dsonar.host.url=https://sonarqube.foodgame.fr \
-        //                 -Dsonar.login=sqa_d81445ef2d3961cddf7e29e31c1aeb2505aacdbd
-        //                 """
-        //             }
-        //         }
-        //     }
-        // }
-
-        // stage('Stop Containers') {
-        //     steps {
-        //         sh '''
-        //         docker ps | grep "workflow_" -v | awk -F " " '{ if(NR>1) print $1}' | xargs docker kill || true
-        //         docker system prune -f
-        //         '''
-        //     }
-        // }
-
-        // stage('Build & Deploy') {
-        //     steps {
-        //         sh '''
-        //         docker-compose stop
-        //         docker-compose build
-        //         docker-compose up -d
-        //         '''
-        //     }
-        // }
-
-        // stage('Push Docker Image (Nexus)') {
-        //     when {
-        //         branch 'master'
-        //     }
-        //     steps {
-        //         withDockerRegistry([credentialsId: 'nexus', url: 'https://nexus.foodgame.fr']) {
-        //             script {
-        //                 def dockerImageName = 'workflow_jenkins_1'
-        //                 def dockerImageTag = 'latest'
-        //                 def nexusRepository = 'fatboar_repo'
-
-        //                 sh """
-        //                 docker tag ${dockerImageName}:${dockerImageTag} ${nexusRepository}/${dockerImageName}:${dockerImageTag}
-        //                 docker push ${nexusRepository}/${dockerImageName}:${dockerImageTag}
-        //                 """
-        //             }
-        //         }
-        //     }
-        // }
-    
         stage('Docker Registry Login, Pull, and Push') {
             when {
-                branch 'master'
+                branch 'dev'
             }
             steps {
                 script {
                     def registryUrl = 'nexus.foodgame.fr:8123'
-                    def imageName = 'sonarqube'
+                    def imageName = 'grafana/tns-db'
                     def imageVersion = 'latest'
                     
                     docker.withRegistry("https://${registryUrl}", 'nexus') {
@@ -123,24 +44,12 @@ pipeline {
                 }
             }
         }
-    
-
-
-        stage('Cleanup') {
-            steps {
-                echo "Nettoyage terminé pour la branche ${env.BRANCH_NAME}"
-            }
-        }
 
-        stage('Fin du Pipeline') {
-            steps {
-                sh 'echo "Félicitations, le pipeline s\'est terminé avec succès !"'
-            }
-        }
+        // ... (autres stages inchangés)
     }
     post {
         success {
-            echo "Pipeline exécuté avec succès pour la branche ${env.BRANCH_NAME}."
+            echo "Pipeline exécutée avec succès pour la branche ${env.BRANCH_NAME}."
         }
         failure {
             echo "Échec du pipeline pour la branche ${env.BRANCH_NAME}."
@@ -150,61 +59,213 @@ pipeline {
 
 
 
+// pipeline {
+//     agent any
+//     environment {
+//         NODEJS_HOME = "${tool 'NodeJS'}"
+//         PATH = "${env.NODEJS_HOME}/bin:${env.PATH}"
+//         DEV_URL = "dev.foodgame.fr"
+//         PREPROD_URL = "preprod.foodgame.fr"
+//         PROD_URL = "prod.foodgame.fr"
+//     }
+//     stages {
+//         stage('Setup Environment') {
+//             steps {
+//                 script {
+//                     echo "Environnement détecté : ${env.BRANCH_NAME}"
+//                     if (env.BRANCH_NAME == 'test') {
+//                         echo "Déploiement sur DEV (${DEV_URL})"
+//                     } else if (env.BRANCH_NAME == 'dev') {
+//                         echo "Déploiement sur PREPROD (${PREPROD_URL})"
+//                     } else if (env.BRANCH_NAME == 'master') {
+//                         echo "Déploiement sur PROD (${PROD_URL})"
+//                     } else {
+//                         error "Branche non prise en charge : ${env.BRANCH_NAME}"
+//                     }
+//                 }
+//                 sh 'npm --version'
+//             }
+//         }
 
-// node{
+//         stage('Checkout Code') {
+//             steps {
+//                 deleteDir()
+//                 checkout scm
+//             }
+//         }
 
-//     env.NODEJS_HOME = "${tool 'NodeJS'}"
-//     // on linux / mac
-//     env.PATH="${env.NODEJS_HOME}/bin:${env.PATH}"
-//     // on windows
-//     //env.PATH="${env.NODEJS_HOME};${env.PATH}"
-//     sh 'npm --version'
+//         // stage('SonarQube Analysis') {
+//         //     steps {
+//         //         script {
+//         //             def scannerHome = tool name: 'SonarQube Scanner', type: 'hudson.plugins.sonar.SonarRunnerInstallation';
+//         //             withSonarQubeEnv('SonarQube') { // Nom du serveur SonarQube configuré dans Jenkins
+//         //                 sh """
+//         //                 ${scannerHome}/bin/sonar-scanner \
+//         //                 -Dsonar.projectKey=FatboarProject-${env.BRANCH_NAME} \
+//         //                 -Dsonar.sources=. \
+//         //                 -Dsonar.host.url=https://sonarqube.foodgame.fr \
+//         //                 -Dsonar.login=sqa_d81445ef2d3961cddf7e29e31c1aeb2505aacdbd
+//         //                 """
+//         //             }
+//         //         }
+//         //     }
+//         // }
 
-// 	stage('checkout')
-// 	{
-// 		deleteDir()
-// 		checkout scm
-// 	}
-	 
-// 	 stage('Stop Containers')
-//     {
-//         sh 'docker ps | grep "workflow_" -v | awk -F " " \'{ if(NR>1) print $1}\' |xargs docker kill |xargs docker rm || true'
-//         sh 'docker system prune -f'
+//         stage('Stop Containers') {
+//             steps {
+//                 sh '''
+//                 docker ps | grep "workflow_" -v | awk -F " " '{ if(NR>1) print $1}' | xargs docker kill || true
+//                 docker system prune -f
+//                 '''
+//             }
+//         }
+
+//         stage('Build & Deploy') {
+//             steps {
+//                 sh '''
+//                 docker-compose stop
+//                 docker-compose build
+//                 docker-compose up -d
+//                 '''
+//             }
+//         }
+
+//         // stage('Push Docker Image (Nexus)') {
+//         //     when {
+//         //         branch 'master'
+//         //     }
+//         //     steps {
+//         //         withDockerRegistry([credentialsId: 'nexus', url: 'https://nexus.foodgame.fr']) {
+//         //             script {
+//         //                 def dockerImageName = 'workflow_jenkins_1'
+//         //                 def dockerImageTag = 'latest'
+//         //                 def nexusRepository = 'fatboar_repo'
+
+//         //                 sh """
+//         //                 docker tag ${dockerImageName}:${dockerImageTag} ${nexusRepository}/${dockerImageName}:${dockerImageTag}
+//         //                 docker push ${nexusRepository}/${dockerImageName}:${dockerImageTag}
+//         //                 """
+//         //             }
+//         //         }
+//         //     }
+//         // }
+    
+//         stage('Docker Registry Login, Pull, and Push') {
+//             when {
+//                 branch 'dev'
+//             }
+//             steps {
+//                 script {
+//                     def registryUrl = 'nexus.foodgame.fr:8123'
+//                     def imageName = 'grafana/tns-db'
+//                     def imageVersion = 'latest'
+                    
+//                     docker.withRegistry("https://${registryUrl}", 'nexus') {
+//                         try {
+//                             Try pulling the image from the registry
+//                             echo "Trying to pull image: ${registryUrl}/${imageName}:${imageVersion}"
+//                             docker.image("${registryUrl}/${imageName}:${imageVersion}").pull()
+//                         } catch (Exception e) {
+//                             echo "Image pull failed. Attempting to build and push."
+
+//                             Pull base image from Docker Hub
+//                             echo "Pulling base image: ${imageName}:${imageVersion}"
+//                             sh "docker pull ${imageName}:${imageVersion}"
+                            
+//                             Tag the image for the private registry
+//                             echo "Tagging image for private registry"
+//                             sh "docker tag ${imageName}:${imageVersion} ${registryUrl}/${imageName}:${imageVersion}"
+                            
+//                             Push the tagged image to the private registry
+//                             echo "Pushing image to private registry"
+//                             sh "docker push ${registryUrl}/${imageName}:${imageVersion}"
+//                         }
+//                     }
+//                 }
+//             }
+//         }
+    
+
+
+//         stage('Cleanup') {
+//             steps {
+//                 echo "Nettoyage terminé pour la branche ${env.BRANCH_NAME}"
+//             }
+//         }
+
+//         stage('Fin du Pipeline') {
+//             steps {
+//                 sh 'echo "Félicitations, le pipeline s\'est terminé avec succès !"'
+//             }
+//         }
 //     }
+//     post {
+//         success {
+//             echo "Pipeline exécuté avec succès pour la branche ${env.BRANCH_NAME}."
+//         }
+//         failure {
+//             echo "Échec du pipeline pour la branche ${env.BRANCH_NAME}."
+//         }
+//     }
+// }
+
+
+
+
+// // node{
+
+// //     env.NODEJS_HOME = "${tool 'NodeJS'}"
+// //     // on linux / mac
+// //     env.PATH="${env.NODEJS_HOME}/bin:${env.PATH}"
+// //     // on windows
+// //     //env.PATH="${env.NODEJS_HOME};${env.PATH}"
+// //     sh 'npm --version'
+
+// // 	stage('checkout')
+// // 	{
+// // 		deleteDir()
+// // 		checkout scm
+// // 	}
+	 
+// // 	 stage('Stop Containers')
+// //     {
+// //         sh 'docker ps | grep "workflow_" -v | awk -F " " \'{ if(NR>1) print $1}\' |xargs docker kill |xargs docker rm || true'
+// //         sh 'docker system prune -f'
+// //     }
 	
 	
-// 	// stage("Push preprod images to nexus")
-// 	// {
-// 	// 	docker.withRegistry('http://localhost:8083','885ef60c-9352-489a-bd1c-e4b695747c21')
-// 	// 	{
-// 	// 		imageApache.push('latest')
-// 	// 		imageExpress.push('latest')
-// 	// 	}*/
-// 	// }
-//     // stage('SonarQube analysis') 
-//     // {  
-//     //      def scannerHome = tool name: 'SonarQube Scanner', type: 'hudson.plugins.sonar.SonarRunnerInstallation';
-//     //     withSonarQubeEnv('SonarQube') 
-//     //     { 
-//     //     // If you have configured more than one global server connection, you can specify its name
-//     //     sh "${scannerHome}/bin/sonar-scanner  \
-//     //     -Dsonar.projectKey=FatboarProject \
-//     //     -Dsonar.sources=. \
-//     //     -Dsonar.host.url=https://sonarqube.foodgame.fr \
-//     //     -Dsonar.login=sqp_09ee9072c917af8212864baf0f75c950afc14c64"
-//     //     }
-//     // }
+// // 	// stage("Push preprod images to nexus")
+// // 	// {
+// // 	// 	docker.withRegistry('http://localhost:8083','885ef60c-9352-489a-bd1c-e4b695747c21')
+// // 	// 	{
+// // 	// 		imageApache.push('latest')
+// // 	// 		imageExpress.push('latest')
+// // 	// 	}*/
+// // 	// }
+// //     // stage('SonarQube analysis') 
+// //     // {  
+// //     //      def scannerHome = tool name: 'SonarQube Scanner', type: 'hudson.plugins.sonar.SonarRunnerInstallation';
+// //     //     withSonarQubeEnv('SonarQube') 
+// //     //     { 
+// //     //     // If you have configured more than one global server connection, you can specify its name
+// //     //     sh "${scannerHome}/bin/sonar-scanner  \
+// //     //     -Dsonar.projectKey=FatboarProject \
+// //     //     -Dsonar.sources=. \
+// //     //     -Dsonar.host.url=https://sonarqube.foodgame.fr \
+// //     //     -Dsonar.login=sqp_09ee9072c917af8212864baf0f75c950afc14c64"
+// //     //     }
+// //     // }
 	
 
-//     stage('Build Docker MEAN Stack(Test Deployment)') 
-//     {
-//         sh 'docker-compose -v'
-//         sh 'docker-compose build'
-//         sh 'docker-compose up -d'
-//     }
+// //     stage('Build Docker MEAN Stack(Test Deployment)') 
+// //     {
+// //         sh 'docker-compose -v'
+// //         sh 'docker-compose build'
+// //         sh 'docker-compose up -d'
+// //     }
    
-//     stage('Fin du Pipeline') 
-//     {
-//        sh 'echo "Félicitation tout c\'est bien déroulé!"'  
-//    }
-// }
+// //     stage('Fin du Pipeline') 
+// //     {
+// //        sh 'echo "Félicitation tout c\'est bien déroulé!"'  
+// //    }
+// // }

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 1 - 0
angular-client/dist/fatboar/browser/vendor.js.map


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 327499 - 0
angular-client/dist/fatboar/server/main.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 1 - 0
angular-client/dist/fatboar/server/main.js.map


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 3108 - 3819
angular-client/package-lock.json


+ 4 - 2
angular-client/package.json

@@ -29,9 +29,9 @@
     "@angular/router": "~9.1.4",
     "@nguniversal/express-engine": "^9.1.1",
     "@types/jwt-decode": "^2.2.1",
-    "@types/leaflet": "^1.5.12",
     "bootstrap": "^4.4.1",
     "chart.js": "^2.9.3",
+    "domino": "^2.1.6",
     "express": "^4.15.2",
     "jwt-decode": "^2.2.0",
     "karma-coverage": "^2.0.3",
@@ -52,9 +52,11 @@
     "@angular/core": "~9.1.4",
     "@angular/language-service": "~9.1.4",
     "@nguniversal/builders": "^9.1.1",
-    "@types/express": "^4.17.0",
+    "@types/express": "^4.17.2",
+    "@types/express-serve-static-core": "^4.17.13",
     "@types/jasmine": "~3.5.0",
     "@types/jasminewd2": "~2.0.3",
+    "@types/leaflet": "^1.5.17",
     "@types/node": "^12.11.1",
     "chai": "^4.2.0",
     "codelyzer": "^5.1.2",

+ 80 - 4
angular-client/server.ts

@@ -1,18 +1,31 @@
 import 'zone.js/dist/zone-node';
-
 import { ngExpressEngine } from '@nguniversal/express-engine';
 import * as express from 'express';
 import { join } from 'path';
-
 import { AppServerModule } from './src/main.server';
 import { APP_BASE_HREF } from '@angular/common';
 import { existsSync } from 'fs';
 
+// Polyfills pour le SSR
+const domino = require('domino');
+const fs = require('fs');
+const path = require('path');
+// const distFolder = join(process.cwd(), 'dist/fatboar/browser');
+// const indexHtml = existsSync(join(distFolder, 'index.original.html')) ? 'index.original.html' : 'index';
+// const template = fs.readFileSync(join(distFolder, indexHtml)).toString();
+const distFolder = join(process.cwd(), 'dist/fatboar/browser');
+const indexHtml = existsSync(join(distFolder, 'index.html')) ? 'index.html' : 'index';
+const template = fs.readFileSync(join(distFolder, indexHtml)).toString();
+
+const win = domino.createWindow(template);
+global['window'] = win;
+global['document'] = win.document;
+global['navigator'] = win.navigator;
+global['CSS'] = null;
+
 // The Express app is exported so that it can be used by serverless Functions.
 export function app() {
   const server = express();
-  const distFolder = join(process.cwd(), 'dist/fatboar/browser');
-  const indexHtml = existsSync(join(distFolder, 'index.original.html')) ? 'index.original.html' : 'index';
 
   // Our Universal express-engine (found @ https://github.com/angular/universal/tree/master/modules/express-engine)
   server.engine('html', ngExpressEngine({
@@ -58,3 +71,66 @@ if (moduleFilename === __filename || moduleFilename.includes('iisnode')) {
 }
 
 export * from './src/main.server';
+
+
+
+// import 'zone.js/dist/zone-node';
+
+// import { ngExpressEngine } from '@nguniversal/express-engine';
+// import * as express from 'express';
+// import { join } from 'path';
+
+// import { AppServerModule } from './src/main.server';
+// import { APP_BASE_HREF } from '@angular/common';
+// import { existsSync } from 'fs';
+
+// // The Express app is exported so that it can be used by serverless Functions.
+// export function app() {
+//   const server = express();
+//   const distFolder = join(process.cwd(), 'dist/fatboar/browser');
+//   const indexHtml = existsSync(join(distFolder, 'index.original.html')) ? 'index.original.html' : 'index';
+
+//   // Our Universal express-engine (found @ https://github.com/angular/universal/tree/master/modules/express-engine)
+//   server.engine('html', ngExpressEngine({
+//     bootstrap: AppServerModule,
+//   }));
+
+//   server.set('view engine', 'html');
+//   server.set('views', distFolder);
+
+//   // Example Express Rest API endpoints
+//   // server.get('/api/**', (req, res) => { });
+//   // Serve static files from /browser
+//   server.get('*.*', express.static(distFolder, {
+//     maxAge: '1y'
+//   }));
+
+//   // All regular routes use the Universal engine
+//   server.get('*', (req, res) => {
+//     res.render(indexHtml, { req, providers: [{ provide: APP_BASE_HREF, useValue: req.baseUrl }] });
+//   });
+
+//   return server;
+// }
+
+// function run() {
+//   const port = process.env.PORT || 4000;
+
+//   // Start up the Node server
+//   const server = app();
+//   server.listen(port, () => {
+//     console.log(`Node Express server listening on http://localhost:${port}`);
+//   });
+// }
+
+// // Webpack will replace 'require' with '__webpack_require__'
+// // '__non_webpack_require__' is a proxy to Node 'require'
+// // The below code is to ensure that the server is run only when not requiring the bundle.
+// declare const __non_webpack_require__: NodeRequire;
+// const mainModule = __non_webpack_require__.main;
+// const moduleFilename = mainModule && mainModule.filename || '';
+// if (moduleFilename === __filename || moduleFilename.includes('iisnode')) {
+//   run();
+// }
+
+// export * from './src/main.server';

+ 2 - 0
angular-client/src/app/app.module.ts

@@ -16,6 +16,7 @@ import { FlexLayoutModule } from "@angular/flex-layout";
 import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
 import { ChartsModule } from 'ng2-charts';
 import { FormsModule } from '@angular/forms';
+// import { FlexLayoutServerModule } from '@angular/flex-layout/server';
 import { ReactiveFormsModule } from '@angular/forms';
 
 //components
@@ -123,6 +124,7 @@ import { TirageComponent } from './components/auth/tirage/tirage.component';
     MatSnackBarModule,
     ReactiveFormsModule, 
     SatDatepickerModule, 
+    // FlexLayoutServerModule,
     SatNativeDateModule,
 
   ],

+ 2 - 0
angular-client/src/app/app.server.module.ts

@@ -1,5 +1,6 @@
 import { NgModule } from '@angular/core';
 import { ServerModule } from '@angular/platform-server';
+import { FlexLayoutServerModule } from '@angular/flex-layout/server';
 
 import { AppModule } from './app.module';
 import { AppComponent } from './app.component';
@@ -7,6 +8,7 @@ import { AppComponent } from './app.component';
 @NgModule({
   imports: [
     AppModule,
+    FlexLayoutServerModule,
     ServerModule,
   ],
   bootstrap: [AppComponent],

+ 81 - 24
angular-client/src/app/components/shared/contact/map/map.component.ts

@@ -1,9 +1,8 @@
+import { Component, OnInit, Inject, PLATFORM_ID } from '@angular/core';
+import { isPlatformBrowser } from '@angular/common';
 import { Restaurant } from './../../../../models/restaurant';
-import { Component, OnInit } from '@angular/core';
-import { HttpClient } from '@angular/common/http';
-import * as L from 'leaflet';
 import { RestaurantsService } from 'src/app/services/restaurants.service';
-
+import { LeafletService } from 'src/app/services/leaflet.service'; // Assurez-vous de créer ce service
 
 @Component({
   selector: 'app-map',
@@ -11,35 +10,93 @@ import { RestaurantsService } from 'src/app/services/restaurants.service';
   styleUrls: ['./map.component.scss']
 })
 export class MapComponent implements OnInit {
-  constructor(private restaurantsService: RestaurantsService) {}
- 
-  // Fonction d'initialisation du composant.
+  private L: any;
+  private macarte: any;
+
+  constructor(
+    private restaurantsService: RestaurantsService,
+    private leafletService: LeafletService,
+    @Inject(PLATFORM_ID) private platformId: Object
+  ) {}
+
   ngOnInit() {
+    if (isPlatformBrowser(this.platformId)) {
+      this.L = this.leafletService.getLeaflet();
+      this.initMap();
+    }
+  }
+
+  private initMap(): void {
+    if (!this.L) return;
+
     // Déclaration de la carte avec les coordonnées du centre et le niveau de zoom.
-    const macarte = L.map('frugalmap').setView([48.85513, 2.353429], 9);
-   
-    L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
+    this.macarte = this.L.map('frugalmap').setView([48.85513, 2.353429], 9);
+
+    this.L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
       attribution: 'FatBoar',
-    }).addTo(macarte);
-   
-    const myIcon = L.icon({
-      // iconUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.2.0/images/marker-icon.png'
+    }).addTo(this.macarte);
+
+    const myIcon = this.L.icon({
       iconUrl: "../assets/img/marker/markericon.png"
-      
     });
-   
-   
+
     this.restaurantsService.getRestaurants().subscribe((data: any) => {
-      console.log('test resto', data)
-      data.forEach( (res : Restaurant ) => {
-        var marker = L.marker([res.latitude, res.longitude], {icon: myIcon}).addTo(macarte);
-  
+      console.log('test resto', data);
+      data.forEach((res: Restaurant) => {
+        const marker = this.L.marker([res.latitude, res.longitude], { icon: myIcon }).addTo(this.macarte);
 
         marker.bindPopup(`<h5 style="text-align: center"><b>${res.name}</b></h5>  <b> adresse : </b>${res.adress}`,
-        { maxWidth: 130 , minWidth:120}
+          { maxWidth: 130, minWidth: 120 }
         );
       });
     });
-   
-  }
   }
+}
+
+
+
+// import { Restaurant } from './../../../../models/restaurant';
+// import { Component, OnInit } from '@angular/core';
+// import { HttpClient } from '@angular/common/http';
+// import * as L from 'leaflet';
+// import { RestaurantsService } from 'src/app/services/restaurants.service';
+
+
+// @Component({
+//   selector: 'app-map',
+//   templateUrl: './map.component.html',
+//   styleUrls: ['./map.component.scss']
+// })
+// export class MapComponent implements OnInit {
+//   constructor(private restaurantsService: RestaurantsService) {}
+ 
+//   // Fonction d'initialisation du composant.
+//   ngOnInit() {
+//     // Déclaration de la carte avec les coordonnées du centre et le niveau de zoom.
+//     const macarte = L.map('frugalmap').setView([48.85513, 2.353429], 9);
+   
+//     L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
+//       attribution: 'FatBoar',
+//     }).addTo(macarte);
+   
+//     const myIcon = L.icon({
+//       // iconUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.2.0/images/marker-icon.png'
+//       iconUrl: "../assets/img/marker/markericon.png"
+      
+//     });
+   
+   
+//     this.restaurantsService.getRestaurants().subscribe((data: any) => {
+//       console.log('test resto', data)
+//       data.forEach( (res : Restaurant ) => {
+//         var marker = L.marker([res.latitude, res.longitude], {icon: myIcon}).addTo(macarte);
+  
+
+//         marker.bindPopup(`<h5 style="text-align: center"><b>${res.name}</b></h5>  <b> adresse : </b>${res.adress}`,
+//         { maxWidth: 130 , minWidth:120}
+//         );
+//       });
+//     });
+   
+//   }
+//   }

+ 238 - 95
angular-client/src/app/services/auth.service.ts

@@ -1,144 +1,103 @@
 import { environment } from 'src/environments/environment';
 import { User } from './../models/userResponse';
 import { Token, payloadToken } from './../models/token';
-import { Injectable } from '@angular/core';
-import { HttpClient, HttpHeaders } from '@angular/common/http';
-import { BehaviorSubject, Observable, throwError } from 'rxjs';
+import { Injectable, Inject, PLATFORM_ID } from '@angular/core';
+import { HttpClient } from '@angular/common/http';
+import { BehaviorSubject, Observable } from 'rxjs';
 import { Router } from '@angular/router';
 import { MatSnackBar } from '@angular/material/snack-bar';
-import { AlertMessageComponent } from 'src/app/components/shared/alert-message/alert-message.component'
-import { catchError, map, tap } from 'rxjs/operators';
+import { AlertMessageComponent } from 'src/app/components/shared/alert-message/alert-message.component';
+import { map, tap } from 'rxjs/operators';
 import * as jwt_decode from 'jwt-decode';
-
-
+import { isPlatformBrowser } from '@angular/common';
+import { StorageService } from 'src/app/services/storage.service'; // Assurez-vous de créer ce service
 
 @Injectable({
   providedIn: 'root'
 })
 export class AuthService {
-
-  //url api
-  private apiUrl = environment.apiUrl
-
+  private apiUrl = environment.apiUrl;
   private currentUserSubject: BehaviorSubject<User> = new BehaviorSubject<User>(null);
   public currentUser: Observable<User> = this.currentUserSubject.asObservable();
-
-  
-
-
   private tokenSubject: BehaviorSubject<Token>;
   public token: Observable<Token>;
-
   private user_infoSubject: BehaviorSubject<User>;
   public user_info: Observable<User>;
-
   private messageSource = new BehaviorSubject('default message');
   currentMessage = this.messageSource.asObservable();
 
-  constructor(private http: HttpClient, public router: Router, public snackBar: MatSnackBar) {
-
-    this.tokenSubject = new BehaviorSubject<Token>(JSON.parse(localStorage.getItem('token')));
+  constructor(
+    private http: HttpClient,
+    public router: Router,
+    public snackBar: MatSnackBar,
+    private storageService: StorageService,
+    @Inject(PLATFORM_ID) private platformId: Object
+  ) {
+    this.tokenSubject = new BehaviorSubject<Token>(JSON.parse(this.storageService.getItem('token')));
     this.token = this.tokenSubject.asObservable();
-
-    this.user_infoSubject = new BehaviorSubject<User>(JSON.parse(localStorage.getItem('user')));
+    this.user_infoSubject = new BehaviorSubject<User>(JSON.parse(this.storageService.getItem('user')));
     this.user_info = this.user_infoSubject.asObservable();
-    
   }
 
   changeMessage(message: string) {
-    this.messageSource.next(message)
+    this.messageSource.next(message);
   }
 
-  //get token
   public get tokenValue(): Token {
     return this.tokenSubject.value;
   }
 
-  //get user Info
   public get userValue(): User {
     return this.user_infoSubject.value;
   }
 
-  // login get  token on login 
   signIn(credentials): Observable<Token> {
-     //debugger;
-    console.log("url ========",this.apiUrl);
-
     return this.http.post<Token>(`${this.apiUrl}/api/auth/login`, credentials)
       .pipe(map(token => {
-        // store jwt token in local storage 
-        localStorage.setItem('token', JSON.stringify(token));
+        this.storageService.setItem('token', JSON.stringify(token));
         this.tokenSubject.next(token);
         return token;
       }));
   }
 
-
-  // Méthode pour s'authentifier avec Google
   signInWithGoogle(): Observable<User> {
     return this.http.get<User>(`${this.apiUrl}/api/auth/google`).pipe(
       map(user => {
-        console.log('je suis present', user )
-        localStorage.setItem('user', JSON.stringify(user));
+        console.log('je suis present', user);
+        this.storageService.setItem('user', JSON.stringify(user));
         return user;
       })
     );
   }
-  
-  // signInWithGoogle(): Observable<string> {
-  //   return this.http.get<any>(`${this.apiUrl}/api/auth/google/callback`).pipe(
-  //     map(response => response.token),
-  //     catchError(error => {
-  //       console.log(error);
-  //       // Gérer l'erreur
-  //       throw error;
-  //     })
-  //   );
-  // }
-    // login get  token on login admin
-    signInAdmin(credentials): Observable<Token> {
-       //debugger;
-      console.log("url ========",this.apiUrl);
-  
-      return this.http.post<Token>(`${this.apiUrl}/api/auth/admin`, credentials)
-        .pipe(map(token => {
-          // store jwt token in local storage 
-          localStorage.setItem('token', JSON.stringify(token));
-          this.tokenSubject.next(token);
-          return token;
-        }));
-    }
-
 
+  signInAdmin(credentials): Observable<Token> {
+    return this.http.post<Token>(`${this.apiUrl}/api/auth/admin`, credentials)
+      .pipe(map(token => {
+        this.storageService.setItem('token', JSON.stringify(token));
+        this.tokenSubject.next(token);
+        return token;
+      }));
+  }
 
-  // iscription get  token on login 
   signUP(data): Observable<Token> {
-
     return this.http.post<Token>(`${this.apiUrl}/api/auth/signup`, data)
       .pipe(map(token => {
-        // store jwt token in local storage 
-        localStorage.setItem('token', JSON.stringify(token));
+        this.storageService.setItem('token', JSON.stringify(token));
         this.tokenSubject.next(token);
         return token;
       }));
   }
 
+  lostPassword(email): Observable<any> {
+    return this.http.put<any>(`${this.apiUrl}/api/auth/forgot-password`, email);
+  }
 
+  resetPassword(data): Observable<any> {
+    return this.http.put<any>(`${this.apiUrl}/api/auth/reset-password`, data);
+  }
 
-// mot de passe oublie 
-lostPassword(email): Observable<any> {
-  return this.http.put<any>(`${this.apiUrl}/api/auth/forgot-password`, email)
-}
-
-
-// réinitialiser mot de passe  
-resetPassword(data): Observable<any> {
-  return this.http.put<any>(`${this.apiUrl}/api/auth/reset-password`, data)
-}
-
-  // isLoggedIn
   public isLoggedIn() {
-    return localStorage.getItem('token') !== null;
+    return this.storageService.getItem('token') !== null;
   }
 
   getCurrentUser(): Observable<User> {
@@ -149,34 +108,28 @@ resetPassword(data): Observable<any> {
     );
   }
 
-  //logout
   public logout() {
-    // remove token from local storage 
-    localStorage.removeItem('token');
+    this.storageService.removeItem('token');
     this.tokenSubject.next(null);
-    // remove user from local storage 
-    localStorage.removeItem('user');
+    this.storageService.removeItem('user');
     this.user_infoSubject.next(null);
     this.router.navigate(['/login']);
-    setTimeout(() => {
-      document.location.reload()
-    },1000)
+    if (isPlatformBrowser(this.platformId)) {
+      setTimeout(() => {
+        document.location.reload();
+      }, 1000);
+    }
   }
 
-   // get info user 
-   getUserInfo(): Observable<User> {
-    
-    let decodedToken : payloadToken = jwt_decode(this.tokenSubject.value.token); 
+  getUserInfo(): Observable<User> {
+    let decodedToken: payloadToken = jwt_decode(this.tokenSubject.value.token); 
     return this.http.get<User>(`${this.apiUrl}/api/users/${decodedToken.userId}`)
       .pipe(map(user => {
-        // store user info in local storage 
-        localStorage.setItem('user', JSON.stringify(user));
+        this.storageService.setItem('user', JSON.stringify(user));
         this.user_infoSubject.next(user);
         return user; 
       }));
-    
   }
-  
 
   openSnackBar(message: string) {
     this.snackBar.openFromComponent(AlertMessageComponent, {
@@ -185,6 +138,196 @@ resetPassword(data): Observable<any> {
       duration: 10000
     });
   }
+}
+
+
+// import { environment } from 'src/environments/environment';
+// import { User } from './../models/userResponse';
+// import { Token, payloadToken } from './../models/token';
+// import { Injectable } from '@angular/core';
+// import { HttpClient, HttpHeaders } from '@angular/common/http';
+// import { BehaviorSubject, Observable, throwError } from 'rxjs';
+// import { Router } from '@angular/router';
+// import { MatSnackBar } from '@angular/material/snack-bar';
+// import { AlertMessageComponent } from 'src/app/components/shared/alert-message/alert-message.component'
+// import { catchError, map, tap } from 'rxjs/operators';
+// import * as jwt_decode from 'jwt-decode';
+
+
+
+// @Injectable({
+//   providedIn: 'root'
+// })
+// export class AuthService {
+
+//   //url api
+//   private apiUrl = environment.apiUrl
+
+//   private currentUserSubject: BehaviorSubject<User> = new BehaviorSubject<User>(null);
+//   public currentUser: Observable<User> = this.currentUserSubject.asObservable();
+
+  
+
+
+//   private tokenSubject: BehaviorSubject<Token>;
+//   public token: Observable<Token>;
+
+//   private user_infoSubject: BehaviorSubject<User>;
+//   public user_info: Observable<User>;
+
+//   private messageSource = new BehaviorSubject('default message');
+//   currentMessage = this.messageSource.asObservable();
+
+//   constructor(private http: HttpClient, public router: Router, public snackBar: MatSnackBar) {
+
+//     this.tokenSubject = new BehaviorSubject<Token>(JSON.parse(localStorage.getItem('token')));
+//     this.token = this.tokenSubject.asObservable();
+
+//     this.user_infoSubject = new BehaviorSubject<User>(JSON.parse(localStorage.getItem('user')));
+//     this.user_info = this.user_infoSubject.asObservable();
+    
+//   }
+
+//   changeMessage(message: string) {
+//     this.messageSource.next(message)
+//   }
+
+//   //get token
+//   public get tokenValue(): Token {
+//     return this.tokenSubject.value;
+//   }
+
+//   //get user Info
+//   public get userValue(): User {
+//     return this.user_infoSubject.value;
+//   }
+
+//   // login get  token on login 
+//   signIn(credentials): Observable<Token> {
+//      //debugger;
+//     console.log("url ========",this.apiUrl);
+
+//     return this.http.post<Token>(`${this.apiUrl}/api/auth/login`, credentials)
+//       .pipe(map(token => {
+//         // store jwt token in local storage 
+//         localStorage.setItem('token', JSON.stringify(token));
+//         this.tokenSubject.next(token);
+//         return token;
+//       }));
+//   }
+
+
+//   // Méthode pour s'authentifier avec Google
+//   signInWithGoogle(): Observable<User> {
+//     return this.http.get<User>(`${this.apiUrl}/api/auth/google`).pipe(
+//       map(user => {
+//         console.log('je suis present', user )
+//         localStorage.setItem('user', JSON.stringify(user));
+//         return user;
+//       })
+//     );
+//   }
+  
+//   // signInWithGoogle(): Observable<string> {
+//   //   return this.http.get<any>(`${this.apiUrl}/api/auth/google/callback`).pipe(
+//   //     map(response => response.token),
+//   //     catchError(error => {
+//   //       console.log(error);
+//   //       // Gérer l'erreur
+//   //       throw error;
+//   //     })
+//   //   );
+//   // }
+//     // login get  token on login admin
+//     signInAdmin(credentials): Observable<Token> {
+//        //debugger;
+//       console.log("url ========",this.apiUrl);
+  
+//       return this.http.post<Token>(`${this.apiUrl}/api/auth/admin`, credentials)
+//         .pipe(map(token => {
+//           // store jwt token in local storage 
+//           localStorage.setItem('token', JSON.stringify(token));
+//           this.tokenSubject.next(token);
+//           return token;
+//         }));
+//     }
+
+
+
+//   // iscription get  token on login 
+//   signUP(data): Observable<Token> {
+
+//     return this.http.post<Token>(`${this.apiUrl}/api/auth/signup`, data)
+//       .pipe(map(token => {
+//         // store jwt token in local storage 
+//         localStorage.setItem('token', JSON.stringify(token));
+//         this.tokenSubject.next(token);
+//         return token;
+//       }));
+//   }
+
+
+
+// // mot de passe oublie 
+// lostPassword(email): Observable<any> {
+//   return this.http.put<any>(`${this.apiUrl}/api/auth/forgot-password`, email)
+// }
+
+
+// // réinitialiser mot de passe  
+// resetPassword(data): Observable<any> {
+//   return this.http.put<any>(`${this.apiUrl}/api/auth/reset-password`, data)
+// }
+
+//   // isLoggedIn
+//   public isLoggedIn() {
+//     return localStorage.getItem('token') !== null;
+//   }
+
+//   getCurrentUser(): Observable<User> {
+//     return this.http.get<User>('/api/auth/user').pipe(
+//       tap((user) => {
+//         this.currentUserSubject.next(user);
+//       })
+//     );
+//   }
+
+//   //logout
+//   public logout() {
+//     // remove token from local storage 
+//     localStorage.removeItem('token');
+//     this.tokenSubject.next(null);
+//     // remove user from local storage 
+//     localStorage.removeItem('user');
+//     this.user_infoSubject.next(null);
+//     this.router.navigate(['/login']);
+//     setTimeout(() => {
+//       document.location.reload()
+//     },1000)
+//   }
+
+//    // get info user 
+//    getUserInfo(): Observable<User> {
+    
+//     let decodedToken : payloadToken = jwt_decode(this.tokenSubject.value.token); 
+//     return this.http.get<User>(`${this.apiUrl}/api/users/${decodedToken.userId}`)
+//       .pipe(map(user => {
+//         // store user info in local storage 
+//         localStorage.setItem('user', JSON.stringify(user));
+//         this.user_infoSubject.next(user);
+//         return user; 
+//       }));
+    
+//   }
+  
+
+//   openSnackBar(message: string) {
+//     this.snackBar.openFromComponent(AlertMessageComponent, {
+//       data: message,
+//       panelClass: ['blue-snackbar'],
+//       duration: 10000
+//     });
+//   }
 
 
-}
+// }

+ 20 - 0
angular-client/src/app/services/leaflet.service.ts

@@ -0,0 +1,20 @@
+// leaflet.service.ts
+import { Injectable, Inject, PLATFORM_ID } from '@angular/core';
+import { isPlatformBrowser } from '@angular/common';
+
+@Injectable({
+  providedIn: 'root'
+})
+export class LeafletService {
+  private L: any;
+
+  constructor(@Inject(PLATFORM_ID) private platformId: Object) {
+    if (isPlatformBrowser(this.platformId)) {
+      this.L = require('leaflet');
+    }
+  }
+
+  getLeaflet() {
+    return this.L;
+  }
+}

+ 33 - 0
angular-client/src/app/services/storage.service.ts

@@ -0,0 +1,33 @@
+import { Injectable, Inject, PLATFORM_ID } from '@angular/core';
+import { isPlatformBrowser } from '@angular/common';
+
+@Injectable({
+  providedIn: 'root'
+})
+export class StorageService {
+  private storage: Storage;
+
+  constructor(@Inject(PLATFORM_ID) private platformId: Object) {
+    this.storage = isPlatformBrowser(this.platformId) ? localStorage : {
+      getItem: (key: string) => null,
+      setItem: (key: string, value: string) => {},
+      removeItem: (key: string) => {},
+      length: 0,
+      clear: () => {},
+      key: (index: number) => null
+    };
+
+  }
+
+  getItem(key: string): string | null {
+    return this.storage.getItem(key);
+  }
+
+  setItem(key: string, value: string): void {
+    this.storage.setItem(key, value);
+  }
+
+  removeItem(key: string): void {
+    this.storage.removeItem(key);
+  }
+}