From 6842cab307133193b117436198f53ffde2a02dfb Mon Sep 17 00:00:00 2001
From: Marco Martorana <74554879+marcomartorana@users.noreply.github.com>
Date: Mon, 27 Sep 2021 17:48:24 +0200
Subject: [PATCH] Add Dashboard functionalities, Add Translation for new pages,
 Change on Auth/services to get Roles (due to Spring needed)

---
 Dockerfile                                    |   3 +-
 adapt-config-json.sh                          |   3 +-
 package-lock.json                             |  41 +++
 package.json                                  |   5 +
 .../components/header/header.component.html   |  34 ++-
 src/app/app.component.ts                      |  27 +-
 src/app/app.module.ts                         | 182 ++++++-------
 src/app/auth/oidc/oidc.ts                     |   4 +
 src/app/auth/services/auth.guard.ts           |   3 +-
 .../services/oidc-user-information.service.ts |  15 +-
 src/app/auth/services/token.interceptor.ts    |  27 +-
 .../datalet-iframe.component.html             |   2 +-
 .../dataset/dataset.component.ts              |   1 +
 .../services/data-cataglogue-api.service.ts   |   1 -
 src/app/pages/home/home.component.html        | 123 ++++++++-
 src/app/pages/pages-menu.ts                   |  28 ++
 src/app/pages/pages-routing.module.ts         |   7 +
 src/app/pages/pages.component.ts              |  45 +++-
 src/app/pages/pages.module.ts                 |   5 +-
 src/assets/config-template.json               |   7 +
 src/assets/config.json                        |   7 +
 src/assets/i18n/en.json                       | 242 ++++++++++++++++++
 src/polyfills.ts                              |   2 +
 23 files changed, 682 insertions(+), 132 deletions(-)

diff --git a/Dockerfile b/Dockerfile
index 5086028b..a1dbf744 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -31,5 +31,6 @@ ENV DASHBOARD_BASE_URL=http://localhost:4200 \
 	BIKE_ANALYSIS_API_BASE_URL=http://localhost:8000/bikeAnalysis \
 	IDRA_BASE_URL=http://localhost:8080 \
 	DATALET_BASE_URL=http://localhost/deep/deep-components/creator.html \
-	TRAFFICSIMSERVER_API_BASE_URL=http://localhost:8081
+	TRAFFICSIMSERVER_API_BASE_URL=http://localhost:8081 \
+	DASHBOARD_CTRL_API_BASE_URL=http://localhost:8085
 	
\ No newline at end of file
diff --git a/adapt-config-json.sh b/adapt-config-json.sh
index b88ad860..bdf02864 100644
--- a/adapt-config-json.sh
+++ b/adapt-config-json.sh
@@ -14,4 +14,5 @@ sed -i -e "s|__TRAFFIC_PREDICTION_API_BASE_URL__|$TRAFFIC_PREDICTION_API_BASE_UR
 sed -i -e "s|__BIKE_ANALYSIS_API_BASE_URL__|$BIKE_ANALYSIS_API_BASE_URL|g" $FILE
 sed -i -e "s|__IDRA_BASE_URL__|$IDRA_BASE_URL|g" $FILE
 sed -i -e "s|__DATALET_BASE_URL__|$DATALET_BASE_URL|g" $FILE
-sed -i -e "s|__TRAFFICSIMSERVER_API_BASE_URL__|$TRAFFICSIMSERVER_API_BASE_URL|g" $FILE
\ No newline at end of file
+sed -i -e "s|__TRAFFICSIMSERVER_API_BASE_URL__|$TRAFFICSIMSERVER_API_BASE_URL|g" $FILE
+sed -i -e "s|__DASHBOARD_CTRL_API_BASE_URL__|$DASHBOARD_CTRL_API_BASE_URL|g" $FILE
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
index 01611bfd..d1d7d230 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -2645,6 +2645,14 @@
         "schema-utils": "^2.7.0"
       }
     },
+    "@kolkov/angular-editor": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/@kolkov/angular-editor/-/angular-editor-1.2.0.tgz",
+      "integrity": "sha512-uAXsYxK62rOcgGJZdT3Q8iqJZ1k9BJchmg23+Iwy+oTtaqdzqkjl1Sgeka1uXQRWEUqFFxjxn7CpU8mNLCmeGQ==",
+      "requires": {
+        "tslib": "^2.0.0"
+      }
+    },
     "@mrmlnc/readdir-enhanced": {
       "version": "2.2.1",
       "resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz",
@@ -4989,6 +4997,14 @@
       "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz",
       "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU="
     },
+    "angular-gridster2": {
+      "version": "11.2.0",
+      "resolved": "https://registry.npmjs.org/angular-gridster2/-/angular-gridster2-11.2.0.tgz",
+      "integrity": "sha512-9+4Qt2/mPKAzGhhzp2Ag++WQbvr3Ry3dbfHG1XI596jpKh1ZtYvTLrh0Fn6jJEq248F1VN0xob9K9PzTH4P/2A==",
+      "requires": {
+        "tslib": "^2.0.0"
+      }
+    },
     "angular2-chartjs": {
       "version": "0.4.1",
       "resolved": "https://registry.npmjs.org/angular2-chartjs/-/angular2-chartjs-0.4.1.tgz",
@@ -11039,6 +11055,11 @@
       "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz",
       "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg="
     },
+    "hammerjs": {
+      "version": "2.0.8",
+      "resolved": "https://registry.npmjs.org/hammerjs/-/hammerjs-2.0.8.tgz",
+      "integrity": "sha1-BO93hiz/K7edMPdpIJWTAiK/YPE="
+    },
     "handle-thing": {
       "version": "2.0.1",
       "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz",
@@ -15377,6 +15398,21 @@
         }
       }
     },
+    "ngx-image-cropper": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/ngx-image-cropper/-/ngx-image-cropper-4.0.1.tgz",
+      "integrity": "sha512-Bl6VG7+dXQDfso5YAJ/9Dbq5Bt1xFsLM0fcyPcPyWt9qm40fofZGGP8Kg03d8/FdmdsoTbuLLHNh4r3YF2RtIw==",
+      "requires": {
+        "tslib": "^1.10.0"
+      },
+      "dependencies": {
+        "tslib": {
+          "version": "1.14.1",
+          "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
+          "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
+        }
+      }
+    },
     "ngx-markdown": {
       "version": "11.1.3",
       "resolved": "https://registry.npmjs.org/ngx-markdown/-/ngx-markdown-11.1.3.tgz",
@@ -19364,6 +19400,11 @@
       "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
       "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8="
     },
+    "resize-observer": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/resize-observer/-/resize-observer-1.0.2.tgz",
+      "integrity": "sha512-X0lHFNsxItpBRIRsdwOTkl/VguTaLGx7Gz9xoTGix9ObBN3jRYq9J/rSIuYDrey8AdU3IkfgIMpCeVSEW1QS0Q=="
+    },
     "resolve": {
       "version": "1.5.0",
       "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz",
diff --git a/package.json b/package.json
index bb29500a..e4e59323 100644
--- a/package.json
+++ b/package.json
@@ -62,6 +62,11 @@
     "@types/leaflet.markercluster": "^1.4.4",
     "@types/leaflet": "1.2.3",
     "@types/leaflet.heat": "0.2.0",
+    "angular-gridster2": "^11.2.0",
+    "@kolkov/angular-editor": "^1.2.0",
+    "hammerjs": "^2.0.8",
+    "ngx-image-cropper": "^4.0.1",
+    "resize-observer": "^1.0.2",
     "angular2-chartjs": "0.4.1",
     "apexcharts": "^3.27.1",
     "bootstrap": "4.3.1",
diff --git a/src/app/@theme/components/header/header.component.html b/src/app/@theme/components/header/header.component.html
index 4df83937..0d8d3384 100644
--- a/src/app/@theme/components/header/header.component.html
+++ b/src/app/@theme/components/header/header.component.html
@@ -25,13 +25,35 @@
       matRipple
       [matRippleUnbounded]="true"
       [matRippleCentered]="true">
-      <nb-user [nbContextMenu]="userMenu"
-               nbContextMenuTag="user-menu"
-               [onlyPicture]="userPictureOnly"
-               [name]="(user?.name!=undefined)?user?.name:user?.preferred_username"
-               [title]="user?.roles.join(' | ')"
-               [picture]="'assets/images/default_user.png'">
+
+      <!--
+      <nb-user  [nbContextMenu]="userMenu"
+                nbContextMenuTag="user-menu"
+                [onlyPicture]="userPictureOnly"
+                [name]="(user?.name!=undefined)?user?.name:user?.preferred_username"
+                [title]="user?.roles.join(' | ')" 
+                [picture]="'assets/images/default_user.png'">
+      </nb-user> 
+      -->
+      
+      <nb-user  *ngIf="user.roles!=undefined"
+                [nbContextMenu]="userMenu"
+                nbContextMenuTag="user-menu"
+                [onlyPicture]="userPictureOnly"
+                [name]="(user?.name!=undefined)?user?.name:user?.preferred_username"
+                [title]="user?.roles.join(' | ')" 
+                [picture]="'assets/images/default_user.png'">
       </nb-user>
+
+      <nb-user  *ngIf="user.realm_access!=undefined && user.realm_access.roles != undefined"
+                [nbContextMenu]="userMenu"
+                nbContextMenuTag="user-menu"
+                [onlyPicture]="userPictureOnly"
+                [name]="(user?.name!=undefined)?user?.name:user?.preferred_username"
+                [title]="user?.realm_access.roles.join(' | ')" 
+                [picture]="'assets/images/default_user.png'">
+      </nb-user>
+
     </nb-action>
   </nb-actions>
 </div>
diff --git a/src/app/app.component.ts b/src/app/app.component.ts
index 6d1ccf66..2063bef2 100644
--- a/src/app/app.component.ts
+++ b/src/app/app.component.ts
@@ -8,9 +8,10 @@ import { AnalyticsService } from './@core/utils/analytics.service';
 import { SeoService } from './@core/utils/seo.service';
 
 import { v4 as uuidv4 } from 'uuid';
-import { NbAuthJWTToken, NbAuthOAuth2JWTToken, NbAuthOAuth2Token, NbAuthService, NbAuthStrategy, NbOAuth2AuthStrategy, NbOAuth2ClientAuthMethod, NbOAuth2ResponseType } from '@nebular/auth';
+import { NbAuthJWTToken, NbAuthOAuth2JWTToken, NbAuthOAuth2Token, NbAuthService, NbAuthStrategy, NbOAuth2AuthStrategy, NbOAuth2ClientAuthMethod, NbOAuth2GrantType, NbOAuth2ResponseType } from '@nebular/auth';
 import { ConfigService } from '@ngx-config/core';
 import { OidcJWTToken } from './auth/oidc/oidc';
+import { TranslateService } from '@ngx-translate/core';
 
 @Component({
   selector: 'ngx-app',
@@ -19,11 +20,13 @@ import { OidcJWTToken } from './auth/oidc/oidc';
 export class AppComponent implements OnInit {
 
 
-  constructor(private analytics: AnalyticsService,
-     private seoService: SeoService,
-     private configService: ConfigService,
-    authService: NbAuthService, // force construction of the auth service
-    oauthStrategy: NbOAuth2AuthStrategy) {
+  constructor(
+      private analytics: AnalyticsService,
+      private seoService: SeoService,
+      private translate: TranslateService,
+      private configService: ConfigService,
+      authService: NbAuthService, // force construction of the auth service
+      oauthStrategy: NbOAuth2AuthStrategy) {
 
     oauthStrategy.setOptions({
       name: configService.getSettings("authProfile"),
@@ -49,14 +52,20 @@ export class AppComponent implements OnInit {
         failure: null, // stay on the same page
       },
       refresh: {
-        // endpoint: 'token',
-        // grantType: NbOAuth2GrantType.REFRESH_TOKEN,
+        endpoint: '/token',
+        grantType: NbOAuth2GrantType.REFRESH_TOKEN,
+        class: OidcJWTToken
       }
-    })
+    });
+
+    //MMA SET DEFAULT LANGUAGE
+    let defaultLanguage = configService.getSettings("defaultLanguage");
+    translate.setDefaultLang(defaultLanguage);
   }
 
   ngOnInit(): void {
     this.analytics.trackPageViews();
     this.seoService.trackCanonicalChanges();
   }
+  
 }
diff --git a/src/app/app.module.ts b/src/app/app.module.ts
index 1196dfff..e8d59942 100644
--- a/src/app/app.module.ts
+++ b/src/app/app.module.ts
@@ -3,95 +3,95 @@
  * Copyright Akveo. All Rights Reserved.
  * Licensed under the MIT License. See License.txt in the project root for license information.
  */
-import { BrowserModule } from '@angular/platform-browser';
-import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
-import { NgModule } from '@angular/core';
-import { HttpClientModule, HttpClient, HTTP_INTERCEPTORS } from '@angular/common/http';
-import { ConfigModule, ConfigLoader } from '@ngx-config/core';
-import { ConfigHttpLoader } from '@ngx-config/http-loader';
-import { TranslateHttpLoader } from "@ngx-translate/http-loader";
-import { CoreModule } from './@core/core.module';
-import { ThemeModule } from './@theme/theme.module';
-import { AppComponent } from './app.component';
-import { AppRoutingModule } from './app-routing.module';
-import {
-  NbDatepickerModule,
-  NbDialogModule,
-  NbMenuModule,
-  NbSidebarModule,
-  NbToastrModule,
-  NbWindowModule,
-  NbTimepickerModule,
-} from '@nebular/theme';
-import { TranslateModule, TranslateLoader } from '@ngx-translate/core';
-import { NbRoleProvider, NbSecurityModule } from '@nebular/security';
-import { TokenInterceptor } from './auth/services/token.interceptor';
-import { AuthGuard } from './auth/services/auth.guard';
-import { AuthLogoutComponent } from './auth/logout/auth-logout.component';
-import { MarkdownModule } from 'ngx-markdown';
+ import { BrowserModule } from '@angular/platform-browser';
+ import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
+ import { NgModule } from '@angular/core';
+ import { HttpClientModule, HttpClient, HTTP_INTERCEPTORS } from '@angular/common/http';
+ import { ConfigModule, ConfigLoader } from '@ngx-config/core';
+ import { ConfigHttpLoader } from '@ngx-config/http-loader';
+ import { TranslateHttpLoader } from "@ngx-translate/http-loader";
+ import { CoreModule } from './@core/core.module';
+ import { ThemeModule } from './@theme/theme.module';
+ import { AppComponent } from './app.component';
+ import { AppRoutingModule } from './app-routing.module';
+ import {
+   NbDatepickerModule,
+   NbDialogModule,
+   NbMenuModule,
+   NbSidebarModule,
+   NbToastrModule,
+   NbWindowModule,
+   NbTimepickerModule,
+ } from '@nebular/theme';
+ import { TranslateModule, TranslateLoader } from '@ngx-translate/core';
+ import { NbSecurityModule } from '@nebular/security';
+ import { TokenInterceptor } from './auth/services/token.interceptor';
+ import { AuthGuard } from './auth/services/auth.guard';
+ import { AuthLogoutComponent } from './auth/logout/auth-logout.component';
+ import { MarkdownModule } from 'ngx-markdown';
+ 
+ export function configFactory(http: HttpClient): ConfigLoader {
+   return new ConfigHttpLoader(http, './assets/config.json');
+ }
+ 
+ export function createTranslateLoader(http: HttpClient) {
+   return new TranslateHttpLoader(http, './assets/i18n/', '.json');
+ }
+ 
+ @NgModule({
+   declarations: [AppComponent, AuthLogoutComponent],
+   imports: [
+     BrowserModule,
+     BrowserAnimationsModule,
+     HttpClientModule,
+     AppRoutingModule,
+     NbSidebarModule.forRoot(),
+     NbMenuModule.forRoot(),
+     NbDatepickerModule.forRoot(),
+     NbTimepickerModule.forRoot(),
+     NbDialogModule.forRoot(),
+     NbWindowModule.forRoot(),
+     NbToastrModule.forRoot(),
+     CoreModule.forRoot(),
+     ThemeModule.forRoot(),
+     MarkdownModule.forRoot(),
+     ConfigModule.forRoot({
+       provide: ConfigLoader,
+       useFactory: configFactory,
+       deps: [HttpClient]
+     }),
+     TranslateModule.forRoot({
+       loader: {
+         provide: TranslateLoader,
+         useFactory: createTranslateLoader,
+         deps: [HttpClient],
+       },
+     }),
 
-
-export function configFactory(http: HttpClient): ConfigLoader {
-  return new ConfigHttpLoader(http, './assets/config.json');
-}
-
-export function createTranslateLoader(http: HttpClient) {
-  return new TranslateHttpLoader(http, './assets/i18n/', '.json');
-}
-
-@NgModule({
-  declarations: [AppComponent, AuthLogoutComponent],
-  imports: [
-    BrowserModule,
-    BrowserAnimationsModule,
-    HttpClientModule,
-    AppRoutingModule,
-    NbSidebarModule.forRoot(),
-    NbMenuModule.forRoot(),
-    NbDatepickerModule.forRoot(),
-    NbTimepickerModule.forRoot(),
-    NbDialogModule.forRoot(),
-    NbWindowModule.forRoot(),
-    NbToastrModule.forRoot(),
-    CoreModule.forRoot(),
-    ThemeModule.forRoot(),
-    MarkdownModule.forRoot(),
-    ConfigModule.forRoot({
-      provide: ConfigLoader,
-      useFactory: configFactory,
-      deps: [HttpClient]
-    }),
-    TranslateModule.forRoot({
-      loader: {
-        provide: TranslateLoader,
-        useFactory: createTranslateLoader,
-        deps: [HttpClient],
-      },
-    }),
-
-    NbSecurityModule.forRoot({
-      accessControl: {
-        ADMIN: {
-          view: '*'
-        },
-        MANAGER: {
-          view: ['external-app', 'maps', 'messina', 'home', 'about', 'charts', 'lorem-ipsum', 'simulation-wizard']
-        },
-        CITIZEN: {
-          view: ['home', 'about', 'ui-features','catalogues', 'simulation-wizard']
-        }
-      },
-    })
-  ],
-  providers: [
-    AuthGuard,
-    {
-      provide: HTTP_INTERCEPTORS,
-      useClass: TokenInterceptor,
-      multi: true
-    }
-  ],
-  bootstrap: [AppComponent],
-})
-export class AppModule {
-}
+     NbSecurityModule.forRoot({
+       accessControl: {
+         ADMIN: {
+           view: '*'
+         },
+         MANAGER: {
+           view: ['external-app', 'maps', 'messina', 'home', 'about', 'charts', 'catalogues', 'simulation-wizard', 'traffic simulation', 'tecnalia', 'dashboard-management']
+         },
+         CITIZEN: {
+           view: ['home', 'about', 'ui-features','catalogues', 'simulation-wizard', 'traffic simulation', 'tecnalia']
+         }
+       },
+     })
+   ],
+   providers: [
+     AuthGuard,
+     {
+       provide: HTTP_INTERCEPTORS,
+       useClass: TokenInterceptor,
+       multi: true
+     }
+   ],
+   bootstrap: [AppComponent],
+ })
+ export class AppModule {
+ }
+ 
\ No newline at end of file
diff --git a/src/app/auth/oidc/oidc.ts b/src/app/auth/oidc/oidc.ts
index 7598356c..570befbe 100644
--- a/src/app/auth/oidc/oidc.ts
+++ b/src/app/auth/oidc/oidc.ts
@@ -14,8 +14,12 @@ export interface UserClaims {
     sub: string;
     updated_at: string;
     roles: string[];
+    realm_access: RealmAccess;
 }
 
+export interface RealmAccess {
+    roles: string[];
+}
 
 export interface OidcToken {
     user: UserClaims;
diff --git a/src/app/auth/services/auth.guard.ts b/src/app/auth/services/auth.guard.ts
index 8fbe1f44..713728b4 100644
--- a/src/app/auth/services/auth.guard.ts
+++ b/src/app/auth/services/auth.guard.ts
@@ -18,7 +18,8 @@ export class AuthGuard implements CanActivate {
     if (!this.configService.getSettings('enableAuthentication')) {
       return true;
     } else {
-      return this.authService.isAuthenticated()
+      //return this.authService.isAuthenticated()
+      return this.authService.isAuthenticatedOrRefresh()
         .pipe(
           tap(authenticated => {
             if (!authenticated) {
diff --git a/src/app/auth/services/oidc-user-information.service.ts b/src/app/auth/services/oidc-user-information.service.ts
index 53a1f8c7..d530159b 100644
--- a/src/app/auth/services/oidc-user-information.service.ts
+++ b/src/app/auth/services/oidc-user-information.service.ts
@@ -29,14 +29,25 @@ export class OidcUserInformationService {
   }
 
   getRole(): Observable<string[]> {
-    return this.user ? observableOf(this.user.roles.map(role => role.toUpperCase())) : observableOf(['CITIZEN']);
+    //console.log("## DEMO GetRole, this.user =>" + this.user);
+    //return observableOf(['ADMIN']);
+    //return this.user ? observableOf(this.user.roles.map(role => role.toUpperCase())) : observableOf(['CITIZEN']);
+    return this.user 
+    ? (
+        this.user.roles != undefined 
+        ? observableOf(this.user.roles.map(role => role.toUpperCase())) 
+        : (this.user.realm_access != undefined && this.user.realm_access.roles != undefined 
+              ? observableOf(this.user.realm_access.roles.map(role => role.toUpperCase())) 
+              : observableOf(['CITIZEN']) 
+          )  
+      ) 
+    : observableOf(['CITIZEN']);
   }
 
   getUser(): Observable<UserClaims> {
     return observableOf(this.user);
   }
 
-
   private publishUser(user: any) {
     this.user$.next(user)
   }
diff --git a/src/app/auth/services/token.interceptor.ts b/src/app/auth/services/token.interceptor.ts
index ae1ddb56..c9afc416 100644
--- a/src/app/auth/services/token.interceptor.ts
+++ b/src/app/auth/services/token.interceptor.ts
@@ -8,6 +8,7 @@ import {
 import { Observable } from 'rxjs';
 import { NbAuthOAuth2JWTToken, NbAuthOAuth2Token, NbAuthService } from '@nebular/auth';
 import { ConfigService } from '@ngx-config/core';
+import { switchMap, tap } from 'rxjs/operators';
 
 @Injectable()
 export class TokenInterceptor implements HttpInterceptor {
@@ -31,14 +32,26 @@ export class TokenInterceptor implements HttpInterceptor {
     
     let newHeaders = req.headers;
     
-    if(this.config.getSettings('enableAuthentication')){
-      this.auth.getToken().subscribe((x: NbAuthOAuth2JWTToken) => this.token = x);
-      if (this.token.getPayload() != null) {
-        newHeaders = newHeaders.append('Authorization', 'Bearer ' + this.token.getPayload().access_token);
-      }
+    if(this.config.getSettings('enableAuthentication')) {
+      return this.auth.isAuthenticatedOrRefresh().pipe(
+        tap(authenticated=>{
+          // console.log("tap authenticated => "+authenticated);
+        }),
+  
+        switchMap((authenticated)=>{
+          this.auth.getToken().subscribe((x: NbAuthOAuth2JWTToken) => this.token = x);
+          let newHeaders = req.headers;
+          if (this.token.getPayload() != null) {
+            newHeaders = newHeaders.append('Authorization', 'Bearer ' + this.token.getPayload().access_token);
+          }
+          const authReq = req.clone({ headers: newHeaders });
+          return next.handle(authReq);
+        })
+      ) 
+    } else {
+      const authReq = req.clone({ headers: newHeaders });
+      return next.handle(authReq);
     }
 
-    const authReq = req.clone({ headers: newHeaders });
-    return next.handle(authReq);
   }
 }
diff --git a/src/app/pages/data-catalogue/datalet-iframe/datalet-iframe.component.html b/src/app/pages/data-catalogue/datalet-iframe/datalet-iframe.component.html
index 2309c568..57600b9b 100644
--- a/src/app/pages/data-catalogue/datalet-iframe/datalet-iframe.component.html
+++ b/src/app/pages/data-catalogue/datalet-iframe/datalet-iframe.component.html
@@ -1,5 +1,5 @@
 <nb-card>
     <nb-card-body>
-            <iframe class="responsive-iframe" frameBorder="0" [src]="iframeUrl | safe"></iframe>
+        <iframe class="responsive-iframe" frameBorder="0" [src]="iframeUrl | safe"></iframe>
     </nb-card-body>
 </nb-card>
\ No newline at end of file
diff --git a/src/app/pages/data-catalogue/dataset/dataset.component.ts b/src/app/pages/data-catalogue/dataset/dataset.component.ts
index f0c0e86a..384e209c 100644
--- a/src/app/pages/data-catalogue/dataset/dataset.component.ts
+++ b/src/app/pages/data-catalogue/dataset/dataset.component.ts
@@ -199,6 +199,7 @@ export class DatasetComponent implements OnInit {
   }
 
   openExistingDatalet(distribution:DCATDistribution){
+        
     this.dialogService.open(ShowDataletsComponent, {
       context: {
         distributionID: distribution.id,
diff --git a/src/app/pages/data-catalogue/services/data-cataglogue-api.service.ts b/src/app/pages/data-catalogue/services/data-cataglogue-api.service.ts
index 58912ffe..2610f531 100644
--- a/src/app/pages/data-catalogue/services/data-cataglogue-api.service.ts
+++ b/src/app/pages/data-catalogue/services/data-cataglogue-api.service.ts
@@ -16,7 +16,6 @@ import { SearchResult } from '../model/search-result';
   providedIn: 'root'
 })
 export class DataCataglogueAPIService {
-
   private apiEndpoint;
 
   constructor(private config:ConfigService,private http:HttpClient) { 
diff --git a/src/app/pages/home/home.component.html b/src/app/pages/home/home.component.html
index 7e39c846..6e956ae0 100644
--- a/src/app/pages/home/home.component.html
+++ b/src/app/pages/home/home.component.html
@@ -78,19 +78,132 @@
 
 
     <div *ngSwitchCase="'MESSINA'">
-        {{pilotName}}
+        <section class="jumbotron text-center">
+            <div class="container">
+                <h1 class="jumbotron-heading">Urbanite Project</h1>
+                <p class="lead text-muted">
+                    <i><b>A platform that will assist with decision-making in urban transportation and transformation.</b></i>
+                </p>
+                <p class="lead text-muted">
+                    In recent years, with the population and size of cities increasing exponentially, transportation has
+                    become even more important. The need for more efficient mobility solutions has been met with a variety of
+                    new concepts like sharing vehicles, electric scooters for rent, and even disruptive start-ups like Uber
+                    or Cabify, which are causing a stir with previously used models. However, such new models are putting
+                    public administrations in a challenging situation. The EU-funded URBANITE project aims to develop a
+                    solution that collects and analyses data, that combined with AI, can assist public administrations in
+                    policy-related decisions concerning urban transformation caused by these new transportation and business models.
+                    URBANITE focuses also on social aspects, by analyzing stakeholders’ trust in technologies aiding decision-making.
+                </p>
+
+                <nb-card>
+                    <nb-card-header>{{pilotName}}</nb-card-header>
+                    <nb-card-body>
+                        <img class="img-fluid" src="/assets/images/messina_07.png" alt="Photo of Messina">
+                    </nb-card-body>
+                    <nb-card-footer class="d-flex justify-content-center">
+                        <nb-icon icon="info" status="info" nbTooltip="Details" (click)="openDialog('MESSINA')"></nb-icon>
+                    </nb-card-footer>
+                </nb-card>
+
+            </div>
+        </section>
     </div>
 
     <div *ngSwitchCase="'BILBAO'">
-        {{pilotName}}
+        <section class="jumbotron text-center">
+            <div class="container">
+                <h1 class="jumbotron-heading">Urbanite Project</h1>
+                <p class="lead text-muted">
+                    <i><b>A platform that will assist with decision-making in urban transportation and transformation.</b></i>
+                </p>
+                <p class="lead text-muted">
+                    In recent years, with the population and size of cities increasing exponentially, transportation has
+                    become even more important. The need for more efficient mobility solutions has been met with a variety of
+                    new concepts like sharing vehicles, electric scooters for rent, and even disruptive start-ups like Uber
+                    or Cabify, which are causing a stir with previously used models. However, such new models are putting
+                    public administrations in a challenging situation. The EU-funded URBANITE project aims to develop a
+                    solution that collects and analyses data, that combined with AI, can assist public administrations in
+                    policy-related decisions concerning urban transformation caused by these new transportation and business models.
+                    URBANITE focuses also on social aspects, by analyzing stakeholders’ trust in technologies aiding decision-making.
+                </p>
+
+                <nb-card>
+                    <nb-card-header>{{pilotName}}</nb-card-header>
+                    <nb-card-body>
+                        <img class="img-fluid" src="/assets/images/bilbao_02.jpeg" alt="Photo of Bilbao">
+                    </nb-card-body>
+                    <nb-card-footer class="d-flex justify-content-center">
+                        <nb-icon icon="info" status="info" nbTooltip="Details" (click)="openDialog('BILBAO')"></nb-icon>
+                    </nb-card-footer>
+                </nb-card>
+
+            </div>
+        </section>
     </div>
 
     <div *ngSwitchCase="'HELSINKI'">
-        {{pilotName}}
+        <section class="jumbotron text-center">
+            <div class="container">
+                <h1 class="jumbotron-heading">Urbanite Project</h1>
+                <p class="lead text-muted">
+                    <i><b>A platform that will assist with decision-making in urban transportation and transformation.</b></i>
+                </p>
+                <p class="lead text-muted">
+                    In recent years, with the population and size of cities increasing exponentially, transportation has
+                    become even more important. The need for more efficient mobility solutions has been met with a variety of
+                    new concepts like sharing vehicles, electric scooters for rent, and even disruptive start-ups like Uber
+                    or Cabify, which are causing a stir with previously used models. However, such new models are putting
+                    public administrations in a challenging situation. The EU-funded URBANITE project aims to develop a
+                    solution that collects and analyses data, that combined with AI, can assist public administrations in
+                    policy-related decisions concerning urban transformation caused by these new transportation and business models.
+                    URBANITE focuses also on social aspects, by analyzing stakeholders’ trust in technologies aiding decision-making.
+                </p>
+
+                <nb-card>
+                    <nb-card-header>{{pilotName}}</nb-card-header>
+                    <nb-card-body>
+                        <img class="img-fluid" src="/assets/images/helsinki_06.jpg" alt="Photo of Helsinki">
+                    </nb-card-body>
+                    <nb-card-footer class="d-flex justify-content-center">
+                        <nb-icon icon="info" status="info" nbTooltip="Details" (click)="openDialog('HELSINKI')"></nb-icon>
+                    </nb-card-footer>
+                </nb-card>
+
+            </div>
+        </section>
     </div>
 
-    <div *ngSwitchCase="'AMSTERDAM'">
-        {{pilotName}}
+   <div *ngSwitchCase="'AMSTERDAM'">
+     <section class="jumbotron text-center">
+            <div class="container">
+                <h1 class="jumbotron-heading">Urbanite Project</h1>
+                <p class="lead text-muted">
+                    <i><b>A platform that will assist with decision-making in urban transportation and transformation.</b></i>
+                </p>
+                <p class="lead text-muted">
+                    In recent years, with the population and size of cities increasing exponentially, transportation has
+                    become even more important. The need for more efficient mobility solutions has been met with a variety of
+                    new concepts like sharing vehicles, electric scooters for rent, and even disruptive start-ups like Uber
+                    or Cabify, which are causing a stir with previously used models. However, such new models are putting
+                    public administrations in a challenging situation. The EU-funded URBANITE project aims to develop a
+                    solution that collects and analyses data, that combined with AI, can assist public administrations in
+                    policy-related decisions concerning urban transformation caused by these new transportation and business models.
+                    URBANITE focuses also on social aspects, by analyzing stakeholders’ trust in technologies aiding decision-making.
+                </p>
+
+                <nb-card> 
+                    <nb-card-header>{{pilotName}}</nb-card-header>
+                    <nb-card-body>
+                        <img class="img-fluid" src="/assets/images/am3.jpg" alt="Photo of Amsterdam">
+                    </nb-card-body>
+                    <nb-card-footer class="d-flex justify-content-center">
+                        <nb-icon icon="info" status="info" nbTooltip="Details" (click)="openDialog('AMSTERDAM')"></nb-icon>
+                    </nb-card-footer>
+                </nb-card>
+
+            </div>
+        </section> 
+
     </div>
 
 </div>
diff --git a/src/app/pages/pages-menu.ts b/src/app/pages/pages-menu.ts
index 6a8554e0..a1715330 100644
--- a/src/app/pages/pages-menu.ts
+++ b/src/app/pages/pages-menu.ts
@@ -99,6 +99,34 @@ export const MENU_ITEMS: NbMenuItem[] = [
       }
     ],
   },
+
+  {
+    title: 'Dashboard Section',
+    icon: 'color-palette-outline',
+    data:{
+      name:"dashboard-management"
+    },
+    children: [
+      {
+        title: 'Manage Dashboard Pages',
+        link: '/pages/dashboard-management/manage-dashboard-pages',
+      },
+      {
+        title: 'Manage Menu Blocks',
+        link: '/pages/dashboard-management/manage-menu-blocks',
+      },
+      {
+        title: 'Clone Dashboard',
+        link: '/pages/dashboard-management/dashboard-clone-wizard',
+      }
+      /*,
+      {
+        title: 'Manage Dashboard Target',
+        link: '/pages/dashboard-management/manage-dashboard-target',
+      }*/
+    ],
+  },
+
   {
     title: 'Maps',
     icon: 'map-outline',
diff --git a/src/app/pages/pages-routing.module.ts b/src/app/pages/pages-routing.module.ts
index b4878a97..a79a0cd2 100644
--- a/src/app/pages/pages-routing.module.ts
+++ b/src/app/pages/pages-routing.module.ts
@@ -43,6 +43,13 @@ const routes: Routes = [{
       loadChildren: () => import('./messina/messina.module')
         .then(m => m.MessinaModule),
     },
+
+    {
+      path: 'dashboard-management',
+      loadChildren: () => import('./dashboard-management/dashboard-management.module')
+        .then(m => m.DashboardManagementModule),
+    },
+
     {
       path: 'charts',
       loadChildren: () => import('./charts/charts.module')
diff --git a/src/app/pages/pages.component.ts b/src/app/pages/pages.component.ts
index 8c5d6072..524d862a 100644
--- a/src/app/pages/pages.component.ts
+++ b/src/app/pages/pages.component.ts
@@ -2,6 +2,9 @@ import { Component, OnInit } from '@angular/core';
 import { NbAccessChecker } from '@nebular/security';
 import { NbMenuItem } from '@nebular/theme';
 import { ConfigService } from '@ngx-config/core';
+import { IMenuBlock } from '../model/menu-block.model';
+import { MenuBlockCrudService } from './dashboard-management/services/menu-block-crud.service';
+import { MenuMapperService } from './dashboard-management/services/menu-mapper.service';
 import { MENU_ITEMS } from './pages-menu';
 
 @Component({
@@ -15,15 +18,18 @@ import { MENU_ITEMS } from './pages-menu';
   `,
 })
 export class PagesComponent implements OnInit {
-
   menu = MENU_ITEMS;
   userRoles: string[];
   demoEnabled=false;
   extPages=[];
   default_pilot="URBANITE";
+
   constructor(
     private accessChecker: NbAccessChecker,
-    private configService: ConfigService) {
+    private configService: ConfigService,
+    private menuBlockService: MenuBlockCrudService,
+    private menuMapperService: MenuMapperService
+    ) {
   }
 
   ngOnInit() {
@@ -44,9 +50,34 @@ export class PagesComponent implements OnInit {
       }
     })
 
-    //if (this.configService.getSettings('enableAuthentication')) {
+    /** JMA - Add SHARED Menu to the Dashboard */
+    this.menuBlockService.getAllShared().subscribe((response: Array<IMenuBlock>) => {
+      // console.log('block response: ', JSON.stringify(response));
+      if (response !== undefined  && response !== null){
+        try{
+          this.menu = this.menu.concat(response.map(item => this.menuMapperService.mapBlockToNbMenuItem(item))) ;
+        } catch(e) {
+          console.log("# Error in menu content loading due to " + e);
+        }
+      }
+      // console.log("# Menu SHARED => "+this.menu);
+    });
+
+    /** JMA -  Add PERSONAL Menu to the Dashboard */
+     this.menuBlockService.getAllPersonal().subscribe((response: Array<IMenuBlock>) => {
+      // console.log('block response: ', JSON.stringify(response));
+      if (response !== undefined  && response !== null){
+        try{
+          this.menu = this.menu.concat(response.map(item => this.menuMapperService.mapBlockToNbMenuItem(item))) ;
+        } catch(e) {
+          console.log("# Error in menu content loading due to " + e);
+        }
+      }
+      // console.log("# Menu PESONAL => "+this.menu);
+    });
+
+
     this.authMenuItems();
-    //}
   }
 
   authMenuItems() {
@@ -76,10 +107,11 @@ export class PagesComponent implements OnInit {
     }
 
     /**
-     * MMA - This is useful to enable a specific menuItem only for a specific Pilot.
+     * MMA - Useful to enable a specific menuItem only for a specific Pilot. 
+     * NOTE: "URBANITE" is visible for all pilots
      */
     if(menuItem.data && menuItem.data['pilot']!=undefined){
-      menuItem.hidden = !(menuItem.data['pilot']==this.default_pilot);
+      menuItem.hidden = menuItem.data['pilot'] != this.default_pilot && this.default_pilot != 'URBANITE';
     }
 
     if (!menuItem.hidden && menuItem.children != null) {
@@ -88,4 +120,5 @@ export class PagesComponent implements OnInit {
       });
     }
   }
+
 }
diff --git a/src/app/pages/pages.module.ts b/src/app/pages/pages.module.ts
index ea319597..89b8fc17 100644
--- a/src/app/pages/pages.module.ts
+++ b/src/app/pages/pages.module.ts
@@ -1,10 +1,11 @@
 import { NgModule } from '@angular/core';
 import { NbMenuModule, NbDatepickerModule } from '@nebular/theme';
-
 import { ThemeModule } from '../@theme/theme.module';
 import { PagesComponent } from './pages.component';
 import { PagesRoutingModule } from './pages-routing.module';
 import { MiscellaneousModule } from './miscellaneous/miscellaneous.module';
+import { SharedModule } from './shared/shared.module';
+import { TranslateModule } from '@ngx-translate/core';
 
 
 @NgModule({
@@ -12,7 +13,9 @@ import { MiscellaneousModule } from './miscellaneous/miscellaneous.module';
     PagesRoutingModule,
     ThemeModule,
     NbMenuModule,
+    SharedModule,
     MiscellaneousModule,
+    TranslateModule,
   ],
   declarations: [
     PagesComponent
diff --git a/src/assets/config-template.json b/src/assets/config-template.json
index c047874f..ea37dcf0 100644
--- a/src/assets/config-template.json
+++ b/src/assets/config-template.json
@@ -1,4 +1,5 @@
 {   
+    "defaultLanguage":"en",
     "dashboardBaseURL":"__DASHBOARD_BASE_URL__",
     "enableAuthentication":true,
     "authProfile": "oidc",
@@ -30,6 +31,12 @@
         "api_base_url":"https://urbanite-node1.comune.messina.it",
         "token":"mcOUnnIyupQJzbitPX7Q2MnyqrVQUkmo"
     },
+    "dashboard-controller":{
+        "api_base_url":"__DASHBOARD_CTRL_API_BASE_URL__",
+        "useIDM4Target":true,
+        "enable_delay":true,
+        "delay": 1400
+    },
     "jsi":{
         "traffic_sim_server":"__TRAFFICSIMSERVER_API_BASE_URL__"
     }
diff --git a/src/assets/config.json b/src/assets/config.json
index e78bb740..3c8d8101 100644
--- a/src/assets/config.json
+++ b/src/assets/config.json
@@ -1,4 +1,5 @@
 {   
+    "defaultLanguage":"en",
     "dashboardBaseURL":"http://localhost:4200",
     "enableAuthentication":true,
     "authProfile": "oidc",
@@ -30,6 +31,12 @@
         "api_base_url":"https://urbanite-node1.comune.messina.it",
         "token":"mcOUnnIyupQJzbitPX7Q2MnyqrVQUkmo"
     },
+    "dashboard-controller":{
+        "api_base_url":"http://localhost:8085",
+        "useIDM4Target":true,
+        "enable_delay":true,
+        "delay": 1400
+    },
     "jsi":{
         "traffic_sim_server":"http://localhost:8081"
     }
diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json
index e69de29b..07e3a146 100644
--- a/src/assets/i18n/en.json
+++ b/src/assets/i18n/en.json
@@ -0,0 +1,242 @@
+{
+    "homepage": {
+        "homepage": "Homepage",
+        "welcome": "Welcome "
+    },
+    "general": {
+        "success": "Success",
+        "error": "Error",
+        "warning": "Warning",
+        "copy": "Copy",
+        "manage": "Manage",
+        "add": "Add",
+        "save": "Save",
+        "back": "Back",
+        "cancel": "Cancel",
+        "edit": "Edit",
+        "drag": "Drag",
+        "delete": "Delete",
+        "created": "created",
+        "updated": "updated",
+        "reset": "Ripristina",
+        "actions": "Actions",
+        "close": "Close",
+        "username": "Username",
+        "log_in": "Login",
+        "log_out": "Logout",
+        "page": "Page",
+        "dashboard": "Dashboard",
+        "component": "Component",
+        "targets": "Targets",
+        "menu_items": "Menu Items",
+        "menu_blocks": "Menu Blocks",
+        "manage_targets": "Manage Targets",
+        "editContent":"Edit Content",
+        "deleteConfirm": "Do you want delete the selected item?",
+        "yes": "Yes",
+        "no": "No",
+        "mandatory_field": "Mandatory field",
+        "catch_error": "Error loading the results, please try again.",
+        "operation_failed": "Operation failed",
+        "datacatalogue_error": "Error in retrieving data from Data Catalogue. Please contact admin"
+    },
+    "dashboardPage":{
+        "title": "Manage Dashboard Pages",
+        "created": "A new Dashboard Page has been succesfully created",
+        "updated": "The Dashboard Page has been succesfully updated",
+        "deleted": "The Dashboard Page has been deleted",
+        "succesfully_cloned": "The Dashboard Page has been sucessfully cloned",
+        "notFound": "No Dashboard Pages found",
+        "createLabel": "Create a new Dashboard Page",
+        "createOrEditLabel": "Create or edit a Dashboard Page",
+        "id": "ID",
+        "name": "Name",
+        "description": "Description",
+        "content": "Content",
+        "note": "Note",
+        "shared": "Published",
+        "createdDate": "Created Date",
+        "createdBy": "Created By",
+        "dashboardComponent": "Dashboard Component",
+        "menuItem": "Menu Item",
+        "target": "Target",
+        "margin": "Margin",
+        "drag_items": "Drag items",
+        "outer_margin": "Outer Margin",
+        "push_items": "Push Items",
+        "disable_push_on_drag": "Disable Push On Drag",
+        "swap_items": "Swap Items",
+        "shared_info": "Field to enable(true) or disable(false) the Dashboard publishing.",
+        "margin_description": "Spacing between the components",
+        "outer_margin_description": "Spacing around the components",
+        "push_items_description": "Push items when resizing and dragging",
+        "disable_push_on_drag_description": "Disable push on drag",
+        "swap_items_description": "Swap items when dragging",
+        "not_mandatory_field": "This field in only for SHARED Dashboard",
+        "checkbox_label":"Flags",
+        "margin_label":"Margin",
+        "back_modal": "Are you sure you want to go back without saving the dashboard?",
+        "catch_error": "Error loading the dashboard page, please try again.",
+        "wait_for_components": "Please wait for components to load.",
+        "visualization_catch_error": "Error in Dashboard page content during visualization. Please contact admin o try again."
+    },
+    "dashboardComponent": {
+        "list": "Dashboard Components",
+        "title": "Dashboard Component",
+        "id": "ID",
+        "componentType": "Component Type",
+        "componentName": "Component Name",
+        "componentcontent": "Componentcontent",
+        "componentPosition": "Component Position",
+        "choose_file": "Choose file",
+        "createdDate": "Created Date",
+        "createdBy": "Created By",
+        "dashboardPage": "Dashboard Page",
+        "properties":"Component properties",
+        "selectComponentType":"Select a component type",
+        "deleteConfirm":"Are you sure to delete component?",
+        "fill_text": "Enter text...",
+        "fill_image": "Paste image url or base 64 image string...",
+        "fill_chart": "Select datalet...",
+        "fill_iframe": "Enter iframe content...",
+        "fill_map": "Enter GeoJson URL of the map...",
+        "fill_map_title": "Enter Title",
+        "fill_weather_title": "Enter Title",
+        "fill_weather_subtitle": "Enter Subtitle",
+        "fill_statistics_title": "Enter Title",
+        "fill_statistics_subtitle": "Enter Subtitle",
+        "fill_statistics_value": "Enter Value",
+        "fill_statistics_icon": "Enter Icon",
+        "select_datalet": "Select a datalet...",
+        "select_aspect_ratio": "Select aspect ratio",
+        "example_map_url": "http://localhost:4200/assets/map/2020-March-heatgeo-5minutes.json",
+        "label_geoJsonurl": "GeoJSON URL",
+        "label_title": "Title",
+        "label_subtitle": "Subtitle",
+        "label_value": "Value",
+        "label_icon": "Icon",
+        "label_content": "Content",
+        "label_datalet": "Datalet",
+        "label_image_url": "Image URL",
+        "label_upload_image": "Upload Image",
+        "upload_from_file": "Upload from file",
+        "upload_from_url/base64": "Upload from url/base64",
+        "catch_error": "Error loading the dashboard component, please try again."
+    },
+    "target": {
+        "list": "Targets",
+        "title": "Target",
+        "notFound": "No Targets found",
+        "createLabel": "Create a new Target",
+        "createOrEditLabel": "Create or edit a Target",
+        "created": "Target has been succesfully created",
+        "updated": "Target has been succesfully updated",
+        "deleted": "Target has been succesfully deleted",
+        "deleteConfirm": "Are you sure you want to delete Target ?",
+        "id": "ID",
+        "type": "Type",
+        "name": "Name",
+        "note": "Note",
+        "value": "Value",
+        "fill_person":"Select person first!",
+        "fill_group":"Select group first!",
+        "fill_role":"Select role first!",
+        "createdDate": "Created Date",
+        "createdBy": "Created By",
+        "dashboardPage": "Dashboard Page",
+        "select_person":"Select Available Person",
+        "select_group":"Select Available Group",
+        "select_role":"Select Available Role",
+        "add_button_info": "Select a Person and/or a Role to share with him the Dashboard",
+        "add_button_info_disabled": "Disabled Section. To enable 'Targets' the Dashboard have to be of type SHARED"
+    },
+    "menuBlock": {
+        "list": "Menu Blocks",
+        "title": "Menu Block",
+        "created": "Menu Block has been succesfully created",
+        "updated": "Menu Block has been succesfully updated",
+        "deleted": "Menu Block has been succesfully deleted",
+        "deleteConfirm": "Are you sure you want to delete Menu Block?",
+        "id": "ID",
+        "code": "Code",
+        "label": "Label",
+        "order": "Order",
+        "type": "Type",
+        "createdDate": "Created Date",
+        "createdBy": "Created By",
+        "menuItem": "Menu Item",
+        "select_menu_block":"Select a menu block",
+        "select_menu_block_info": "Selecting a SHARED block the Dashboard will be of type SHARED, otherwise the Dashboard will be of type PERSONAL.",
+        "shared": "Shared",
+        "delete_fk_error": "Delete failed cause this menu block is linked to more menu items.",
+        "type_info": "SHARED is for sharing the menu and the dashboard linked, PERSONAL is only for private visibility (not sharing)."
+    },
+    "menuItem": {
+        "list": "Menu Items",
+        "title": "Menu Item",
+        "created": "Menu Item has been succesfully created",
+        "updated": "Menu Item has been succesfully updated",
+        "deleted": "Menu Item has been succesfully deleted",
+        "deleteConfirm": "Are you sure you want to delete Menu Item?",
+        "id": "ID",
+        "code": "Code",
+        "label": "Label",
+        "order": "Order",
+        "type": "Type",
+        "createdDate": "Created Date",
+        "createdBy": "Created By",
+        "dashboardPage": "Dashboard Page",
+        "menuBlock": "Menu Block",
+        "menu_item_label":"Menu Item label",
+        "add_menu_item_label": "Add the label of MenuItem",
+        "add_button_info": "Select a menu block and then write the menu item label to add a link to the Dashboard",
+        "copy_info": "Copy the Dashboard name into menu item label (to generate the link Name)"
+    },
+    "dashboardClone":{
+        "step_one": "First step",
+        "step_two": "Second step",
+        "step_three": "Third step",
+        "question_one": "Which Dashboard do you want to clone?",
+        "question_two": "Which Dashboard want to create?",
+        "question_three": "Do you want to proceed with cloning?",
+        "question_targets": "Do you want to clone targets?",
+        "action_clone": "Clone",
+        "action_prev": "Prev",
+        "action_next": "Next",
+        "action_preview": "Preview",
+        "clone_targets": "Clone the targets",
+        "summary_one": "Selected dashboard name:",
+        "summary_two": "Created dashboard name:",
+        "summary_three": "Created dashboard targets:",
+        "select_dashboard": "Select a dashboard",
+        "add_dashboard_name":"Dashboard name",
+        "info": "Click on the Preview button to visualize it",
+        "source_dashboard": "Source Dashboard",
+        "parameter_error": "Error: missing 1 or more parameters",
+        "cloned_dashboard_name": "Cloned Dashboard name",
+        "clone_missing_parameter": "Clone Missing Parameters"
+    },
+    "ComponentType": {
+        "null": "",
+        "TEXT": "TEXT",
+        "IMAGE": "IMAGE",
+        "CHART": "CHART",
+        "IFRAME": "IFRAME",
+        "STATISTICS": "SUMMARY",
+        "MAP": "MAP",
+        "WEATHER": "WEATHER EXAMPLE"
+      },
+    "MenuType": {
+        "null": "",
+        "SHARED": "SHARED",
+        "PERSONAL": "PERSONAL",
+        "OTHER": "EMPTY TYPE"
+    },
+    "TargetType": {
+        "null": "",
+        "PERSON": "PERSON",
+        "GROUP": "GROUP",
+        "ROLE": "ROLE"
+    }
+
+}
\ No newline at end of file
diff --git a/src/polyfills.ts b/src/polyfills.ts
index 4ed2f714..1505190e 100644
--- a/src/polyfills.ts
+++ b/src/polyfills.ts
@@ -55,3 +55,5 @@ import 'core-js/es7/object';
 if (typeof SVGElement.prototype.contains === 'undefined') {
   SVGElement.prototype.contains = HTMLDivElement.prototype.contains;
 }
+
+import 'hammerjs/hammer';
-- 
GitLab