Преглед на файлове

connection to api, added components

onunez преди 6 години
родител
ревизия
71da161b02
променени са 100 файла, в които са добавени 2351 реда и са изтрити 774 реда
  1. 8 3
      package-lock.json
  2. 1 0
      package.json
  3. 11 6
      src/app/app.component.ts
  4. 11 9
      src/app/app.module.ts
  5. 6 7
      src/app/app.routing.ts
  6. 166 0
      src/app/components/assets/assets.component.html
  7. 145 0
      src/app/components/assets/assets.component.scss
  8. 6 6
      src/app/components/assets/assets.component.spec.ts
  9. 422 0
      src/app/components/assets/assets.component.ts
  10. 67 146
      src/app/components/dashboard/dashboard.component.html
  11. 19 60
      src/app/components/dashboard/dashboard.component.scss
  12. 135 7
      src/app/components/dashboard/dashboard.component.ts
  13. 15 12
      src/app/components/login/login.component.html
  14. 3 3
      src/app/components/login/login.component.scss
  15. 72 49
      src/app/components/login/login.component.ts
  16. 11 0
      src/app/components/plugins/bar-chart/bar-chart.component.html
  17. 0 0
      src/app/components/plugins/bar-chart/bar-chart.component.scss
  18. 25 0
      src/app/components/plugins/bar-chart/bar-chart.component.spec.ts
  19. 53 0
      src/app/components/plugins/bar-chart/bar-chart.component.ts
  20. 1 0
      src/app/components/plugins/doughnut-chart/doughnut-chart.component.html
  21. 0 0
      src/app/components/plugins/doughnut-chart/doughnut-chart.component.scss
  22. 25 0
      src/app/components/plugins/doughnut-chart/doughnut-chart.component.spec.ts
  23. 15 0
      src/app/components/plugins/doughnut-chart/doughnut-chart.component.ts
  24. 10 16
      src/app/components/plugins/maps/maps.component.html
  25. 5 5
      src/app/components/plugins/maps/maps.component.ts
  26. 32 0
      src/app/components/plugins/organization-cards/organization-cards.component.html
  27. 4 0
      src/app/components/plugins/organization-cards/organization-cards.component.scss
  28. 25 0
      src/app/components/plugins/organization-cards/organization-cards.component.spec.ts
  29. 35 0
      src/app/components/plugins/organization-cards/organization-cards.component.ts
  30. 0 12
      src/app/components/plugins/plant-detail/plant-detail.component.html
  31. 0 10
      src/app/components/plugins/plant-detail/plant-detail.component.scss
  32. 0 29
      src/app/components/plugins/plant-detail/plant-detail.component.ts
  33. 19 4
      src/app/components/plugins/plugins.module.ts
  34. 10 0
      src/app/components/plugins/polar-chart/polar-chart.component.html
  35. 0 0
      src/app/components/plugins/polar-chart/polar-chart.component.scss
  36. 25 0
      src/app/components/plugins/polar-chart/polar-chart.component.spec.ts
  37. 53 0
      src/app/components/plugins/polar-chart/polar-chart.component.ts
  38. 6 6
      src/app/components/plugins/weather-card/weather-card.component.html
  39. 14 4
      src/app/components/plugins/weather-card/weather-card.component.scss
  40. 13 13
      src/app/components/plugins/weather-card/weather-card.component.ts
  41. 1 1
      src/app/components/profile/profile.component.html
  42. 2 2
      src/app/components/shared/navbar/navbar.component.html
  43. 25 10
      src/app/components/shared/navbar/navbar.component.ts
  44. 8 6
      src/app/components/shared/sidebar/sidebar.component.html
  45. 13 1
      src/app/components/shared/sidebar/sidebar.component.ts
  46. 119 85
      src/app/data/plants.data.ts
  47. 0 31
      src/app/helpers/auth.guard.ts
  48. 0 24
      src/app/helpers/error.interceptor.ts
  49. 0 112
      src/app/helpers/fake-backend.ts
  50. 0 4
      src/app/helpers/index.ts
  51. 0 27
      src/app/helpers/jwt.interceptor.ts
  52. 21 2
      src/app/layouts/admin/admin.module.ts
  53. 7 1
      src/app/layouts/admin/admin.routing.ts
  54. 1 0
      src/app/models/index.ts
  55. 0 0
      src/app/models/measure.ts
  56. 11 0
      src/app/models/organization.ts
  57. 7 5
      src/app/models/plant.ts
  58. 6 6
      src/app/models/user.ts
  59. 59 0
      src/app/services/assets/assets.service.ts
  60. 12 0
      src/app/services/auth.service.spec.ts
  61. 121 0
      src/app/services/auth.service.ts
  62. 16 34
      src/app/services/authentication.service.ts
  63. 78 0
      src/app/services/logs.service.ts
  64. 12 0
      src/app/services/measures.service.spec.ts
  65. 20 0
      src/app/services/measures.service.ts
  66. 12 0
      src/app/services/organizations.service.spec.ts
  67. 123 0
      src/app/services/organizations.service.ts
  68. 79 5
      src/app/services/plants.service.ts
  69. 4 1
      src/app/services/services.module.ts
  70. BIN
      src/assets/img/01d.png
  71. BIN
      src/assets/img/01n.png
  72. BIN
      src/assets/img/02d.png
  73. BIN
      src/assets/img/02n.png
  74. BIN
      src/assets/img/03d.png
  75. BIN
      src/assets/img/03n.png
  76. BIN
      src/assets/img/04d.png
  77. BIN
      src/assets/img/04n.png
  78. BIN
      src/assets/img/09d.png
  79. BIN
      src/assets/img/09n.png
  80. BIN
      src/assets/img/10d.png
  81. BIN
      src/assets/img/10n.png
  82. BIN
      src/assets/img/11d.png
  83. BIN
      src/assets/img/11n.png
  84. BIN
      src/assets/img/50d.png
  85. BIN
      src/assets/img/50n.png
  86. BIN
      src/assets/img/car-icon.png
  87. 23 0
      src/assets/img/circle.svg
  88. BIN
      src/assets/img/desktop-pc-icon.png
  89. BIN
      src/assets/img/inverlec_logo.png
  90. BIN
      src/assets/img/logo-inverlec2.png
  91. 69 0
      src/assets/img/sound.svg
  92. BIN
      src/assets/img/tv-icon.png
  93. BIN
      src/assets/img/waves-alt.png
  94. BIN
      src/assets/img/waves-opt.png
  95. BIN
      src/assets/img/waves.png
  96. 2 2
      src/assets/scss/core/_fixed-plugin.scss
  97. 1 1
      src/assets/scss/core/_sidebar-and-main-panel.scss
  98. 29 5
      src/assets/scss/material-dashboard.scss
  99. 2 1
      src/environments/environment.ts
  100. 0 1
      src/index.html

+ 8 - 3
package-lock.json

@@ -1342,9 +1342,9 @@
       "integrity": "sha512-IlUyCs/hLv12hzz2pGugbrdRpBbwE6JUM4Bm4CCqLptmZj+t8pw8Ywthde8yUDdpgGgTJeJ9G5o92QadyGbP3g=="
     },
     "@types/chart.js": {
-      "version": "2.8.4",
-      "resolved": "https://registry.npmjs.org/@types/chart.js/-/chart.js-2.8.4.tgz",
-      "integrity": "sha512-qc73o22TTRaNbxqXKvZpYynxkzKHhGVYgJ+J8M/iVfXJPxHP+5UJlRM+VuPSyP++sGjZjX9kc3wkIv+hDD4IKQ=="
+      "version": "2.8.5",
+      "resolved": "https://registry.npmjs.org/@types/chart.js/-/chart.js-2.8.5.tgz",
+      "integrity": "sha512-CohUDPD3f5e/sGI8SUs1zaUnS38MMA+4WDDxBoudQIKVqNj4LJG2P+Z0WXB+vT4jkDpc7itXYoNIZq1f1MpulA=="
     },
     "@types/datatables.net": {
       "version": "1.10.17",
@@ -9710,6 +9710,11 @@
         "has-flag": "^3.0.0"
       }
     },
+    "sweetalert2": {
+      "version": "8.17.1",
+      "resolved": "https://registry.npmjs.org/sweetalert2/-/sweetalert2-8.17.1.tgz",
+      "integrity": "sha512-aCPXmK1YyVUfsw36iDETzUnYj1fxwXSY/dkt8cnqViv7f5sOS5i37LXIf9LLiDCd99EbY4d4kvZkyWYlJZ79Xw=="
+    },
     "symbol-observable": {
       "version": "1.2.0",
       "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz",

+ 1 - 0
package.json

@@ -46,6 +46,7 @@
     "popper.js": "^1.15.0",
     "rxjs": "6.5.2",
     "rxjs-compat": "^6.5.2",
+    "sweetalert2": "^8.17.1",
     "tslib": "^1.10.0",
     "zone.js": "~0.9.1"
   },

+ 11 - 6
src/app/app.component.ts

@@ -1,7 +1,7 @@
-import { Component } from '@angular/core';
+import { Component, OnInit } from '@angular/core';
 import { Router } from '@angular/router';
 
-import { AuthenticationService } from '@app/services/authentication.service';
+//import { AuthenticationService } from '@app/services/authentication.service';
 import { User, Role } from './models';
 
 @Component({
@@ -9,15 +9,20 @@ import { User, Role } from './models';
   templateUrl: './app.component.html',
   styleUrls: ['./app.component.scss']
 })
-export class AppComponent {
+export class AppComponent implements OnInit {
   title = 'plant-viewer';
   currentUser: User;
 
   constructor(
     private router: Router,
-    private authenticationService: AuthenticationService
-  ) {
-    this.authenticationService.currentUser.subscribe(x => this.currentUser = x);
+    //private authenticationService: AuthenticationService,
+  )
+
+  {
+    //this.authenticationService.currentUser.subscribe(x => this.currentUser = x);
+  }
+
+  ngOnInit() {
   }
 
   get isAdmin() {

+ 11 - 9
src/app/app.module.ts

@@ -7,14 +7,16 @@ import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
 import { registerLocaleData } from '@angular/common';
 import { RouterModule } from '@angular/router';
 
+
+
 // Internationalization i18n
 import localeEs from '@angular/common/locales/es';
 import localeEsExtra from '@angular/common/locales/extra/es';
 registerLocaleData(localeEs, 'es-Es', localeEsExtra);
 
 // used to create fake backend
-import { fakeBackendProvider } from './helpers';
-import { JwtInterceptor, ErrorInterceptor } from './helpers';
+//import { fakeBackendProvider } from './helpers';
+//import { JwtInterceptor, ErrorInterceptor } from './helpers';
 
 
 import { AppRoutingModule } from './app.routing';
@@ -27,12 +29,11 @@ import { AdminComponent } from './layouts/admin/admin.component';
 
 
 import { NgxDatatableModule } from '@swimlane/ngx-datatable';
+import { MatSelectModule } from '@angular/material/select';
+
 
-//import { DashboardComponent } from './dashboard/dashboard.component';
-//import { AgmCoreModule } from '@agm/core';
 import { PluginsModule } from './components/plugins/plugins.module';
 import { LoginComponent } from './components/login/login.component';
-import { AuthenticationService } from './services/authentication.service';
 
 
 //import { DashboardComponent } from './dashboard/dashboard.component';
@@ -56,13 +57,14 @@ import { AuthenticationService } from './services/authentication.service';
     AppRoutingModule,
     PluginsModule,
     NgxDatatableModule,
+    MatSelectModule,
   ],
   providers: [
-    { provide: HTTP_INTERCEPTORS, useClass: JwtInterceptor, multi: true },
-    { provide: HTTP_INTERCEPTORS, useClass: ErrorInterceptor, multi: true },
-    AuthenticationService,
+    //{ provide: HTTP_INTERCEPTORS, useClass: JwtInterceptor, multi: true },
+    //{ provide: HTTP_INTERCEPTORS, useClass: ErrorInterceptor, multi: true },
+    //AuthenticationService,
     // provider used to create fake backend
-    fakeBackendProvider
+    //fakeBackendProvider
   ],
   bootstrap: [AppComponent]
 })

+ 6 - 7
src/app/app.routing.ts

@@ -6,7 +6,7 @@ import { AdminModule } from './layouts/admin/admin.module';
 
 import { AdminComponent } from './layouts/admin/admin.component';
 import { LoginComponent } from './components/login/login.component';
-import { AuthGuard } from './helpers/auth.guard';
+import { AuthGuard } from './services/authentication.service';
 import { Role } from './models/role';
 
 const routes: Routes =[
@@ -14,7 +14,8 @@ const routes: Routes =[
     path: '',
     redirectTo: 'dashboard',
     pathMatch: 'full',
-  }, {
+  }, 
+  {
     path: '',
     component: AdminComponent,
     canActivate: [AuthGuard],
@@ -22,10 +23,7 @@ const routes: Routes =[
       path: '',
       loadChildren : () => AdminModule
     }]
-  }, {
-    path: 'login',
-    component: LoginComponent
-  },
+  }, { path: 'login', component: LoginComponent },
   { path: '**', redirectTo: '' }
 ];
 
@@ -34,7 +32,8 @@ const routes: Routes =[
     CommonModule,
     BrowserModule,
     RouterModule.forRoot(routes,{
-       useHash: true
+       useHash: true,
+       onSameUrlNavigation: 'reload'
     })
   ],
   exports: [

+ 166 - 0
src/app/components/assets/assets.component.html

@@ -0,0 +1,166 @@
+<h2 class="floating-title">{{title}}</h2>
+<div class="main-content">
+  <div class="row align-container">
+    <div class="col-12">    
+      <label for="sel3">Plantas</label>
+    </div>
+  </div>
+  <div class="row">
+    <div class="col-lg-6 col-sm-4">
+      <div class="align-container">
+        <select class="custom-select"(onChange)="onChangeObj($event)" name="sel3">
+          <option *ngFor="let item of listAssets" [selected]="item._id===organizationId" [value]="item._id" >{{item.name}}</option>
+        </select>
+      </div>
+      <br>
+    </div>
+
+    <!-- Weather card -->
+    <div class="col-lg-6 col-sm-8">
+      <div class="row align-container">
+        <div class="col-lg-12">
+          <app-weather-card></app-weather-card>
+        </div>
+      </div>
+    </div>
+
+  </div>
+  <br>
+
+  <!-- Basic stats cards -->
+  <div class="row align-container" style="padding: 0 25px;">
+
+    <div class="col-xl-3 col-lg-6 col-md-6 col-sm-6 p-1">
+      <div class="widget">
+        <div class="mini-stats ">
+          <span class="sky-skin"><i class="fa fa-bolt"></i></span>
+          <p>Ultimo dia</p>
+          <h3 *ngIf="listEnergyProduced">
+            {{listEnergyProduced.today.total_energy_kWh}}
+            <small>kW</small>
+          </h3>
+        </div>
+      </div>
+    </div>
+    
+    <div class="col-xl-3 col-lg-6 col-md-6 col-sm-6 p-1">
+      <div class="widget">
+        <div class="mini-stats ">
+          <span class="dark-yellow-skin"><i class="fa fa-bolt"></i></span>
+          <p>Ultima semana</p>
+          <h3 *ngIf="listEnergyProduced">
+            {{listEnergyProduced.thisWeek.total_energy_kWh/1000 | number}}
+            <small>MWh</small>
+          </h3>
+        </div>
+      </div>
+    </div>
+    
+    <div class="col-xl-3 col-lg-6 col-md-6 col-sm-6 p-1">
+      <div class="widget">
+        <div class="mini-stats ">
+          <span class="yellow-skin"><i class="fa fa-bolt"></i></span>
+          <p>Ultimos 30 días</p>
+          <h3 *ngIf="listEnergyProduced">
+            {{listEnergyProduced.thisMonth.total_energy_kWh/1000 | number}}
+            <small>MWh</small>
+          </h3>
+        </div>
+      </div>
+    </div>
+
+    <div class="col-xl-3 col-lg-6 col-md-6 col-sm-6 p-1">
+      <div class="widget">
+        <div class="mini-stats ">
+          <span class="dark-yellow-skin"><i class="fa fa-bolt"></i></span>
+          <p>Total</p>
+          <h3 *ngIf="listEnergyProduced">
+            {{listEnergyProduced.lifeTime.total_energy_kWh/1000 | number}}
+            <small>MWh</small>
+          </h3>
+        </div>
+      </div>
+    </div>
+
+  </div>
+  
+  <br>
+
+  <!-- Chartjs potency generation graphic -->
+  <div class="row align-container">
+    <div class="col-lg-12 col-md-12 col-sm-12">
+      <div class="widget">
+        <div class="mini-stats">
+
+          <div style="display: block" >
+            <canvas baseChart #baseChart="base-chart" [datasets]="barChartData" [labels]="barChartLabels" [options]="barChartOptions"
+              [legend]="barChartLegend" [chartType]="barChartType"></canvas>
+          </div>
+
+          <p>Seleccione un rango de visualización</p>
+
+          <button class="btn" [class.btn-success]='isActive[0]' (click)="onMeasureClickDay()">Día</button>
+          <button class="btn" [class.btn-success]='isActive[1]' (click)="onMeasureClickWeek()">Semana</button>
+          <button class="btn" [class.btn-success]='isActive[2]' (click)="onMeasureClickMonth()">Mes</button>
+          <button class="btn" [class.btn-success]='isActive[3]' (click)="onMeasureYear()">Año</button>
+
+        </div>
+      </div>
+    </div>
+  </div>
+  
+  <!-- Enviromental cool stats cards -->
+  <div class="row align-container">
+
+    <div class="col-xl-4 col-lg-6 col-md-6 col-sm-6">
+      <div class="widget">
+        <div class="enviroment-stats">
+          <div class="enviromental-icon">
+            <img src="assets/img/tv-icon.png" alt="">
+          </div>
+          <div class="enviromental-text">
+            La energía para operar un televisor durante
+            <span>1,847,140</span>
+            horas
+          </div>
+        </div>
+      </div>
+    </div>
+    
+    <div class="col-xl-4 col-lg-6 col-md-6 col-sm-6">
+      <div class="widget">
+        <div class="enviroment-stats">
+          <div class="enviromental-icon">
+            <img src="assets/img/car-icon.png" alt="">
+          </div>
+          <div class="enviromental-text">
+            Los gases de efecto invernadero que emiten 
+            <span>57</span>
+            usuarios de vehiculos en 1 año
+          </div>
+        </div>
+      </div>
+    </div>
+    
+    <div class="col-xl-4 col-lg-6 col-md-6 col-sm-6">
+      <div class="widget">
+        <div class="enviroment-stats">
+          <div class="enviromental-icon">
+            <img src="assets/img/desktop-pc-icon.png" alt="">
+          </div>
+          <div class="enviromental-text">
+            La energía para alimentar 
+            <span>2044</span>
+            computadoras por 1 año
+          </div>
+           
+        </div>
+      </div>
+    </div>
+
+  </div>
+
+  <br>
+  <br>
+
+</div>

+ 145 - 0
src/app/components/assets/assets.component.scss

@@ -0,0 +1,145 @@
+table {
+  width: 100%;
+}
+
+.mat-form-field {
+  font-size: 14px;
+  width: 100%;
+}
+
+.example-loading-shade {
+  position: absolute;
+  top: 0;
+  left: 0;
+  bottom: 56px;
+  right: 0;
+  background: rgba(0, 0, 0, 0.15);
+  z-index: 1;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+}
+
+.example-rate-limit-reached {
+  color: #980000;
+  max-width: 360px;
+  text-align: center;
+}
+
+/* Structure */
+.example-container {
+  position: relative;
+  min-height: 200px;
+}
+
+.example-table-container {
+  position: relative;
+  //max-height: 400px;
+  overflow: auto;
+}
+
+
+.widget {
+  background: #ffffff none repeat scroll 0 0;
+  float: left;
+  margin-top: 14px;
+  position: relative;
+  width: 100%;
+  border-radius: 5px;
+
+  .chart-padding {
+    padding: 10px;
+  }
+
+  .mini-stats {
+    background: #ffffff none repeat scroll 0 0;
+    border-radius: 5px;
+    float: left;
+    padding: 10px;
+    position: relative;
+    width: 100%;
+
+    p {
+      color: #878888;
+      display: block;
+      font-size: 12px;
+      line-height: 20px;
+      margin: 6px 0 0;
+      text-transform: uppercase;
+      display: block;
+      width: auto;
+    }
+
+    span {
+      border: 1px solid;
+      border-radius: 50%;
+      color: #fff;
+      float: left;
+      font-size: 25px;
+      height: 50px;
+      line-height: 50px;
+      margin-right: 5px;
+      text-align: center;
+      width: 50px;
+      display: block;
+    }
+
+    h3 {
+      margin: 0;
+      display: block;
+    }
+
+  }
+
+  .enviroment-stats {
+    background: #ffffff none repeat scroll 0 0;
+    border-radius: 5px;
+    padding: 20px;
+    display: table;
+
+    .enviromental-icon {
+      height: 128px;
+      display: table-cell;
+      vertical-align: middle;
+    }
+
+    .enviromental-text {
+      line-height: 1.2;
+      display: table-cell;
+      font-size: 1rem;
+      text-transform: initial;
+      padding-left: 10px;
+      vertical-align: middle;
+
+      span {
+        float: none;
+        height: auto;
+        margin: 0;
+        width: auto;
+        display: inline;
+        border: none;
+        font-size: 1.2rem;
+        font-weight: bold;
+        color: #386641;
+        vertical-align: middle;
+      }
+    }
+
+  }
+}
+
+
+
+
+
+@media screen and (min-width: 960px) {
+  .mini-stats {
+    
+    p,
+    span,
+    h3 {
+      display: block;
+    }
+
+  }
+}

+ 6 - 6
src/app/components/plugins/plant-detail/plant-detail.component.spec.ts → src/app/components/assets/assets.component.spec.ts

@@ -1,20 +1,20 @@
 import { async, ComponentFixture, TestBed } from '@angular/core/testing';
 
-import { PlantDetailComponent } from './plant-detail.component';
+import { AssetsComponent } from './assets.component';
 
-describe('PlantDetailComponent', () => {
-  let component: PlantDetailComponent;
-  let fixture: ComponentFixture<PlantDetailComponent>;
+describe('AssetsComponent', () => {
+  let component: AssetsComponent;
+  let fixture: ComponentFixture<AssetsComponent>;
 
   beforeEach(async(() => {
     TestBed.configureTestingModule({
-      declarations: [ PlantDetailComponent ]
+      declarations: [ AssetsComponent ]
     })
     .compileComponents();
   }));
 
   beforeEach(() => {
-    fixture = TestBed.createComponent(PlantDetailComponent);
+    fixture = TestBed.createComponent(AssetsComponent);
     component = fixture.componentInstance;
     fixture.detectChanges();
   });

+ 422 - 0
src/app/components/assets/assets.component.ts

@@ -0,0 +1,422 @@
+import { Component, OnInit, ViewChild,OnChanges } from '@angular/core';
+import { ChartOptions, ChartType, ChartDataSets } from 'chart.js';
+import { Label, BaseChartDirective } from 'ng2-charts';
+
+import { Plant } from 'src/app/models/plant';
+import { Organization } from '@app/models/organization';
+
+
+import { MeasuresService } from 'src/app/services/measures.service';
+import { PlantsService } from 'src/app/services/plants.service';
+import { AssetsService } from 'src/app/services/assets/assets.service';
+import { LogsService } from 'src/app/services/logs.service';
+
+import { OrganizationsService } from '@app/services/organizations.service';
+
+import { ActivatedRoute } from '@angular/router';
+import { Observable, forkJoin } from 'rxjs';
+
+
+import * as moment from 'moment';
+
+import Swal from 'sweetalert2';
+import { environment } from '@environments/environment';
+import { HttpClient } from '@angular/common/http';
+
+@Component({
+  selector: 'app-assets',
+  templateUrl: './assets.component.html',
+  styleUrls: ['./assets.component.scss']
+})
+
+
+export class AssetsComponent implements OnInit {
+ 
+  title = "Plantas";
+
+  organizationId:string;
+  listAssets:any;
+  listEnergyProduced:any;
+  error:boolean;
+  errorMessage:string;
+
+  // For chartjs
+  tsLabels: any[];
+  polarLabels: any[];
+  serieA: any[];
+  serieB: any[];
+  serieC: any[];
+ 
+  public barChartType: ChartType;
+  public barChartLegend:boolean;
+  public barChartLabels: Label[];
+  public barChartOptions: ChartOptions;
+  public barChartData: ChartDataSets[];
+
+  isActive:[boolean,boolean,boolean,boolean]; // Tipo de parámetro activado?
+  selectedMeasureType = 'Voltaje'; // Medidores
+
+
+  constructor(
+    private orgService: OrganizationsService, 
+    private route: ActivatedRoute, 
+    private plantsService: PlantsService,
+    private assetService: AssetsService,
+    private http: HttpClient,
+    private logsService: LogsService,
+    private measService: MeasuresService) {
+      
+      Swal.fire({
+        allowOutsideClick: false,
+        type: 'info',
+        text: 'Espere por favor...'
+      });
+      Swal.showLoading();
+      
+  }
+
+  @ViewChild("baseChart",null) chart: BaseChartDirective;
+
+  ngOnInit() {
+    
+    let plants = this.plantsService.getAssets();
+    let energy_produced = this.plantsService.getAssetsProducedEnergy();
+
+    forkJoin([plants, energy_produced]).subscribe(results => {
+      this.listAssets = results[0]["assets"];
+      this.listEnergyProduced = results[1];   
+      //this.route.queryParams.subscribe(params => {
+        //this.organizationId = params['id'];
+        //console.log(this.organizationId); // Print the parameter to the console.
+      //});
+      Swal.close();
+    },
+    (err) => {
+      Swal.fire({
+        type: 'error',
+        title: 'Error en el servidor',
+        text: "No su pudo obtener la informacion"
+      });
+    });
+
+    this.barChartLegend = true;
+    this.barChartOptions = {
+      responsive: true,
+      scales: {
+        xAxes: [{
+          stacked: true
+        }],
+        yAxes: [{
+          stacked: true
+        }]
+      }
+    };
+    this.isActive = [false, false, true, false];
+    this.onMeasureClickMonth();
+  }
+ 
+  getAllAssetData(): void {
+    console.log("i get here :P");
+  }
+
+  isSelected(){
+    if(this.organizationId!=undefined){
+      return true;
+    }
+    else{
+      return false;
+    }
+  }
+
+
+  public onMeasureClickDay(): void {
+    this.chart.chart.destroy;
+
+    this.isActive = [true, false, false, false];
+    this.chart.datasets = [
+      {
+       
+				label: 'Dataset 1',
+				data: [
+					11,
+					13,
+					8,
+					10,
+					7,
+					6,
+          9,
+          12,
+          9,
+          9,
+          5,
+          20
+				]
+			}, {
+				label: 'Dataset 2',
+				data: [
+					11,
+					22,
+					10,
+					6,
+					7,
+					3,
+          15,
+          12,
+          12,
+          14,
+          9,
+          5
+				]
+			}, {
+				label: 'Dataset 3',
+				data: [
+					8,
+					6,
+					20,
+					11,
+					20,
+					13,
+          9,
+          11,
+          13,
+          7,
+					3,
+					15
+				]
+			}
+
+      //{ data: this.serieA, label: this.selectedMeasureType + ' A', fill: false, lineTension: 0},
+      //{ data: this.serieB, label: this.selectedMeasureType + ' B', fill: false, lineTension: 0},
+      //{ data: this.serieC, label: this.selectedMeasureType + ' C', fill: false, lineTension: 0}
+    ];
+    this.tsLabels = ['Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio', 'Julio', 'Agosto', 'Septiembre', 'Octubre', 'Noviembre', 'Diciembre'];
+    this.chart.labels = this.tsLabels;
+    this.chart.chartType  = 'line';
+    this.chart.ngOnInit();
+
+  }
+
+  public onMeasureClickWeek(): void {
+    
+    this.chart.chart.destroy;
+    Swal.fire({
+      allowOutsideClick: false,
+      type: 'info',
+      text: 'Espere por favor...'
+    });
+    Swal.showLoading();
+
+    setTimeout(()=>{ 
+      this.isActive = [false, true, false, false];
+  
+      this.logsService.getEnergyProducedByWeek().subscribe(res => {
+        this.barChartLabels = res["7D"].map(obj => obj.dateMax).reverse();
+        this.serieA = res["7D"].map(obj => obj.total_energy_kWh).reverse();
+      
+        this.barChartData = [
+          { data: this.serieA, label: "Total", fill: false, lineTension: 0},
+        ];
+      
+      });
+      
+      this.chart.chartType  = 'bar';
+      this.chart.ngOnInit();
+      
+      Swal.close();
+    }, 2000);
+
+
+    
+
+
+    /*
+    this.chart.chart.destroy;
+
+    this.isActive = [false, true, false, false];
+
+    this.barChartData = [
+      {
+       
+				label: 'Dataset 1',
+				data: [
+					11,
+					10,
+					7,
+					9,
+          12,
+          5,
+          20
+				]
+			}, {
+				label: 'Dataset 2',
+				data: [
+					22,
+					10,
+					6,
+          12,
+          14,
+          9,
+          5
+				]
+			}, {
+				label: 'Dataset 3',
+				data: [
+					8,
+					20,
+          11,
+          13,
+          7,
+					3,
+					15
+				]
+			}
+      
+
+      //{ data: this.serieA, label: this.selectedMeasureType + ' A', fill: false, lineTension: 0},
+      //{ data: this.serieB, label: this.selectedMeasureType + ' B', fill: false, lineTension: 0},
+      //{ data: this.serieC, label: this.selectedMeasureType + ' C', fill: false, lineTension: 0}
+    ];
+
+    this.tsLabels = ['10/09/2019', '11/09/2019', '12/09/2019', '13/09/2019', '14/09/2019', '15/09/2019', '16/09/2019']; */
+   
+  }
+
+  public onMeasureClickMonth(): void {
+    
+    if (this.chart.data != undefined){
+      this.chart.chart.destroy;
+    }
+
+    this.isActive = [false, false, true, false];
+
+    this.barChartData = [
+      {
+       
+				label: 'Dataset 1',
+				data: [
+					11,
+					13,
+					8,
+					10,
+					7,
+					6,
+          9,
+          12,
+          9,
+          9,
+          5,
+          20
+				]
+			}, {
+				label: 'Dataset 2',
+				data: [
+					11,
+					22,
+					10,
+					6,
+					7,
+					3,
+          15,
+          12,
+          12,
+          14,
+          9,
+          5
+				]
+			}, {
+				label: 'Dataset 3',
+				data: [
+					8,
+					6,
+					20,
+					11,
+					20,
+					13,
+          9,
+          11,
+          13,
+          7,
+					3,
+					15
+				]
+			}
+
+      //{ data: this.serieA, label: this.selectedMeasureType + ' A', fill: false, lineTension: 0},
+      //{ data: this.serieB, label: this.selectedMeasureType + ' B', fill: false, lineTension: 0},
+      //{ data: this.serieC, label: this.selectedMeasureType + ' C', fill: false, lineTension: 0}
+    ];
+    this.tsLabels = ['Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio', 'Julio', 'Agosto', 'Septiembre', 'Octubre', 'Noviembre', 'Diciembre'];
+    this.barChartLabels = this.tsLabels;
+    this.barChartType  = 'bar';
+    //this.chart.ngOnInit();
+  }
+
+  public onMeasureYear(): void {
+    this.chart.chart.destroy;
+
+    this.isActive = [false, false, false, true];
+
+    this.barChartData = [
+      {
+       
+				label: 'Dataset 1',
+				data: [
+					11,
+					13,
+					8,
+					10,
+					7,
+					6,
+          9,
+          12,
+          9,
+          9,
+          5,
+          20
+				]
+			}, {
+				label: 'Dataset 2',
+				data: [
+					11,
+					22,
+					10,
+					6,
+					7,
+					3,
+          15,
+          12,
+          12,
+          14,
+          9,
+          5
+				]
+			}, {
+				label: 'Dataset 3',
+				data: [
+					8,
+					6,
+					20,
+					11,
+					20,
+					13,
+          9,
+          11,
+          13,
+          7,
+					3,
+					15
+				]
+			}
+
+      //{ data: this.serieA, label: this.selectedMeasureType + ' A', fill: false, lineTension: 0},
+      //{ data: this.serieB, label: this.selectedMeasureType + ' B', fill: false, lineTension: 0},
+      //{ data: this.serieC, label: this.selectedMeasureType + ' C', fill: false, lineTension: 0}
+    ];
+
+    this.tsLabels = ['Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio', 'Julio', 'Agosto', 'Septiembre', 'Octubre', 'Noviembre', 'Diciembre'];
+    this.barChartLabels = this.tsLabels;
+    this.barChartType  = 'bar';
+    this.chart.ngOnInit();
+  }
+
+}

+ 67 - 146
src/app/components/dashboard/dashboard.component.html

@@ -1,163 +1,84 @@
+<h2 class="floating-title">{{title}}</h2>
+
 <div class="main-content">
   <div class="container-fluid">
+
     <div class="row">
       <div class="col-lg-6 col-md-6 col-sm-6">
-        <div class="row">
-
-          <div class="col-lg-6 col-md-6 col-sm-6">
-            <div class="widget">
-							<div class="mini-stats ">
-								<span class="sky-skin"><i class="fa fa-bolt"></i></span>
-								<p>Capacidad instalada</p>
-								<h3>
-                  369.6
-                  <small>kW</small>
-                </h3>
-							</div>
-						</div>
+        <div class="card dark-yellow-skin bg-gradient-danger card-img-holder text-white">
+          <div class="card-body">
+            <img alt="circle-image" class="card-img-absolute" src="assets/img/waves-opt.png">
+            <h4 class="font-weight-normal mb-3">Total de plantas instaladas
+              <i class="mdi mdi-chart-line mdi-24px float-right"></i>
+            </h4>
+            <h2 class="mb-3">30</h2>
+          </div>
+        </div>
+      </div>
+      <div class="col-lg-6 col-md-6 col-sm-6">
+        <div class="card sky-skin bg-gradient-danger card-img-holder text-white">
+          <div class="card-body">
+            <img alt="circle-image" class="card-img-absolute" src="assets/img/waves-opt.png">
+            <h4 class="font-weight-normal mb-3">Capacidad instalada total
+              <i class="mdi mdi-chart-line mdi-24px float-right"></i>
+            </h4>
+            <h2 class="mb-3">{{totalMetersInstalled}} kW</h2>
           </div>
+        </div>
+      </div>
+  
+  
+    </div>
+    
+    <br>
 
-          <div class="col-lg-6 col-md-6 col-sm-6">
-            <div class="widget">
-							<div class="mini-stats ">
-								<span class="dark-yellow-skin"><i class="fa fa-bolt"></i></span>
-								<p>Ultimos 365 días</p>
-                <h3>
-                  270.83
-                  <small>MWh</small>
-                </h3>
-							</div>
-						</div>
+    <div class="row ">
+      <div *ngIf="error; then showAlert"></div>
+      <ng-template #showAlert>
+        <div class="col-lg-12">
+          <div class= 'card border-danger'>
+            <div class="card-body">
+              Error en el servidor, no se pudo obtener el listado de plantas
+            </div>
           </div>
+        </div>
+      </ng-template>
+    </div>
+    <br>
 
-          <div class="col-lg-6 col-md-6 col-sm-6">
-            <div class="widget">
-							<div class="mini-stats ">
-								<span class="yellow-skin"><i class="fa fa-bolt"></i></span>
-								<p>Ultimos 30 días</p>
-								<h3>
-                  56.24
-                  <small>MWh</small>
-                </h3>
-							</div>
-						</div>
+    <div class="row">
+      <div class="col-md-8">
+        <div class= 'card border-success'>
+          <div class="card-body">
+            <div style="height: 350px;" leaflet [leafletOptions]="options" [leafletLayers]="markers"
+              (leafletMapReady)='onMapReady($event)'>
+            </div>
           </div>
+        </div> 
+      </div>
+      <div class="col-md-4">
 
-          <div class="col-lg-6 col-md-6 col-sm-6">
-            <div class="widget">
-              <div class="mini-stats ">
-                <span class="cream-skin"><i class="fa fa-bolt"></i></span>
-                <p>Ultimos 24 horas</p>
-                <h3>
-                  1.55
-                  <small>MWh</small>
-                </h3>
+          <div class='plant-detail' *ngIf=selectedPlant>
+            <div class= 'card border-success' style="height: 390px;">
+              <div class="card-body">
+                <h3><i class="fa fa-bolt"></i> {{selectedPlant.name}} </h3>
+                
+                <p class='h4'>País: {{selectedPlant.country}}</p>
+                <p class='h4'>Ciudad: {{selectedPlant.city}}</p>
+                <p class='h4'>Dirección: {{selectedPlant.address}}</p>
+                <p class='h4'>Capacidad Instalada: {{selectedPlant.installedCapacity_kW}} kW</p>
+                
+                <button class="btn bg-yellow btn-flat">Ir a Planta</button>
               </div>
+                  
             </div>
           </div>
-        </div>
-        <br>
-        <div class="row">
-          <div class="col-lg-12">
-            <app-weather-card></app-weather-card>
-          </div>
-        </div>
-      </div>
-      <div class="col-lg-6 col-md-6 col-sm-12">
-        Grafico
+            
+        <app-plant-detail [plantId]="plantId"></app-plant-detail>
       </div>
     </div>
-  </div>
-  <br>
-  <div class="d-none d-md-block">
-    <app-plants-datatables></app-plants-datatables>
-  </div>
+    <br>
+      
 
-  <div class="d-block d-md-none">
-    <app-plants-status></app-plants-status>
   </div>
-
-
-  <app-maps></app-maps>
-
-</div>
-
-
-<!--
-<div class="col-lg-3 col-md-6 col-sm-6">
-  <div class="card card-stats">
-    <div class="card-header card-header-warning card-header-icon">
-      <div class="card-icon">
-        <i class="material-icons">offline_bolt</i>
-      </div>
-      <p class="card-category">Capacidad instalada</p>
-      <h3 class="card-title">369.6
-        <small>kW</small>
-      </h3>
-    </div>
-    <div class="card-footer">
-      <div class="stats">
-        <i class="material-icons">business</i>
-        <span>5 plantas</span>
-      </div>
-    </div>
-  </div>
-</div>
-<div class="col-lg-3 col-md-6 col-sm-6">
-  <div class="card card-stats">
-    <div class="card-header card-header-success card-header-icon">
-      <div class="card-icon">
-        <i class="material-icons">date_range</i>
-      </div>
-      <p class="card-category">Ultimos 365 días</p>
-      <h3 class="card-title">270.83
-        <small>MWh</small>
-      </h3>
-    </div>
-    <div class="card-footer">
-      <div class="stats">
-        <i class="material-icons">offline_bolt</i>
-        Energía
-      </div>
-    </div>
-  </div>
-</div>
-<div class="col-lg-3 col-md-6 col-sm-6">
-  <div class="card card-stats">
-    <div class="card-header card-header-danger card-header-icon">
-      <div class="card-icon">
-        <i class="material-icons">date_range</i>
-      </div>
-      <p class="card-category">Ultimos 30 días</p>
-      <h3 class="card-title">56.24
-        <small>MWh</small>
-      </h3>
-    </div>
-    <div class="card-footer">
-      <div class="stats">
-        <i class="material-icons">offline_bolt</i>
-        Energía
-      </div>
-    </div>
-  </div>
-</div>
-<div class="col-lg-3 col-md-6 col-sm-6">
-  <div class="card card-stats">
-    <div class="card-header card-header-danger card-header-icon">
-      <div class="card-icon">
-          <i class="material-icons">date_range</i>
-      </div>
-      <p class="card-category">Ultimas 24 horas</p>
-      <h3 class="card-title">1.55
-        <small>MWh</small>
-      </h3>
-    </div>
-    <div class="card-footer">
-      <div class="stats">
-        <i class="material-icons">offline_bolt</i>
-        Energía
-      </div>
-    </div>
-  </div>
-</div>
--->
+  <br>

+ 19 - 60
src/app/components/dashboard/dashboard.component.scss

@@ -2,68 +2,27 @@ agm-map {
   height: 300px;
 }
 
-.widget {
-  background: #ffffff none repeat scroll 0 0;
-  float: left;
-  margin-top: 14px;
-  position: relative;
-  width: 100%;
-  border-radius: 5px;
-
-  .widget-controls {
-    padding-right: 10px;
-    padding-top: 10px;
-    position: absolute;
-    right: 0;
-    top: 0;
-    z-index: 1;
-
-    span {
-      border: 1px solid;
-      border-radius: 50%;
-      color: #fff;
-      float: left;
-      font-size: 20px;
-      height: 57px;
-      line-height: 56px;
-      margin-right: 15px;
-      text-align: center;
-      width: 57px;
-    }
-  }
-
-  .mini-stats {
-    background: #ffffff none repeat scroll 0 0;
-    border-radius: 5px;
-    float: left;
-    padding: 15px 20px;
-    position: relative;
-    width: 100%;
+.card-img-holder {
+  margin-bottom: 10px;
+}
 
-    p {
-      color: #878888;
-      display: block;
-      font-size: 11px;
-      line-height: 20px;
-      margin: 6px 0 0;
-      text-transform: uppercase;
-    }
+.hidden-element {
+  display: none;
+}
 
-    span {
-      border: 1px solid;
-      border-radius: 50%;
-      color: #fff;
-      float: left;
-      font-size: 20px;
-      height: 57px;
-      line-height: 56px;
-      margin-right: 15px;
-      text-align: center;
-      width: 57px;
-    }
+.detail-box {
+  border: none;
+  border-radius: 0;
+  box-shadow: none;
+}
 
-    h3 {
-      margin: 0;
-    }
+.plant-detail {
+  h3 {
+    margin-top: 0;
+  }
+  button {
+    position: absolute;
+    bottom: 15px;
   }
 }
+

+ 135 - 7
src/app/components/dashboard/dashboard.component.ts

@@ -1,6 +1,15 @@
-import { Component, OnInit } from '@angular/core';
+import { ActivatedRoute } from '@angular/router';
+import { Component, OnInit, Input, Output, EventEmitter, OnDestroy, NgZone } from '@angular/core';
 import { Plant } from 'src/app/models/plant';
 import { PlantsService } from 'src/app/services/plants.service';
+import { OrganizationsService } from 'src/app/services/organizations.service';
+import { latLng, tileLayer, marker, Layer, icon, Map, latLngBounds, LatLng, LatLngBounds, point } from 'leaflet';
+
+import { of as observableOf, Observable, throwError, from } from 'rxjs';
+
+import * as moment from 'moment';
+import Swal from 'sweetalert2';
+
 
 @Component({
   selector: 'app-dashboard',
@@ -8,19 +17,94 @@ import { PlantsService } from 'src/app/services/plants.service';
   styleUrls: ['./dashboard.component.scss']
 })
 export class DashboardComponent implements OnInit {
-  listData: Plant[];
+
+  title = "Dashboard";
+
+
+  listData:any;
   rows = [];
+  markers: Layer[] = [];
+  points: LatLng[] = [];
+
+  listOrganizations: any;
+  error:boolean;
+  plantId: string;
+  plant:any;
+  sub: any;
+  plantNotFound: boolean;
+  selectedPlant: any;
 
-  constructor(private plantsService: PlantsService) {}
-  ngOnInit(): void {
 
-    this.plantsService.getPlants().subscribe(res => {
-      this.listData = res;
+  totalMetersInstalled:string;
+
+  lastUpdate = new Date().toLocaleString();
+  i: number;
+
+  // Leajflet map
+  icon = icon({
+    iconSize: [25, 41],
+    iconAnchor: [13, 41],
+    iconUrl: 'marker-icon.png',
+    //shadowUrl: 'marker-shadow.png'
+  });
+
+  // Open Street Map definitions
+  LAYER_OSM = tileLayer(
+    'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
+    { maxZoom: 18,
+      attribution: '&copy; OpenStreetMap contributors'
+    } 
+  );
+
+  // Values to bind to Leaflet Directive
+  options = {
+    layers: [ this.LAYER_OSM ],
+    zoom: 8,
+    center: latLng([13.661714, -89.251530])
+  };
+  
+  constructor(private plantsService: PlantsService, private route: ActivatedRoute, private orgService: OrganizationsService, private zone: NgZone) {
+
+    Swal.fire({
+      allowOutsideClick: false,
+      type: 'info',
+      text: 'Espere por favor...'
     });
+    Swal.showLoading();
+
 
-    this.rows = [JSON.stringify(this.listData)];
+    this.plantsService.getAssets().subscribe(res => {
+      this.listData = res["assets"];
+    }, (err) => {
+      Swal.fire({
+        type: 'error',
+        title: 'Error en el servidor',
+        text: "No su pudo obtener la informacion"
+      });
+    });
 
+    if (localStorage.getItem("installedCapacityTotal_kW") == undefined){
+      this.plantsService.getInstalledCapacity().subscribe(res => {
+        this.totalMetersInstalled = res["installedCapacityTotal_kW"];
+        localStorage.setItem("totalMetersInstalled", this.totalMetersInstalled);
+      });
+    }
+    else {
+      this.totalMetersInstalled = localStorage.getItem("installedCapacityTotal_kW");
+    }
+    
+  
+  }
 
+
+  ngOnInit(): void {
+
+    setTimeout(()=>{ 
+      this.addMarkers();
+      Swal.close();
+    }, 1500);
+
+    
     var responsiveOptions: any[] = [
       ['screen and (max-width: 640px)', {
         seriesBarDistance: 5,
@@ -34,4 +118,48 @@ export class DashboardComponent implements OnInit {
 
   }
 
+  getAsset(id:string){
+    return observableOf(this.listData.find(e => e.id === id));
+  }
+
+  
+  addMarkers() {
+    for (const plant of this.listData) {
+      const lat = plant.latitud;
+      const long = plant.longitud;
+      const newMarker = marker(
+        [lat, long],
+        {icon: this.icon})
+        .bindPopup('<b>' + plant.name + '</b><br>Dirección: ' + plant.address)
+        .on('click', () => {
+          this.zone.run(() => {
+            this.sendPlantId(plant.id);
+          });
+        });
+      this.points.push(latLng([lat, long]));
+      this.markers.push(newMarker);
+    }
+  }
+
+  sendPlantId(id: string) {
+    this.plantId = id;
+    this.selectedPlant = this.listData.find(e => e.id === this.plantId);
+    console.log("selected plant");
+    console.log(this.selectedPlant);
+  }
+
+  onMapReady(map: Map) {
+    setTimeout(() => {
+      map.invalidateSize();
+    }, 0);
+
+    const bounds = latLngBounds(this.points);
+    map.fitBounds(bounds, {
+      padding: point(24, 24),
+      maxZoom: 10.5,
+      animate: true
+    });
+  }
+
+
 }

+ 15 - 12
src/app/components/login/login.component.html

@@ -3,33 +3,36 @@
     <div class="vertical-align-middle auth-main">
       <div class="auth-box">
         <div class="top">
-          <img alt="Inverlec" src="./assets/img/logo-inverlec.png">
+          <img alt="Inverlec" src="./assets/img/inverlec_logo.png">
         </div>
         <div class="card">
           <div class="header">
-            <p class="lead">Login to your account</p>
+            <p class="lead">Iniciar sesión con tu cuenta</p>
           </div>
           <div class="body">
-            <form class="form-auth-small ng-untouched ng-pristine ng-valid" [formGroup]="loginForm" (ngSubmit)="onSubmit()">
+            <form class="form-auth-small ng-untouched ng-pristine ng-valid" (ngSubmit)="login(f)" #f="ngForm" >
               <div class="form-group">
-                <label for="username">Username</label>
-                <input type="text" formControlName="username" class="form-control" [ngClass]="{ 'is-invalid': submitted && f.username.errors }" />
-                <div *ngIf="submitted && f.username.errors" class="invalid-feedback">
-                    <div *ngIf="f.username.errors.required">Username is required</div>
+                <label for="email">Correo electrónico</label>
+                
+                <input type="text" name="email" class="form-control" [ngClass]="{ 'is-invalid': submitted && f.controls['email'].errors }"
+                        [(ngModel)]="user.email"  required email />
+                <div *ngIf="submitted && f.controls['email'].errors" class="invalid-feedback">
+                    <div *ngIf="f.username.errors.required">Ingresar email</div>
                 </div>
               </div>
               <div class="form-group">
-                <label for="password">Password</label>
-                <input type="password" formControlName="password" class="form-control" [ngClass]="{ 'is-invalid': submitted && f.password.errors }" />
-                <div *ngIf="submitted && f.password.errors" class="invalid-feedback">
+                <label for="password">Contraseña</label>
+                <input type="password" name="password"  class="form-control" [ngClass]="{ 'is-invalid': submitted && f.controls['password'].errors }" 
+                        [(ngModel)]="user.password" required minlength="6" />
+                <div *ngIf="submitted && f.controls['password'].errors" class="invalid-feedback">
                     <div *ngIf="f.password.errors.required">Password is required</div>
                 </div>
               </div>
               <button [disabled]="loading" class="btn btn-primary">
                 <span *ngIf="loading" class="spinner-border spinner-border-sm mr-1"></span>
-                Login
+                Iniciar sesión
               </button>
-              <div *ngIf="error" class="alert alert-danger mt-3 mb-0">{{error}}</div>
+              <!--<div *ngIf="error" class="alert alert-danger mt-3 mb-0">{{error}}</div>-->
             </form>
           </div>
         </div>

+ 3 - 3
src/app/components/login/login.component.scss

@@ -26,10 +26,10 @@
   position: absolute;
   left: 0;
   top: 0;
-  width: 400px;
+  width: 450px;
   height: 100%;
   z-index: -1;
-  background: #173f80;
+  background: #f0f0f0;
 }
 
 .auth-main:after {
@@ -40,7 +40,7 @@
   width: 100%;
   height: 100%;
   z-index: -2;
-  background: #f0f0f0;
+  background: #223d7d;
   //background: url(../../assets/images/auth_bg.jpg) no-repeat top left fixed;
 }
 

+ 72 - 49
src/app/components/login/login.component.ts

@@ -1,67 +1,90 @@
 import { Component, OnInit } from '@angular/core';
-import { Router, ActivatedRoute } from '@angular/router';
-import { FormBuilder, FormGroup, Validators } from '@angular/forms';
-import { first } from 'rxjs/operators';
+import { Location } from '@angular/common';
 
-import { AuthenticationService } from '@app/services/authentication.service';
+import { Router, ActivatedRoute, NavigationEnd } from '@angular/router';
+import { NgForm } from '@angular/forms';
+
+import { User } from '../../models/user';
+import { AuthService } from '../../services/auth.service';
+
+import Swal from 'sweetalert2';
 
 @Component({
   selector: 'app-login',
   templateUrl: './login.component.html',
   styleUrls: ['./login.component.scss']
 })
-
 export class LoginComponent implements OnInit {
-    loginForm: FormGroup;
-    loading = false;
-    submitted = false;
-    returnUrl: string;
-    error = '';
-
-    constructor(
-        private formBuilder: FormBuilder,
-        private route: ActivatedRoute,
-        private router: Router,
-        private authenticationService: AuthenticationService
-    ) {
-        // redirect to home if already logged in
-        if (this.authenticationService.currentUserValue) {
-            this.router.navigate(['/']);
-        }
-    }
 
-    ngOnInit() {
-        this.loginForm = this.formBuilder.group({
-            username: ['', Validators.required],
-            password: ['', Validators.required]
-        });
+  user: User = new User();
+  recordarme = false;
+  returnUrl: string;
+  error_message: string;
+
+  constructor( private auth: AuthService,
+               private router: Router,
+               private route: ActivatedRoute,
+               private location: Location ) {
+
+              this.router.routeReuseStrategy.shouldReuseRoute = function(){
+                return false;
+              }
+
+              this.router.events.subscribe((evt) => {
+                if (evt instanceof NavigationEnd) {
+                  // trick the Router into believing it's last link wasn't previously loaded
+                  this.router.navigated = false;
+                  // if you need to scroll back to top, here is the right place
+                  window.scrollTo(0, 0);
+                }
+              });
+            }
 
-        // get return url from route parameters or default to '/'
-        this.returnUrl = this.route.snapshot.queryParams['returnUrl'] || '/';
+  ngOnInit() {
+    this.returnUrl = this.route.snapshot.queryParams['returnUrl'] || '/';
+    if ( localStorage.getItem('email') ) {
+      this.user.email = localStorage.getItem('email');
+      //this.recordarme = true;
     }
+  }
 
-    // convenience getter for easy access to form fields
-    get f() { return this.loginForm.controls; }
+  login( form: NgForm ) {
+    if (  form.invalid ) { return; }
 
-    onSubmit() {
-        this.submitted = true;
+    Swal.fire({
+      allowOutsideClick: false,
+      type: 'info',
+      text: 'Espere por favor...'
+    });
+    Swal.showLoading();
 
-        // stop here if form is invalid
-        if (this.loginForm.invalid) {
-            return;
+    this.auth.login( this.user )
+      .subscribe( resp => {
+
+        Swal.close();
+
+        if ( this.recordarme ) {
+          localStorage.setItem('email', this.user.email);
         }
 
-        this.loading = true;
-        this.authenticationService.login(this.f.username.value, this.f.password.value)
-            .pipe(first())
-            .subscribe(
-                data => {
-                    this.router.navigate([this.returnUrl]);
-                },
-                error => {
-                    console.log(error);
-                    this.error = error;
-                    this.loading = false;
-                });
-    }
+        //this.router.navigate([this.returnUrl]);
+        window.location.href="/";
+      }, (err) => {
+        if(err.error.error.message == "INVALID_EMAIL"){
+          this.error_message = "Correo electrónico inválido";
+        }
+        else if(err.error.error.message == "INVALID_PASSWORD"){
+          this.error_message = "Contraseña incorrecta";
+        }
+        else {
+          this.error_message = "Ha ocurrido un error";
+        }
+        Swal.fire({
+          type: 'error',
+          title: 'Error al autenticar',
+          text: this.error_message
+        });
+      });
+  }
+
 }

+ 11 - 0
src/app/components/plugins/bar-chart/bar-chart.component.html

@@ -0,0 +1,11 @@
+<div style="height: 400px">
+    <canvas baseChart id="measure-graph"
+      [datasets]="barChartData"
+      [labels]="barChartLabels"
+      [options]="barChartOptions"
+      [colors]="barChartColors"
+      [legend]="barChartLegend"
+      [chartType]="barChartType"
+      [plugins]="barChartPlugins">
+    </canvas>
+  </div>

+ 0 - 0
src/app/components/plugins/bar-chart/bar-chart.component.scss


+ 25 - 0
src/app/components/plugins/bar-chart/bar-chart.component.spec.ts

@@ -0,0 +1,25 @@
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { BarChartComponent } from './bar-chart.component';
+
+describe('BarChartComponent', () => {
+  let component: BarChartComponent;
+  let fixture: ComponentFixture<BarChartComponent>;
+
+  beforeEach(async(() => {
+    TestBed.configureTestingModule({
+      declarations: [ BarChartComponent ]
+    })
+    .compileComponents();
+  }));
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(BarChartComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});

+ 53 - 0
src/app/components/plugins/bar-chart/bar-chart.component.ts

@@ -0,0 +1,53 @@
+import { Component, OnInit, Input } from '@angular/core';
+import { Label, Color } from 'ng2-charts';
+import { ChartDataSets, ChartOptions } from 'chart.js';
+
+@Component({
+  selector: 'app-bar-chart',
+  templateUrl: './bar-chart.component.html',
+  styleUrls: ['./bar-chart.component.scss']
+})
+export class BarChartComponent implements OnInit {
+
+  @Input() public barChartData: ChartDataSets;
+  @Input() public barChartOptions: ChartOptions;
+  @Input() public barChartTitle: string;
+  @Input() public barChartLabels: Label[];
+  @Input() public barChartColors: Color[] = [
+    { // light-blue
+      backgroundColor: '#3c8dbc',
+      borderColor: '#3c8dbc',
+      pointBackgroundColor: '#3c8dbc',
+      pointBorderColor: '#fff',
+      pointHoverBackgroundColor: '#fff',
+      pointHoverBorderColor: '#3c8dbc'
+    },
+    { // orange
+      backgroundColor: '#00a65a',
+      borderColor: '#00a65a',
+      pointBackgroundColor: '#00a65a',
+      pointBorderColor: '#fff',
+      pointHoverBackgroundColor: '#fff',
+      pointHoverBorderColor: '#00a65a'
+    },
+    { // red
+      backgroundColor: '#f56954',
+      borderColor: '#f56954',
+      pointBackgroundColor: '#f56954',
+      pointBorderColor: '#fff',
+      pointHoverBackgroundColor: '#fff',
+      pointHoverBorderColor: '#f56954'
+    }
+  ];
+  @Input() public barChartLegend = true;
+  @Input() public barChartType:string;
+  @Input() public barChartPlugins = [];
+
+
+
+  constructor() { }
+
+  ngOnInit() {
+  }
+
+}

+ 1 - 0
src/app/components/plugins/doughnut-chart/doughnut-chart.component.html

@@ -0,0 +1 @@
+<p>doughnut-chart works!</p>

+ 0 - 0
src/app/components/plugins/doughnut-chart/doughnut-chart.component.scss


+ 25 - 0
src/app/components/plugins/doughnut-chart/doughnut-chart.component.spec.ts

@@ -0,0 +1,25 @@
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { DoughnutChartComponent } from './doughnut-chart.component';
+
+describe('DoughnutChartComponent', () => {
+  let component: DoughnutChartComponent;
+  let fixture: ComponentFixture<DoughnutChartComponent>;
+
+  beforeEach(async(() => {
+    TestBed.configureTestingModule({
+      declarations: [ DoughnutChartComponent ]
+    })
+    .compileComponents();
+  }));
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(DoughnutChartComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});

+ 15 - 0
src/app/components/plugins/doughnut-chart/doughnut-chart.component.ts

@@ -0,0 +1,15 @@
+import { Component, OnInit } from '@angular/core';
+
+@Component({
+  selector: 'app-doughnut-chart',
+  templateUrl: './doughnut-chart.component.html',
+  styleUrls: ['./doughnut-chart.component.scss']
+})
+export class DoughnutChartComponent implements OnInit {
+
+  constructor() { }
+
+  ngOnInit() {
+  }
+
+}

+ 10 - 16
src/app/components/plugins/maps/maps.component.html

@@ -1,23 +1,17 @@
-<div class="align-container">
-  <mat-expansion-panel>
-    <mat-expansion-panel-header>
-      <mat-panel-title>
-        Ubicaciones
-      </mat-panel-title>
-    </mat-expansion-panel-header>
-
-    <div class="container-fluid">
-      <div class="row">
-        <div class="col-md-8">
+<div class="container-fluid">
+  <div class="row">
+    <div class="col-md-8">
+      <div class= 'card border-success'>
+        <div class="card-body">
           <div style="height: 350px;" leaflet [leafletOptions]="options" [leafletLayers]="markers"
             (leafletMapReady)='onMapReady($event)'>
           </div>
         </div>
-        <div class="col-md-4">
-          <app-plant-detail [plantId]="plantId"></app-plant-detail>
-        </div>
-      </div>
+      </div> 
+    </div>
+    <div class="col-md-4">
+      <app-plant-detail [plantId]="plantId"></app-plant-detail>
     </div>
-  </mat-expansion-panel>
+  </div>
 </div>
 <br>

+ 5 - 5
src/app/components/plugins/maps/maps.component.ts

@@ -10,7 +10,7 @@ import { PlantsService } from 'src/app/services/plants.service';
 })
 export class MapsComponent implements OnInit {
 
-  listData: Plant[];
+  listData:any;
   markers: Layer[] = [];
   points: LatLng[] = [];
   plantId: number;
@@ -41,7 +41,7 @@ export class MapsComponent implements OnInit {
   };
 
   ngOnInit() {
-    this.plantsService.getPlants().subscribe(res => {
+    this.plantsService.getAssets().subscribe(res => {
       this.listData = res;
     });
     this.addMarkers();
@@ -50,12 +50,12 @@ export class MapsComponent implements OnInit {
   addMarkers() {
     for (const plant of this.listData) {
       const name = plant.name;
-      const lat = plant.latitude;
-      const long = plant.longitude;
+      const lat = plant.latitud;
+      const long = plant.longitud;
       const newMarker = marker(
         [lat, long],
         {icon: this.icon})
-        .bindPopup('<b>' + plant.name + '</b><br>Fecha de Instalación: ' + plant.installDate)
+        .bindPopup('<b>' + plant.name + '</b><br>Dirección: ' + plant.address)
         .on('click', () => {
           this.zone.run(() => {
             this.sendPlantId(plant.id);

+ 32 - 0
src/app/components/plugins/organization-cards/organization-cards.component.html

@@ -0,0 +1,32 @@
+<div class="row">
+  <div *ngIf="error; then thenBlock else elseBlock"></div>
+  <ng-template #thenBlock>
+    <div class="col-lg-12">
+      <div class= 'card border-danger'>
+        <div class="card-body">
+          Error en el servidor, no se pudo obtener el listado de organizaciones
+        </div>
+      </div>
+    </div>
+  </ng-template>
+  <ng-template #elseBlock>
+    <div *ngFor="let item of listOrganizations; index as i;" class="col-lg-4 col-md-4 col-sm-6">
+      <div class= 'card border-success'>
+        <div class="card-body">
+          <h5 class="card-title">{{item.name}}</h5>
+          <h6 class="card-subtitle mb-2 text-muted">{{item.city}}, {{item.country}}</h6>
+          <br>
+          <p class="card-text">
+            Nombre contacto: <b>{{item.contactName}}</b>
+            <br>
+            Numero contacto: <b>{{item.contactNumber}}</b>
+            <br>
+            Direccion: <b>{{item.address}}</b>
+          </p>
+          <a [routerLink]="['/assets']" [queryParams]="{ id: item.id }" href="#" class="btn btn-sm btn-primary float-right">Ir a plantas</a>
+        </div>
+      </div>
+    </div>
+  </ng-template>
+</div>
+<br>

+ 4 - 0
src/app/components/plugins/organization-cards/organization-cards.component.scss

@@ -0,0 +1,4 @@
+.card-title {
+  color: #ee964b;
+  font-weight: bold;
+}

+ 25 - 0
src/app/components/plugins/organization-cards/organization-cards.component.spec.ts

@@ -0,0 +1,25 @@
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { OrganizationCardsComponent } from './organization-cards.component';
+
+describe('OrganizationCardsComponent', () => {
+  let component: OrganizationCardsComponent;
+  let fixture: ComponentFixture<OrganizationCardsComponent>;
+
+  beforeEach(async(() => {
+    TestBed.configureTestingModule({
+      declarations: [ OrganizationCardsComponent ]
+    })
+    .compileComponents();
+  }));
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(OrganizationCardsComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});

+ 35 - 0
src/app/components/plugins/organization-cards/organization-cards.component.ts

@@ -0,0 +1,35 @@
+import { Component, OnInit } from '@angular/core';
+import { Organization } from 'src/app/models/organization';
+import { OrganizationsService } from 'src/app/services/organizations.service';
+import { RouterModule } from '@angular/router';
+
+@Component({
+  selector: 'app-organization-cards',
+  templateUrl: './organization-cards.component.html',
+  styleUrls: ['./organization-cards.component.scss']
+})
+export class OrganizationCardsComponent implements OnInit {
+  
+  listOrganizations:any;
+  error:boolean = false;
+  errorMessage:string;
+
+  constructor(private orgService: OrganizationsService) { }
+
+  ngOnInit() {
+
+    //});
+    this.orgService.getOrganizations().subscribe((res)=>{
+      this.listOrganizations = res["organizations"];
+    },
+    (err) => {
+      this.error = true;
+      this.errorMessage = err.message;
+    });
+      
+
+  }
+
+
+  
+}

+ 0 - 12
src/app/components/plugins/plant-detail/plant-detail.component.html

@@ -1,12 +0,0 @@
-<div class='plant-detail' *ngIf=plant>
-  <h2><i class="fa fa-bolt"></i> {{plant.name}} </h2>
-
-  <p class='h4'>País: {{plant.country}}</p>
-  <p class='h4'>Ciudad: {{plant.city}}</p>
-  <p class='h4'>Fecha de Instalación: {{plant.installDate}}</p>
-  <p class='h4'>Potencia Instalada: {{plant.installedCapacity}} kW</p>
-  <p class='h4'>Generación Total: kWh</p>
-  <p class='h4'>Generación 24-h: kWh</p>
-
-  <button class="btn bg-yellow btn-flat">Ir a Planta</button>
-</div>

+ 0 - 10
src/app/components/plugins/plant-detail/plant-detail.component.scss

@@ -1,10 +0,0 @@
-.detail-box {
-  border: none;
-  border-radius: 0;
-  box-shadow: none;
-}
-
-button {
-  position: absolute;
-  bottom: 0;
-}

+ 0 - 29
src/app/components/plugins/plant-detail/plant-detail.component.ts

@@ -1,29 +0,0 @@
-import { Component, OnInit, Input, OnChanges } from '@angular/core';
-import { PlantsService } from 'src/app/services/plants.service';
-import { Plant } from 'src/app/models/plant';
-
-@Component({
-  selector: 'app-plant-detail',
-  templateUrl: './plant-detail.component.html',
-  styleUrls: ['./plant-detail.component.scss']
-})
-export class PlantDetailComponent implements OnInit, OnChanges {
-
-  @Input() plantId: number;
-  plant: Plant;
-
-  id: number;
-
-  constructor(private plantsService: PlantsService) { }
-
-  ngOnInit() {
-
-  }
-
-  ngOnChanges() {
-    this.plantsService.getPlant(this.plantId).subscribe(res => {
-      this.plant = res;
-    });
-  }
-
-}

+ 19 - 4
src/app/components/plugins/plugins.module.ts

@@ -1,9 +1,11 @@
 import { NgModule } from "@angular/core";
 import { CommonModule } from "@angular/common";
 import { LeafletModule } from "@asymmetrik/ngx-leaflet";
+import { ChartsModule } from "ng2-charts";
+import { RouterModule } from '@angular/router';
+
 import { MapsComponent } from './maps/maps.component';
 import { PlantsStatusComponent } from './plants-status/plants-status.component';
-import { PlantDetailComponent } from "./plant-detail/plant-detail.component";
 import {
   MatButtonModule,
   MatInputModule,
@@ -19,8 +21,13 @@ import {
 
 } from '@angular/material';
 import {  } from '@angular/material/table';
+
 import { PlantsDatatablesComponent } from './plants-datatables/plants-datatables.component';
 import { WeatherCardComponent } from './weather-card/weather-card.component';
+import { BarChartComponent } from './bar-chart/bar-chart.component';
+import { PolarChartComponent } from './polar-chart/polar-chart.component';
+import { DoughnutChartComponent } from './doughnut-chart/doughnut-chart.component';
+import { OrganizationCardsComponent } from './organization-cards/organization-cards.component';
 
 /*import { BoxModule } from "angular-admin-lte";
 import { LineChartComponent } from "./line-chart/line-chart.component";
@@ -38,10 +45,13 @@ export const MQTT_SERVICE_OPTIONS: IMqttServiceOptions = {
 @NgModule({
   declarations: [
     MapsComponent,
-    PlantDetailComponent,
     PlantsStatusComponent,
     PlantsDatatablesComponent,
     WeatherCardComponent,
+    BarChartComponent,
+    PolarChartComponent,
+    DoughnutChartComponent,
+    OrganizationCardsComponent,
   ],
   imports: [
     CommonModule,
@@ -56,14 +66,19 @@ export const MQTT_SERVICE_OPTIONS: IMqttServiceOptions = {
     MatTableModule,
     MatPaginatorModule,
     MatProgressSpinnerModule,
-    MatSortModule
+    MatSortModule,
+    ChartsModule,
+    RouterModule
   ],
   exports: [
     MapsComponent,
-    PlantDetailComponent,
     PlantsStatusComponent,
     PlantsDatatablesComponent,
     WeatherCardComponent,
+    BarChartComponent,
+    PolarChartComponent,
+    OrganizationCardsComponent
+    
   ]
 })
 export class PluginsModule {}

+ 10 - 0
src/app/components/plugins/polar-chart/polar-chart.component.html

@@ -0,0 +1,10 @@
+<div style="height: 400px">
+  <canvas baseChart
+    [datasets]="polarChartData"
+    [labels]="polarChartLabels"
+    [options]="polarChartOptions"
+    [chartType]="polarChartType"
+    [legend]="polarChartLegend"
+    [plugins]="polarChartPlugins">
+  </canvas>
+</div>

+ 0 - 0
src/app/components/plugins/polar-chart/polar-chart.component.scss


+ 25 - 0
src/app/components/plugins/polar-chart/polar-chart.component.spec.ts

@@ -0,0 +1,25 @@
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { PolarChartComponent } from './polar-chart.component';
+
+describe('PolarChartComponent', () => {
+  let component: PolarChartComponent;
+  let fixture: ComponentFixture<PolarChartComponent>;
+
+  beforeEach(async(() => {
+    TestBed.configureTestingModule({
+      declarations: [ PolarChartComponent ]
+    })
+    .compileComponents();
+  }));
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(PolarChartComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});

+ 53 - 0
src/app/components/plugins/polar-chart/polar-chart.component.ts

@@ -0,0 +1,53 @@
+import { Component, OnInit, Input } from '@angular/core';
+import { Label, Color } from 'ng2-charts';
+import { ChartDataSets, ChartOptions } from 'chart.js';
+
+@Component({
+  selector: 'app-polar-chart',
+  templateUrl: './polar-chart.component.html',
+  styleUrls: ['./polar-chart.component.scss']
+})
+export class PolarChartComponent implements OnInit {
+
+  @Input() public polarChartData: ChartDataSets;
+  @Input() public polarChartOptions: ChartOptions;
+  @Input() public polarChartTitle: string;
+  @Input() public polarChartLabels: Label[];
+  @Input() public polarChartColors: Color[] = [
+    { // light-blue
+      backgroundColor: '#3c8dbc',
+      borderColor: '#3c8dbc',
+      pointBackgroundColor: '#3c8dbc',
+      pointBorderColor: '#fff',
+      pointHoverBackgroundColor: '#fff',
+      pointHoverBorderColor: '#3c8dbc'
+    },
+    { // orange
+      backgroundColor: '#00a65a',
+      borderColor: '#00a65a',
+      pointBackgroundColor: '#00a65a',
+      pointBorderColor: '#fff',
+      pointHoverBackgroundColor: '#fff',
+      pointHoverBorderColor: '#00a65a'
+    },
+    { // red
+      backgroundColor: '#f56954',
+      borderColor: '#f56954',
+      pointBackgroundColor: '#f56954',
+      pointBorderColor: '#fff',
+      pointHoverBackgroundColor: '#fff',
+      pointHoverBorderColor: '#f56954'
+    }
+  ];
+  @Input() public polarChartLegend = true;
+  @Input() public polarChartType = 'polarArea';
+  @Input() public polarChartPlugins = [];
+
+
+
+  constructor() { }
+
+  ngOnInit() {
+  }
+
+}

+ 6 - 6
src/app/components/plugins/weather-card/weather-card.component.html

@@ -1,20 +1,20 @@
 <div class="widget">
   <div class="row">
-    <div class="col-lg-6 col-md-6 col-xs-12">
+    <div class="col-lg-7 col-md-6 col-xs-12">
       <div class="date">
         {{currentDate}}
       </div>
       <div class="city">
-          San Salvador
+        {{cityName}}
       </div>
       <div class="date">
-        Parcialmente nublado
+        {{state}}
       </div>
     </div>
-    <div class="col-lg-6 col-md-6 col-xs-12">
+    <div class="col-lg-5 col-md-6 col-xs-12">
       <div class="temp">
-         <img src="https://s5.postimg.cc/yzcm7htyb/image.png" alt="" width="60">
-         27&deg;
+         <img src="assets/img/{{icon}}.png" alt="" width="60">
+         <span>{{temp}}°</span>
       </div>
     </div>
   </div>

+ 14 - 4
src/app/components/plugins/weather-card/weather-card.component.scss

@@ -3,10 +3,10 @@ div.widget
   position: relative;
   width: 100%;
   //margin: 150px auto;
-  background-color: #fcfdfd;
+  margin-top: 0;
+  background-color: #fff;
   border-radius: 9px;
   padding: 15px 20px;
-  box-shadow: 0px 31px 35px -26px #080c21;
 }
 
 div.date
@@ -28,10 +28,20 @@ div.city
 
 div.temp
 {
-  font-size: 5em;
   color: rgba(0,0,0,0.9);
   font-weight: 400;
-  padding: 10px;
+  display: inline-block;
+
+  span,
+  img {
+    display: inline-block;
+    margin-right: 10px;
+    padding-left: 0;
+    vertical-align: middle;
+    text-align: right;
+    margin-bottom: 20px;
+    font-size: 4em;
+  }
 }
 
 div.panel

+ 13 - 13
src/app/components/plugins/weather-card/weather-card.component.ts

@@ -22,9 +22,9 @@ export class WeatherCardComponent implements OnInit {
   maxTemp: number;
   minTemp: number;
   errorMessage: string;
-  cityName;
+  cityName: string;
   cityAdded = false;
-
+  icon: string;
   pipe = new DatePipe('es-ES')
   newDate = Date.now();
   currentDate = this.pipe.transform(this.newDate, 'fullDate')
@@ -35,17 +35,17 @@ export class WeatherCardComponent implements OnInit {
 
   ngOnInit() {
     this.weather.getWeather("San%20Salvador")
-         .pipe(first())
-         .subscribe((payload) => {
-           this.state = payload.weather[0].main;
-           this.temp = Math.ceil(payload.main.temp);
-           console.log(payload);
-         }, (err) => {
-           this.errorMessage = err.error.message;
-           setTimeout(() => {
-             this.errorMessage = '';
-           }, 3000);
-         });
+      .pipe(first())
+      .subscribe((payload) => {
+        this.cityName = payload.name
+        this.state = payload.weather[0].description;
+        this.temp = Math.ceil(payload.main.temp);
+        this.icon = payload.weather[0].icon;
+      }, (err) => {
+        this.errorMessage = err.error.message;
+        console.log("weather");
+        console.log(this.errorMessage);  
+      });
 
   }
 

+ 1 - 1
src/app/components/profile/profile.component.html

@@ -1 +1 @@
-<p>profile works!</p>
+<h2 class="floating-title">{{title}}</h2>

+ 2 - 2
src/app/components/shared/navbar/navbar.component.html

@@ -6,7 +6,7 @@
         <i class="material-icons text_align-center visible-on-sidebar-regular">more_vert</i>
         <i class="material-icons design_bullet-list-67 visible-on-sidebar-mini">view_list</i>
       </a>
-      <a class="navbar-brand">{{getTitle()}}</a>
+      <!--<a class="navbar-brand">{{getTitle()}}</a>-->
     </div>
     <button mat-raised-button class="navbar-toggler" type="button" (click)="sidebarToggle()">
       <span class="sr-only">Toggle navigation</span>
@@ -33,7 +33,7 @@
           </a>
         </li>
         <li class="nav-item">
-          <a class="nav-link" title="Logout" (click)="logout()" href="#">
+          <a class="nav-link" title="Logout" (click)="logout()" href="javascript:void(0)">
             <i class="material-icons">exit_to_app</i>
             <p>
               <span class="d-lg-none d-md-block">Logout</span>

+ 25 - 10
src/app/components/shared/navbar/navbar.component.ts

@@ -1,9 +1,10 @@
 import { Component, OnInit, ElementRef } from '@angular/core';
 import { ROUTES } from '../sidebar/sidebar.component';
 import {Location, LocationStrategy, PathLocationStrategy} from '@angular/common';
-import { Router } from '@angular/router';
-import { AuthenticationService } from 'src/app/services/authentication.service';
+import { Router, ActivatedRoute } from '@angular/router';
+//import { AuthenticationService } from 'src/app/services/authentication.service';
 import { AdminLayoutRoutes } from 'src/app/layouts/admin/admin.routing';
+import { AuthService } from '../../../services/auth.service';
 
 @Component({
   selector: 'app-navbar',
@@ -20,7 +21,7 @@ export class NavbarComponent implements OnInit {
     private toggleButton: any;
     private sidebarVisible: boolean;
     private sidebarMini: boolean;
-    constructor(location: Location,  private element: ElementRef, private router: Router, private authenticationService: AuthenticationService) {
+    constructor(location: Location,  private element: ElementRef, private router: Router, private auth: AuthService, private route: ActivatedRoute) {
       this.location = location;
       this.sidebarVisible = false;
       this.sidebarMini = false;
@@ -143,22 +144,36 @@ export class NavbarComponent implements OnInit {
     };
 
     logout() {
-      this.authenticationService.logout();
-      this.router.navigate(['/login']);
+      this.auth.logout();
+      this.router.navigateByUrl("login");
     }
 
     getTitle(){
       var titlee = this.location.prepareExternalUrl(this.location.path());
+      var component_local = this.router.url;
+      var main_title:string;
+
+      console.log(AdminLayoutRoutes)
+
       if(titlee.charAt(0) === '#'){
         titlee = titlee.slice( 1 );
       }
-
-      for(var item = 0; item < this.leTitles.length; item++){
-
+      var item=0
+      while( item < this.leTitles.length){
+        
         if("/"+this.leTitles[item].path === titlee){
-          return this.leTitles[item].data['title'];
+          main_title = this.leTitles[item].data['title'];
+          break;
         }
+        item++;
       }
-      return 'Dashboard';
+      console.log(main_title);
+      if (main_title === undefined) {
+        return 'Dashboard';
+      }
+      else {
+        return main_title;
+      }
+
     }
 }

+ 8 - 6
src/app/components/shared/sidebar/sidebar.component.html

@@ -4,7 +4,7 @@
       <img src="./assets/img/logo-inverlec2.png">
     </div>
   </a>
-  <a class="simple-text logo-normal" href="/">Plant viewer</a>
+  <a class="simple-text logo-normal" href="/">&nbsp;</a>
 </div>
 
 <div class="sidebar-wrapper">
@@ -40,14 +40,15 @@
           <p>{{menuItem.title}}</p>
         </a>
       </li>
+      <!--
       <li class="nav-item" routerlinkactive="active">
-        <!----><!---->
+        
         <a class="nav-link collapsed" data-toggle="collapse" href="#components" aria-expanded="false">
           <i class="material-icons">business</i>
           <p>Plantas<b class="caret"></b></p>
-        </a><!---->
+        </a>
         <div class="collapse" id="components" style="">
-          <ul class="nav"><!---->
+          <ul class="nav">
             <li class="nav-item" routerlinkactive="active">
               <a class="nav-link" href="#/components/buttons"><span class="sidebar-mini">B</span><span class="sidebar-normal">COCESNA ESTACION<br> EL SALVADOR</span></a>
             </li>
@@ -66,12 +67,13 @@
           </ul>
         </div>
       </li>
+      -->
       <hr>
     </ul>
   <div *ngIf="isMobileMenu()">
     <ul class="nav navbar-nav nav-mobile-menu-bottom">
       <li class="nav-item">
-          <a class="nav-link" title="Logout" (click)="logout()" href="#">
+          <a class="nav-link" title="Logout" (click)="logout()" href="javascript:void(0)">
               <i class="material-icons">exit_to_app</i>
               <p>
                   <span class="d-lg-none d-md-block">Logout</span>
@@ -80,4 +82,4 @@
       </li>
     </ul>
   </div>
-</div>
+</div>

+ 13 - 1
src/app/components/shared/sidebar/sidebar.component.ts

@@ -1,4 +1,6 @@
 import { Component, OnInit } from '@angular/core';
+import { AuthService } from '../../../services/auth.service';
+import { Router } from '@angular/router';
 
 declare const $: any;
 declare interface RouteInfo {
@@ -9,6 +11,9 @@ declare interface RouteInfo {
 }
 export const ROUTES: RouteInfo[] = [
     { path: '/dashboard', title: 'Dashboard',  icon: 'dashboard', class: '' },
+    { path: '/assets', title: 'Plantas',  icon: 'wb_sunny', class: '' },
+    { path: '/reports', title: 'Reportes',  icon: 'assignment', class: '' },
+    { path: '/profile', title: 'Perfil',  icon: 'person', class: '' },
     //{ path: '/profile', title: 'Perfil',  icon:'person', class: '' },
     /*{ path: '/table-list', title: 'Table List',  icon:'content_paste', class: '' },
     { path: '/typography', title: 'Typography',  icon:'library_books', class: '' },
@@ -26,15 +31,22 @@ export const ROUTES: RouteInfo[] = [
 export class SidebarComponent implements OnInit {
   menuItems: any[];
 
-  constructor() { }
+  constructor(private auth: AuthService, private router: Router) { }
 
   ngOnInit() {
     this.menuItems = ROUTES.filter(menuItem => menuItem);
   }
+  
   isMobileMenu() {
       if ($(window).width() > 991) {
           return false;
       }
       return true;
   };
+
+  logout() {
+    this.auth.logout();
+    this.router.navigateByUrl("login");
+  };
+
 }

+ 119 - 85
src/app/data/plants.data.ts

@@ -4,188 +4,222 @@ export const plantsData: Plant[] = [
   {
     id: 0,
     name: 'Exozent',
-    state: true,
-    installDate: '2018-06-06',
+    //state: true,
+    //installDate: '2018-06-06',
     country: 'El Salvador',
     city: 'Zacatecoluca',
-    latitude: 13.49,
-    longitude: -88.95,
-    installedCapacity: 60
+    latitud: 13.49,
+    longitud: -88.95,
+    installedCapacity_kW: 60,
+    address: '-',
+    organizationId: '1'
   },
   {
     id: 1,
     name: 'Norsup',
-    state: true,
-    installDate: '2019-01-13',
+    //state: true,
+    //installDate: '2019-01-13',
     country: 'El Salvador',
     city: 'San Miguel',
-    latitude: 13.5,
-    longitude: -88.93,
-    installedCapacity: 239
+    latitud: 13.5,
+    longitud: -88.93,
+    installedCapacity_kW: 239,
+    address: '-',
+    organizationId: '1'
   },
   {
     id: 2,
     name: 'Digique',
-    state: true,
-    installDate: '2018-08-20',
+    //state: true,
+    //installDate: '2018-08-20',
     country: 'El Salvador',
     city: 'San Salvador',
-    latitude: 13.66,
-    longitude: -88.93,
-    installedCapacity: 269
+    latitud: 13.66,
+    longitud: -88.93,
+    installedCapacity_kW: 269,
+    address: '-',
+    organizationId: '1'
   },
   {
     id: 3,
     name: 'Zeam',
-    state: false,
-    installDate: '2018-05-14',
+    //state: false,
+    //installDate: '2018-05-14',
     country: 'El Salvador',
     city: 'La Union',
-    latitude: 13.44,
-    longitude: -88.99,
-    installedCapacity: 21
+    latitud: 13.44,
+    longitud: -88.99,
+    installedCapacity_kW: 21,
+    address: '-',
+    organizationId: '1'
   },
   {
     id: 4,
     name: 'Bitrex',
-    state: true,
-    installDate: '2019-05-31',
+    //state: true,
+    //installDate: '2019-05-31',
     country: 'El Salvador',
     city: 'Zacatecoluca',
-    latitude: 13.47,
-    longitude: -88.85,
-    installedCapacity: 77
+    latitud: 13.47,
+    longitud: -88.85,
+    installedCapacity_kW: 77,
+    address: '-',
+    organizationId: '1'
   },
   {
     id: 5,
     name: 'Polaria',
-    state: false,
-    installDate: '2018-11-27',
+    //state: false,
+    //installDate: '2018-11-27',
     country: 'El Salvador',
     city: 'San Miguel',
-    latitude: 13.54,
-    longitude: -88.95,
-    installedCapacity: 56
+    latitud: 13.54,
+    longitud: -88.95,
+    installedCapacity_kW: 56,
+    address: '-',
+    organizationId: '1'
   },
   {
     id: 6,
     name: 'Velity',
-    state: false,
-    installDate: '2018-09-11',
+    //state: false,
+    //installDate: '2018-09-11',
     country: 'El Salvador',
     city: 'La Union',
-    latitude: 13.63,
-    longitude: -89.03,
-    installedCapacity: 111
+    latitud: 13.63,
+    longitud: -89.03,
+    installedCapacity_kW: 111,
+    address: '-',
+    organizationId: '1'
   },
   {
     id: 7,
     name: 'Farmex',
-    state: true,
-    installDate: '2018-11-05',
+    //state: true,
+    //installDate: '2018-11-05',
     country: 'El Salvador',
     city: 'San Vicente',
-    latitude: 13.62,
-    longitude: -89.01,
-    installedCapacity: 140
+    latitud: 13.62,
+    longitud: -89.01,
+    installedCapacity_kW: 140,
+    address: '-',
+    organizationId: '1'
   },
   {
     id: 8,
     name: 'Wazzu',
-    state: false,
-    installDate: '2019-05-04',
+    //state: false,
+    //installDate: '2019-05-04',
     country: 'El Salvador',
     city: 'San Vicente',
-    latitude: 13.64,
-    longitude: -88.86,
-    installedCapacity: 4
+    latitud: 13.64,
+    longitud: -88.86,
+    installedCapacity_kW: 4,
+    address: '-',
+    organizationId: '1'
   },
   {
     id: 9,
     name: 'Olympix',
-    state: true,
-    installDate: '2018-06-10',
+    //state: true,
+    //installDate: '2018-06-10',
     country: 'El Salvador',
     city: 'San Miguel',
-    latitude: 13.6,
-    longitude: -88.82,
-    installedCapacity: 131
+    latitud: 13.6,
+    longitud: -88.82,
+    installedCapacity_kW: 131,
+    address: '-',
+    organizationId: '1'
   },
   {
     id: 10,
     name: 'Fossiel',
-    state: false,
-    installDate: '2018-02-19',
+    //state: false,
+    //installDate: '2018-02-19',
     country: 'El Salvador',
     city: 'Zacatecoluca',
-    latitude: 13.62,
-    longitude: -88.92,
-    installedCapacity: 69
+    latitud: 13.62,
+    longitud: -88.92,
+    installedCapacity_kW: 69,
+    address: '-',
+    organizationId: '1'
   },
   {
     id: 11,
     name: 'Immunics',
-    state: true,
-    installDate: '2018-10-17',
+    //state: true,
+    //installDate: '2018-10-17',
     country: 'El Salvador',
     city: 'Zacatecoluca',
-    latitude: 13.62,
-    longitude: -88.88,
-    installedCapacity: 136
+    latitud: 13.62,
+    longitud: -88.88,
+    installedCapacity_kW: 136,
+    address: '-',
+    organizationId: '1'
   },
   {
     id: 12,
     name: 'Uberlux',
-    state: false,
-    installDate: '2019-02-28',
+    //state: false,
+    //installDate: '2019-02-28',
     country: 'El Salvador',
     city: 'San Vicente',
-    latitude: 13.52,
-    longitude: -88.94,
-    installedCapacity: 228
+    latitud: 13.52,
+    longitud: -88.94,
+    installedCapacity_kW: 228,
+    address: '-',
+    organizationId: '1'
   },
   {
     id: 13,
     name: 'Vitricomp',
-    state: false,
-    installDate: '2018-05-11',
+    //state: false,
+    //installDate: '2018-05-11',
     country: 'El Salvador',
     city: 'La Union',
-    latitude: 13.48,
-    longitude: -88.76,
-    installedCapacity: 118
+    latitud: 13.48,
+    longitud: -88.76,
+    installedCapacity_kW: 118,
+    address: '-',
+    organizationId: '1'
   },
   {
     id: 14,
     name: 'Cormoran',
-    state: false,
-    installDate: '2018-07-10',
+    //state: false,
+    //installDate: '2018-07-10',
     country: 'El Salvador',
     city: 'San Salvador',
-    latitude: 13.45,
-    longitude: -88.89,
-    installedCapacity: 14
+    latitud: 13.45,
+    longitud: -88.89,
+    installedCapacity_kW: 14,
+    address: '-',
+    organizationId: '1'
   },
   {
     id: 15,
     name: 'Quarmony',
-    state: false,
-    installDate: '2019-03-27',
+    //state: false,
+    //installDate: '2019-03-27',
     country: 'El Salvador',
     city: 'San Miguel',
-    latitude: 13.64,
-    longitude: -88.74,
-    installedCapacity: 263
+    latitud: 13.64,
+    longitud: -88.74,
+    installedCapacity_kW: 263,
+    address: '-',
+    organizationId: '1'
   },
   {
     id: 16,
     name: 'Bostonic',
-    state: false,
-    installDate: '2019-02-17',
+    //state: false,
+    //installDate: '2019-02-17',
     country: 'El Salvador',
     city: 'Zacatecoluca',
-    latitude: 13.47,
-    longitude: -88.82,
-    installedCapacity: 204
+    latitud: 13.47,
+    longitud: -88.82,
+    installedCapacity_kW: 204,
+    address: '-',
+    organizationId: '1'
   }
 ];

+ 0 - 31
src/app/helpers/auth.guard.ts

@@ -1,31 +0,0 @@
-import { Injectable } from '@angular/core';
-import { Router, CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
-
-import { AuthenticationService } from '@app/services/authentication.service';
-
-@Injectable({ providedIn: 'root' })
-export class AuthGuard implements CanActivate {
-    constructor(
-        private router: Router,
-        private authenticationService: AuthenticationService
-    ) { }
-
-    canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
-        const currentUser = this.authenticationService.currentUserValue;
-        if (currentUser) {
-            // check if route is restricted by role
-            if (route.data.roles && route.data.roles.indexOf(currentUser.role) === -1) {
-                // role not authorised so redirect to home page
-                this.router.navigate(['/']);
-                return false;
-            }
-
-            // authorised so return true
-            return true;
-        }
-
-        // not logged in so redirect to login page with the return url
-        this.router.navigate(['/login'], { queryParams: { returnUrl: state.url } });
-        return false;
-    }
-}

+ 0 - 24
src/app/helpers/error.interceptor.ts

@@ -1,24 +0,0 @@
-import { Injectable } from '@angular/core';
-import { HttpRequest, HttpHandler, HttpEvent, HttpInterceptor } from '@angular/common/http';
-import { Observable, throwError } from 'rxjs';
-import { catchError } from 'rxjs/operators';
-
-import { AuthenticationService } from '../services/authentication.service';
-
-@Injectable()
-export class ErrorInterceptor implements HttpInterceptor {
-    constructor(private authenticationService: AuthenticationService) { }
-
-    intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
-        return next.handle(request).pipe(catchError(err => {
-            if ([401, 403].indexOf(err.status) !== -1) {
-                // auto logout if 401 Unauthorized or 403 Forbidden response returned from api
-                this.authenticationService.logout();
-                location.reload(true);
-            }
-
-            const error = err.error.message || err.statusText;
-            return throwError(error);
-        }))
-    }
-}

+ 0 - 112
src/app/helpers/fake-backend.ts

@@ -1,112 +0,0 @@
-import { Injectable } from '@angular/core';
-import { HttpRequest, HttpResponse, HttpHandler, HttpEvent, HttpInterceptor, HTTP_INTERCEPTORS } from '@angular/common/http';
-import { Observable, of, throwError } from 'rxjs';
-import { delay, mergeMap, materialize, dematerialize } from 'rxjs/operators';
-
-import { User, Role } from '../models';
-
-const users: User[] = [
-    { id: 1, username: 'admin', password: 'admin', firstName: 'Admin', lastName: 'User', role: Role.Admin },
-    { id: 2, username: 'user', password: 'user', firstName: 'Normal', lastName: 'User', role: Role.User }
-];
-
-@Injectable()
-export class FakeBackendInterceptor implements HttpInterceptor {
-    intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
-        const { url, method, headers, body } = request;
-
-        // wrap in delayed observable to simulate server api call
-        return of(null)
-            .pipe(mergeMap(handleRoute))
-            .pipe(materialize()) // call materialize and dematerialize to ensure delay even if an error is thrown (https://github.com/Reactive-Extensions/RxJS/issues/648)
-            .pipe(delay(500))
-            .pipe(dematerialize());
-
-        function handleRoute() {
-            switch (true) {
-                case url.endsWith('/users/authenticate') && method === 'POST':
-                    return authenticate();
-                case url.endsWith('/users') && method === 'GET':
-                    return getUsers();
-                case url.match(/\/users\/\d+$/) && method === 'GET':
-                    return getUserById();
-                default:
-                    // pass through any requests not handled above
-                    return next.handle(request);
-            }
-
-        }
-
-        // route functions
-
-        function authenticate() {
-            const { username, password } = body;
-            const user = users.find(x => x.username === username && x.password === password);
-            if (!user) return error('Username or password is incorrect');
-            return ok({
-                id: user.id,
-                username: user.username,
-                firstName: user.firstName,
-                lastName: user.lastName,
-                role: user.role,
-                token: `fake-jwt-token.${user.id}`
-            });
-        }
-
-        function getUsers() {
-            if (!isAdmin()) return unauthorized();
-            return ok(users);
-        }
-
-        function getUserById() {
-            if (!isLoggedIn()) return unauthorized();
-
-            // only admins can access other user records
-            if (!isAdmin() && currentUser().id !== idFromUrl()) return unauthorized();
-
-            const user = users.find(x => x.id === idFromUrl());
-            return ok(user);
-        }
-
-        // helper functions
-
-        function ok(body) {
-            return of(new HttpResponse({ status: 200, body }));
-        }
-
-        function unauthorized() {
-            return throwError({ status: 401, error: { message: 'unauthorized' } });
-        }
-
-        function error(message) {
-            return throwError({ status: 400, error: { message } });
-        }
-
-        function isLoggedIn() {
-            const authHeader = headers.get('Authorization') || '';
-            return authHeader.startsWith('Bearer fake-jwt-token');
-        }
-
-        function isAdmin() {
-            return isLoggedIn() && currentUser().role === Role.Admin;
-        }
-
-        function currentUser() {
-            if (!isLoggedIn()) return;
-            const id = parseInt(headers.get('Authorization').split('.')[1]);
-            return users.find(x => x.id === id);
-        }
-
-        function idFromUrl() {
-            const urlParts = url.split('/');
-            return parseInt(urlParts[urlParts.length - 1]);
-        }
-    }
-}
-
-export const fakeBackendProvider = {
-    // use fake backend in place of Http service for backend-less development
-    provide: HTTP_INTERCEPTORS,
-    useClass: FakeBackendInterceptor,
-    multi: true
-};

+ 0 - 4
src/app/helpers/index.ts

@@ -1,4 +0,0 @@
-export * from './auth.guard';
-export * from './error.interceptor';
-export * from './fake-backend';
-export * from './jwt.interceptor';

+ 0 - 27
src/app/helpers/jwt.interceptor.ts

@@ -1,27 +0,0 @@
-import { Injectable } from '@angular/core';
-import { HttpRequest, HttpHandler, HttpEvent, HttpInterceptor } from '@angular/common/http';
-import { Observable } from 'rxjs';
-
-import { environment } from '@environments/environment';
-import { AuthenticationService } from '@app/services/authentication.service';
-
-@Injectable()
-export class JwtInterceptor implements HttpInterceptor {
-    constructor(private authenticationService: AuthenticationService) { }
-
-    intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
-        // add auth header with jwt if user is logged in and request is to api url
-        const currentUser = this.authenticationService.currentUserValue;
-        const isLoggedIn = currentUser && currentUser.token;
-        const isApiUrl = request.url.startsWith(environment.apiUrl);
-        if (isLoggedIn && isApiUrl) {
-            request = request.clone({
-                setHeaders: {
-                    Authorization: `Bearer ${currentUser.token}`
-                }
-            });
-        }
-
-        return next.handle(request);
-    }
-}

+ 21 - 2
src/app/layouts/admin/admin.module.ts

@@ -3,9 +3,15 @@ import { NgModule } from '@angular/core';
 import { RouterModule } from '@angular/router';
 import { CommonModule } from '@angular/common';
 import { FormsModule, ReactiveFormsModule } from '@angular/forms';
+import { LeafletModule } from "@asymmetrik/ngx-leaflet";
+import { ChartsModule } from 'ng2-charts';
+
+
+
 import { AdminLayoutRoutes } from './admin.routing';
 import { DashboardComponent } from '../../components/dashboard/dashboard.component';
 import { ProfileComponent } from '../../components/profile/profile.component';
+import { AssetsComponent } from '../../components/assets/assets.component';
 
 import { PluginsModule } from '../../components/plugins/plugins.module';
 
@@ -16,7 +22,12 @@ import {
   MatFormFieldModule,
   MatTooltipModule,
   MatSelectModule,
-  MatExpansionModule
+  MatExpansionModule,
+  MatTableModule,
+  MatPaginatorModule,
+  MatProgressSpinnerModule,
+  MatSortModule
+
 } from '@angular/material';
 
 @NgModule({
@@ -31,11 +42,19 @@ import {
     MatInputModule,
     MatSelectModule,
     MatTooltipModule,
+    MatExpansionModule,
+    MatTableModule,
+    MatPaginatorModule,
+    MatProgressSpinnerModule,
+    MatSortModule,
     PluginsModule,
+    LeafletModule,
+    ChartsModule
   ],
   declarations: [
     DashboardComponent,
-    ProfileComponent
+    ProfileComponent,
+    AssetsComponent,
   ]
 })
 

+ 7 - 1
src/app/layouts/admin/admin.routing.ts

@@ -2,6 +2,7 @@ import { Routes } from '@angular/router';
 
 import { DashboardComponent } from '../../components/dashboard/dashboard.component';
 import { ProfileComponent } from '../../components/profile/profile.component';
+import { AssetsComponent } from '@app/components/assets/assets.component';
 /*
 import { TableListComponent } from '../../table-list/table-list.component';
 import { TypographyComponent } from '../../typography/typography.component';
@@ -18,7 +19,12 @@ export const AdminLayoutRoutes: Routes = [
   { path: 'profile',
     component: ProfileComponent,
     data: {title: "Perfil de usuario"}
-  }
+  },
+  { path: 'assets', 
+    component: AssetsComponent,
+    data: {title: "Listado de plantas"}
+  },
+
   /*
   { path: 'table-list',     component: TableListComponent },
   { path: 'typography',     component: TypographyComponent },

+ 1 - 0
src/app/models/index.ts

@@ -1,3 +1,4 @@
 export * from './role';
 export * from './user';
 export * from './plant';
+export * from './measure';

+ 0 - 0
src/app/data/measures.ts → src/app/models/measure.ts


+ 11 - 0
src/app/models/organization.ts

@@ -0,0 +1,11 @@
+import { Observable } from 'rxjs';
+
+export interface Organization {
+    id: string;
+    name: string;
+    contactName: string;
+    contactNumber: number;
+    country: string;
+    city: string;
+    address: string;
+}

+ 7 - 5
src/app/models/plant.ts

@@ -1,15 +1,17 @@
 import { Observable } from 'rxjs';
 
 export interface Plant {
+
     id: number;
     name: string;
-    state: boolean;
-    installDate: string;
+    organizationId: string;
     country: string;
     city: string;
-    latitude: number;
-    longitude: number;
-    installedCapacity: number;
+    address:string;
+    installedCapacity_kW: number;
+    latitud: number;
+    longitud: number;
+    //state: boolean;
 }
 
 export abstract class PlantData {

+ 6 - 6
src/app/models/user.ts

@@ -1,15 +1,15 @@
 import { Role } from "./role";
 
 export class User {
-    id: number;
-    username: string;
+    email: string;
     password: string;
-    firstName: string;
-    lastName: string;
-    role: Role;
+    firstName?: string;
+    lastName?: string;
+    uniqueid?: number;
+    role?: Role;
     token?: string;
     birthdate?: Date;
-    email?: string;
+    username?: string;
     address?: string;
     city?: string;
     country?: string;

+ 59 - 0
src/app/services/assets/assets.service.ts

@@ -0,0 +1,59 @@
+import { Injectable } from '@angular/core';
+import { Organization } from '../../models/organization';
+import { Plant } from '../../models/plant';
+
+import { of as observableOf, Observable, throwError } from 'rxjs';
+import { HttpClient, HttpHeaders } from '@angular/common/http';
+import { retry, catchError, map, timeout } from 'rxjs/operators';
+
+import { environment } from '@environments/environment';
+
+@Injectable({
+  providedIn: 'root'
+})
+export class AssetsService {
+
+  time:number = 10000;
+
+  constructor(private http: HttpClient) {
+  }
+
+  getAssets() {
+    return this.http.get(`${environment.api2Url}/users/api_v1/movies`)
+    .pipe(
+      timeout(this.time),
+      map(response =>{
+        console.log(response);
+        return response;
+      }),
+      catchError(this.errorHandl)
+    )
+  }
+  
+  getAssetsId() {
+    return this.http.get(`${environment.api2Url}/users/api_v1/movies/1`)
+    .pipe(
+      timeout(this.time),
+      map(response =>{
+        console.log(response);
+        return response;
+      }),
+      catchError(this.errorHandl)
+    )
+  }
+  
+
+  errorHandl(error) {
+    let errorMessage = '';
+    if(error.error instanceof ErrorEvent) {
+      // Get client-side error
+      errorMessage = error.error.message;
+    } else {
+      // Get server-side error
+      errorMessage = `Error Code: ${error.status}\nMessage: ${error.message}`;
+    }
+    console.log(error);
+    return throwError(errorMessage);
+ }
+
+}

+ 12 - 0
src/app/services/auth.service.spec.ts

@@ -0,0 +1,12 @@
+import { TestBed } from '@angular/core/testing';
+
+import { AuthService } from './auth.service';
+
+describe('AuthService', () => {
+  beforeEach(() => TestBed.configureTestingModule({}));
+
+  it('should be created', () => {
+    const service: AuthService = TestBed.get(AuthService);
+    expect(service).toBeTruthy();
+  });
+});

+ 121 - 0
src/app/services/auth.service.ts

@@ -0,0 +1,121 @@
+import { Injectable } from '@angular/core';
+import { HttpClient } from '@angular/common/http';
+import { User } from '../models/user';
+
+import { map } from 'rxjs/operators';
+
+@Injectable({
+  providedIn: 'root'
+})
+export class AuthService {
+
+  private url = 'https://www.googleapis.com/identitytoolkit/v3/relyingparty';
+  private apikey = 'AIzaSyDanKihOdPD7MgARSec7_B7NtMcSSJbu4Q';
+
+  userToken: string;
+
+  // Crear nuevo user
+  // https://www.googleapis.com/identitytoolkit/v3/relyingparty/signupNewUser?key=[API_KEY]
+
+
+  // Login
+  // https://www.googleapis.com/identitytoolkit/v3/relyingparty/verifyPassword?key=[API_KEY]
+
+
+  constructor( private http: HttpClient ) {
+    this.leerToken();
+  }
+
+
+  logout() {
+    localStorage.removeItem('token');
+  }
+
+  login( user: User ) {
+
+    console.log(user);
+    const authData = {
+      email: user.email,
+      password: user.password,
+      returnSecureToken: true
+    };
+
+    return this.http.post(
+      `${ this.url }/verifyPassword?key=${ this.apikey }`,
+      authData
+    ).pipe(
+      map( resp => {
+        this.guardarToken( resp['idToken'] );
+        return resp;
+      })
+    );
+
+  }
+
+  nuevouser( user: User ) {
+
+    const authData = {
+      ...user,
+      returnSecureToken: true
+    };
+
+    return this.http.post(
+      `${ this.url }/signupNewUser?key=${ this.apikey }`,
+      authData
+    ).pipe(
+      map( resp => {
+        this.guardarToken( resp['idToken'] );
+        return resp;
+      })
+    );
+
+  }
+
+
+  private guardarToken( idToken: string ) {
+
+    this.userToken = idToken;
+    localStorage.setItem('token', idToken);
+
+    let hoy = new Date();
+    hoy.setSeconds( 3600 );
+
+    localStorage.setItem('expira', hoy.getTime().toString() );
+
+
+  }
+
+  leerToken() {
+
+    if ( localStorage.getItem('token') ) {
+      this.userToken = localStorage.getItem('token');
+    } else {
+      this.userToken = '';
+    }
+
+    return this.userToken;
+
+  }
+
+
+  estaAutenticado(): boolean {
+
+    if ( this.userToken.length < 2 ) {
+      return false;
+    }
+
+    const expira = Number(localStorage.getItem('expira'));
+    const expiraDate = new Date();
+    expiraDate.setTime(expira);
+
+    if ( expiraDate > new Date() ) {
+      return true;
+    } else {
+      return false;
+    }
+
+
+  }
+
+
+}

+ 16 - 34
src/app/services/authentication.service.ts

@@ -1,43 +1,25 @@
 import { Injectable } from '@angular/core';
-import { HttpClient } from '@angular/common/http';
-import { BehaviorSubject, Observable } from 'rxjs';
-import { map } from 'rxjs/operators';
+import { Router, CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
 
-import { environment } from '@environments/environment';
-import { User } from '@app/models';
+import { AuthService } from '../services/auth.service';
 
-@Injectable({ providedIn: 'root' })
-export class AuthenticationService {
-    private currentUserSubject: BehaviorSubject<User>;
-    public currentUser: Observable<User>;
+@Injectable({
+  providedIn: 'root'
+})
+export class AuthGuard implements CanActivate {
 
-    constructor(private http: HttpClient) {
-        this.currentUserSubject = new BehaviorSubject<User>(JSON.parse(localStorage.getItem('currentUser')));
-        this.currentUser = this.currentUserSubject.asObservable();
-    }
-
-    public get currentUserValue(): User {
-        return this.currentUserSubject.value;
-    }
+  constructor( private auth: AuthService,
+               private router: Router) {}
 
-    login(username: string, password: string) {
-        return this.http.post<any>(`${environment.apiUrl}/users/authenticate`, { username, password })
-            .pipe(map(user => {
-                // login successful if there's a jwt token in the response
-                if (user && user.token) {
-                    // store user details and jwt token in local storage to keep user logged in between page refreshes
-                    localStorage.setItem('currentUser', JSON.stringify(user));
-                    this.currentUserSubject.next(user);
-                }
+  canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean  {
 
-                return user;
-            }));
+    if ( this.auth.estaAutenticado() ) {
+      return true;
+    } else {
+      this.router.navigate(['login'], { queryParams: { returnUrl: state.url }});
+      return false;
     }
+ 
+  }
 
-    logout() {
-        // remove user from local storage to log user out
-        localStorage.removeItem('currentUser');
-        this.currentUserSubject.next(null);
-    }
-    
 }

+ 78 - 0
src/app/services/logs.service.ts

@@ -0,0 +1,78 @@
+import { Injectable } from '@angular/core';
+import { Organization } from '../models/organization';
+import { Plant } from '../models/plant';
+
+import { of as observableOf, Observable, throwError } from 'rxjs';
+import { HttpClient, HttpHeaders } from '@angular/common/http';
+import { retry, catchError, map, timeout } from 'rxjs/operators';
+
+import { environment } from '@environments/environment';
+
+@Injectable({
+  providedIn: 'root'
+})
+export class LogsService {
+
+  time:number = 10000;
+
+  constructor(private http: HttpClient) {
+  }
+
+  getEnergyProducedByDay() {
+    return this.http.get(`${environment.apiUrl}/logs/energyProduced/1D`)
+    .pipe(
+      timeout(this.time),
+      map(response =>{
+        return response;
+      }),
+      catchError(this.errorHandl)
+    )
+  }
+
+  getEnergyProducedByWeek() {
+    return this.http.get(`${environment.apiUrl}/logs/energyProduced/7D`)
+    .pipe(
+      timeout(this.time),
+      map(response =>{
+        return response;
+      }),
+      catchError(this.errorHandl)
+    )
+  }
+  
+  getEnergyProducedByMonth() {
+    return this.http.get(`${environment.apiUrl}/logs/energyProduced/1M`)
+    .pipe(
+      timeout(this.time),
+      map(response =>{
+        return response;
+      }),
+      catchError(this.errorHandl)
+    )
+  }
+
+  getEnergyProducedByYear() {
+    return this.http.get(`${environment.apiUrl}/logs/energyProduced/YTD`)
+    .pipe(
+      timeout(this.time),
+      map(response =>{
+        return response;
+      }),
+      catchError(this.errorHandl)
+    )
+  }
+
+  errorHandl(error) {
+    let errorMessage = '';
+    if(error.error instanceof ErrorEvent) {
+      // Get client-side error
+      errorMessage = error.error.message;
+    } else {
+      // Get server-side error
+      errorMessage = `Error Code: ${error.status}\nMessage: ${error.message}`;
+    }
+    console.log(error);
+    return throwError(errorMessage);
+ }
+
+}

+ 12 - 0
src/app/services/measures.service.spec.ts

@@ -0,0 +1,12 @@
+import { TestBed } from '@angular/core/testing';
+
+import { MeasuresService } from './measures.service';
+
+describe('MeasuresService', () => {
+  beforeEach(() => TestBed.configureTestingModule({}));
+
+  it('should be created', () => {
+    const service: MeasuresService = TestBed.get(MeasuresService);
+    expect(service).toBeTruthy();
+  });
+});

+ 20 - 0
src/app/services/measures.service.ts

@@ -0,0 +1,20 @@
+import { measures } from 'src/app/data/measures.data';
+import { Injectable } from '@angular/core';
+import { Measure, MeasureData } from 'src/app/models/measure';
+import { of as observableOf, Observable } from 'rxjs';
+
+@Injectable({
+  providedIn: 'root'
+})
+export class MeasuresService extends MeasureData {
+
+  private measData: Measure[] = measures;
+
+  constructor() {
+    super();
+  }
+
+  getMeasures(): Observable<Measure[]> {
+    return observableOf(this.measData);
+  }
+}

+ 12 - 0
src/app/services/organizations.service.spec.ts

@@ -0,0 +1,12 @@
+import { TestBed } from '@angular/core/testing';
+
+import { OrganizationsService } from './organizations.service';
+
+describe('OrganizationsService', () => {
+  beforeEach(() => TestBed.configureTestingModule({}));
+
+  it('should be created', () => {
+    const service: OrganizationsService = TestBed.get(OrganizationsService);
+    expect(service).toBeTruthy();
+  });
+});

+ 123 - 0
src/app/services/organizations.service.ts

@@ -0,0 +1,123 @@
+import { Injectable } from '@angular/core';
+import { Organization } from '../models/organization';
+import { of as observableOf, Observable, throwError } from 'rxjs';
+import { HttpClient, HttpHeaders } from '@angular/common/http';
+import { retry, catchError, map, timeout } from 'rxjs/operators';
+
+import { environment } from '@environments/environment';
+
+
+@Injectable({
+  providedIn: 'root'
+})
+export class OrganizationsService {
+
+  private listData: Organization[];
+
+  constructor(private http: HttpClient) {}
+
+  httpOptions = {
+    headers: new HttpHeaders({
+      'Content-Type': 'application/json; charset=utf-8',
+      'Access-Control-Allow-Origin': '*',
+    })
+  }
+ 
+  getOrganizations(): Observable<any> {
+    return this.http.get<any>(`${environment.apiUrl}/organizations`)
+    .pipe(
+      timeout(5000),
+      map(response =>{
+        return response;
+      }),
+      catchError(this.errorHandl)
+    )
+  }
+  
+  errorHandl(error) {
+    let errorMessage = '';
+    if(error.error instanceof ErrorEvent) {
+      // Get client-side error
+      errorMessage = error.error.message;
+    } else {
+      // Get server-side error
+      errorMessage = `Error Code: ${error.status}\nMessage: ${error.message}`;
+    }
+    console.log(error);
+    return throwError(errorMessage);
+ }
+  //getOrganizations(): Observable<any> {
+    //return this.http.get(`${environment.apiUrl}/organizations`);
+  //}
+
+
+  
+
+  //getOrganization(id: number): Observable<Organization> {
+  //  return observableOf(this.listData.find(e => e.id === id));
+  //}
+}
+/*
+import { Injectable } from '@angular/core';
+import { HttpClient, HttpHeaders } from '@angular/common/http';
+import { Bug } from './bug';
+import { Observable, throwError } from 'rxjs';
+import { retry, catchError } from 'rxjs/operators';
+
+@Injectable({
+  providedIn: 'root'
+})
+
+export class BugService {
+
+  // Base url
+  baseurl = 'http://localhost:3000';
+
+  constructor(private http: HttpClient) { }
+
+  // Http Headers
+  httpOptions = {
+    headers: new HttpHeaders({
+      'Content-Type': 'application/json'
+    })
+  }
+
+  // POST
+  CreateBug(data): Observable<Bug> {
+    return this.http.post<Bug>(this.baseurl + '/bugtracking/', JSON.stringify(data), this.httpOptions)
+    .pipe(
+      retry(1),
+      catchError(this.errorHandl)
+    )
+  }  
+
+  // GET
+  GetIssue(id): Observable<Bug> {
+    return this.http.get<Bug>(this.baseurl + '/bugtracking/' + id)
+    .pipe(
+      retry(1),
+      catchError(this.errorHandl)
+    )
+  }
+
+
+
+
+import { Injectable } from '@angular/core';
+import { User } from '@app/models';
+
+@Injectable({ providedIn: 'root' })
+export class UserService {
+    constructor(private http: HttpClient) { }
+
+    getAll() {
+        return this.http.get<User[]>(`${environment.apiUrl}/users`);
+    }
+
+    getById(id: number) {
+        return this.http.get<User>(`${environment.apiUrl}/users/${id}`);
+    }
+}
+
+
+*/

+ 79 - 5
src/app/services/plants.service.ts

@@ -1,6 +1,13 @@
 import { Injectable } from '@angular/core';
+import { Organization } from '../models/organization';
 import { PlantData, Plant } from '../models/plant';
-import { of as observableOf, Observable } from 'rxjs';
+
+import { of as observableOf, Observable, throwError } from 'rxjs';
+import { HttpClient, HttpHeaders } from '@angular/common/http';
+import { retry, catchError, map, timeout } from 'rxjs/operators';
+
+import { environment } from '@environments/environment';
+
 import { plantsData } from '../data/plants.data';
 
 @Injectable({
@@ -9,16 +16,83 @@ import { plantsData } from '../data/plants.data';
 export class PlantsService extends PlantData {
 
   private listData: Plant[] = plantsData;
+  
+  time:number = 10000;
 
-  constructor() {
+  constructor(private http: HttpClient) {
     super();
-   }
+  }
+
+  getInstalledCapacity() {
+    return this.http.get(`${environment.apiUrl}/metersInstalled/installedCapacityTotal`)
+    .pipe(
+      timeout(this.time),
+      map(response =>{
+        return response;
+      }),
+      catchError(this.errorHandl)
+    )
+  }
+
+  getAssets() {
+    return this.http.get(`${environment.apiUrl}/assets`)
+    .pipe(
+      map(response =>{
+        return response;
+      }),
+      catchError(this.errorHandl)
+    )
+  }
 
-  getPlants(): Observable<Plant[]> {
+  //getAsset(id: string) {
+    //return observableOf(this.listData.find(e => e.id === id));
+  //}
+
+  
+  getAssetsProducedEnergy() {
+    return this.http.get(`${environment.apiUrl}/assets/energyProduced`)
+    .pipe(
+      timeout(this.time),
+      map( response =>{
+        return response;
+      }),
+      catchError(this.errorHandl)
+    )
+  }
+
+  getPlants() {
     return observableOf(this.listData);
   }
 
-  getPlant(id: number): Observable<Plant> {
+  getPlant(id: number) {
     return observableOf(this.listData.find(e => e.id === id));
   }
+
+ 
+  
+
+  getOrganizationPlants(id:string)  {
+    return this.http.get<any>(`${environment.apiUrl}/assets/${id}`)
+    .pipe(
+      timeout(this.time),
+      map(response =>{
+        return response;
+      }),
+      catchError(this.errorHandl)
+    )
+  }
+  
+  errorHandl(error) {
+    let errorMessage = '';
+    if(error.error instanceof ErrorEvent) {
+      // Get client-side error
+      errorMessage = error.error.message;
+    } else {
+      // Get server-side error
+      errorMessage = `Error Code: ${error.status}\nMessage: ${error.message}`;
+    }
+    console.log(error);
+    return throwError(errorMessage);
+ }
+
 }

+ 4 - 1
src/app/services/services.module.ts

@@ -1,7 +1,8 @@
 import { NgModule } from '@angular/core';
 import { CommonModule } from '@angular/common';
 import { PlantsService } from './plants.service';
-//import { RealTimeMeasuresService } from './real-time-measures.service';
+import { MeasuresService } from './measures.service';
+import { OrganizationsService } from './organizations.service';
 
 @NgModule({
   declarations: [],
@@ -10,6 +11,8 @@ import { PlantsService } from './plants.service';
   ],
   providers: [
     PlantsService,
+    MeasuresService,
+    OrganizationsService
   //RealTimeMeasuresService
   ]
 })

BIN
src/assets/img/01d.png


BIN
src/assets/img/01n.png


BIN
src/assets/img/02d.png


BIN
src/assets/img/02n.png


BIN
src/assets/img/03d.png


BIN
src/assets/img/03n.png


BIN
src/assets/img/04d.png


BIN
src/assets/img/04n.png


BIN
src/assets/img/09d.png


BIN
src/assets/img/09n.png


BIN
src/assets/img/10d.png


BIN
src/assets/img/10n.png


BIN
src/assets/img/11d.png


BIN
src/assets/img/11n.png


BIN
src/assets/img/50d.png


BIN
src/assets/img/50n.png


BIN
src/assets/img/car-icon.png


+ 23 - 0
src/assets/img/circle.svg

@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 22.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 viewBox="0 0 153 187" style="enable-background:new 0 0 153 187;" xml:space="preserve">
+<style type="text/css">
+	.st0{opacity:0.2;fill:#FFFFFF;}
+</style>
+<g>
+	<title>3</title>
+	<desc>Created with Sketch.</desc>
+	<g id="Mask-_x2B_-Mask-Mask" transform="translate(14.000000, 0.000000)">
+		<g id="Mask">
+		</g>
+		<g id="Mask_1_">
+			<path class="st0" d="M138,141.2c-3.6,0.5-7.3,0.8-11,0.8c-29.6,0-55.4-16.5-68.6-40.9c-6-11-9.4-23.7-9.4-37.1
+				c0-26.5,13.2-49.9,33.4-64H138v129.5"/>
+		</g>
+		<g id="Mask_2_">
+			<path class="st0" d="M138,141.2V187H-15c0.2-43.3,31.9-79.1,73.4-85.9c4.6-0.8,9.3-1.1,14.1-1.1c26.1,0,49.5,11.4,65.5,29.5"/>
+		</g>
+	</g>
+</g>
+</svg>

BIN
src/assets/img/desktop-pc-icon.png


BIN
src/assets/img/inverlec_logo.png


BIN
src/assets/img/logo-inverlec2.png


+ 69 - 0
src/assets/img/sound.svg

@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 viewBox="0 0 469.333 469.333" style="enable-background:new 0 0 469.333 469.333;" xml:space="preserve">
+<g>
+	<path style="fill:#F44336;" d="M10.667,298.667C4.779,298.667,0,293.888,0,288V181.333c0-5.888,4.779-10.667,10.667-10.667
+		s10.667,4.779,10.667,10.667V288C21.333,293.888,16.555,298.667,10.667,298.667z"/>
+	<path style="fill:#F44336;" d="M74.667,384C68.779,384,64,379.221,64,373.333V96c0-5.888,4.779-10.667,10.667-10.667
+		S85.333,90.112,85.333,96v277.333C85.333,379.221,80.555,384,74.667,384z"/>
+	<path style="fill:#F44336;" d="M138.667,469.333c-5.888,0-10.667-4.779-10.667-10.667v-448C128,4.779,132.779,0,138.667,0
+		s10.667,4.779,10.667,10.667v448C149.333,464.555,144.555,469.333,138.667,469.333z"/>
+	<path style="fill:#F44336;" d="M202.667,448c-5.888,0-10.667-4.779-10.667-10.667V32c0-5.888,4.779-10.667,10.667-10.667
+		S213.333,26.112,213.333,32v405.333C213.333,443.221,208.555,448,202.667,448z"/>
+	<path style="fill:#F44336;" d="M266.667,362.667c-5.888,0-10.667-4.779-10.667-10.667V117.333c0-5.888,4.779-10.667,10.667-10.667
+		s10.667,4.779,10.667,10.667V352C277.333,357.888,272.555,362.667,266.667,362.667z"/>
+	<path style="fill:#F44336;" d="M330.667,448c-5.888,0-10.667-4.779-10.667-10.667V32c0-5.888,4.779-10.667,10.667-10.667
+		c5.888,0,10.667,4.779,10.667,10.667v405.333C341.333,443.221,336.555,448,330.667,448z"/>
+	<path style="fill:#F44336;" d="M394.667,362.667c-5.888,0-10.667-4.779-10.667-10.667V117.333c0-5.888,4.779-10.667,10.667-10.667
+		c5.888,0,10.667,4.779,10.667,10.667V352C405.333,357.888,400.555,362.667,394.667,362.667z"/>
+	<path style="fill:#F44336;" d="M458.667,298.667c-5.888,0-10.667-4.779-10.667-10.667V181.333c0-5.888,4.779-10.667,10.667-10.667
+		c5.888,0,10.667,4.779,10.667,10.667V288C469.333,293.888,464.555,298.667,458.667,298.667z"/>
+</g>
+<path d="M10.667,298.667C4.779,298.667,0,293.888,0,288V181.333c0-5.888,4.779-10.667,10.667-10.667s10.667,4.779,10.667,10.667V288
+	C21.333,293.888,16.555,298.667,10.667,298.667z"/>
+<path d="M74.667,384C68.779,384,64,379.221,64,373.333V96c0-5.888,4.779-10.667,10.667-10.667S85.333,90.112,85.333,96v277.333
+	C85.333,379.221,80.555,384,74.667,384z"/>
+<path d="M138.667,469.333c-5.888,0-10.667-4.779-10.667-10.667v-448C128,4.779,132.779,0,138.667,0s10.667,4.779,10.667,10.667v448
+	C149.333,464.555,144.555,469.333,138.667,469.333z"/>
+<path d="M202.667,448c-5.888,0-10.667-4.779-10.667-10.667V32c0-5.888,4.779-10.667,10.667-10.667S213.333,26.112,213.333,32
+	v405.333C213.333,443.221,208.555,448,202.667,448z"/>
+<path d="M266.667,362.667c-5.888,0-10.667-4.779-10.667-10.667V117.333c0-5.888,4.779-10.667,10.667-10.667
+	s10.667,4.779,10.667,10.667V352C277.333,357.888,272.555,362.667,266.667,362.667z"/>
+<path d="M330.667,448c-5.888,0-10.667-4.779-10.667-10.667V32c0-5.888,4.779-10.667,10.667-10.667
+	c5.888,0,10.667,4.779,10.667,10.667v405.333C341.333,443.221,336.555,448,330.667,448z"/>
+<path d="M394.667,362.667c-5.888,0-10.667-4.779-10.667-10.667V117.333c0-5.888,4.779-10.667,10.667-10.667
+	c5.888,0,10.667,4.779,10.667,10.667V352C405.333,357.888,400.555,362.667,394.667,362.667z"/>
+<path d="M458.667,298.667c-5.888,0-10.667-4.779-10.667-10.667V181.333c0-5.888,4.779-10.667,10.667-10.667
+	c5.888,0,10.667,4.779,10.667,10.667V288C469.333,293.888,464.555,298.667,458.667,298.667z"/>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+</svg>

BIN
src/assets/img/tv-icon.png


BIN
src/assets/img/waves-alt.png


BIN
src/assets/img/waves-opt.png


BIN
src/assets/img/waves.png


+ 2 - 2
src/assets/scss/core/_fixed-plugin.scss

@@ -30,9 +30,9 @@
 
 .fixed-plugin{
     position: fixed;
-    top: 115px;
+    top: 65px;
     right: 0;
-    width: 64px;
+    width: 50px;
     background: rgba(0,0,0,.3);
     z-index: 1031;
     border-radius: 8px 0 0 8px;

+ 1 - 1
src/assets/scss/core/_sidebar-and-main-panel.scss

@@ -410,7 +410,7 @@
     @include transition (0.33s, cubic-bezier(0.685, 0.0473, 0.346, 1));
 
      .main-content{
-        margin-top: 70px;
+        margin-top: 50px;
         padding: 20px 10px;
         min-height: calc(100vh - 123px);
     }

+ 29 - 5
src/assets/scss/material-dashboard.scss

@@ -22,12 +22,14 @@
  @import "~bootstrap/scss/bootstrap";
 
 
- // Core Components
  @import "core/buttons";
  @import "core/checkboxes";
  @import "core/radios";
  @import "core/forms";
  @import "core/input-group";
+
+
+ // Core Components
  @import "core/images";
  @import "core/navbar";
  @import "core/alerts";
@@ -44,10 +46,6 @@
  @import "core/tables";
  @import "core/misc";
 
-@import "core/cards";
-@import "core/cards/card-stats";
-@import "core/cards/card-profile";
-@import "core/cards/card-plain";
 
  //plugin scss
  @import "core/plugins/animate";
@@ -57,6 +55,9 @@
 
 @import "core/angular-modal.scss";
 
+
+// Defaults
+
 .sky-skin {
   background-color: $palette-blue;
   border-color: #0b2338 !important;
@@ -76,3 +77,26 @@
   background-color: $palette-dark-yellow;
   border-color: #cf6a14 !important;
 }
+
+.widget {
+  background-color: #fff;
+}
+
+.custom-select {
+  background-color: #fff;
+  padding-left: 20px;
+  background-position: right 20px center;
+}
+
+.card-img-absolute {
+  position: absolute;
+  bottom: 15px;
+  right: 0;
+  height: 80px;
+  max-width: 150px;
+}
+
+.floating-title {
+  font-size: 1.2rem;
+  margin: 21px 65px 10px;
+}

+ 2 - 1
src/environments/environment.ts

@@ -4,8 +4,9 @@
 
 export const environment = {
     production: false,
-    apiUrl: 'http://localhost:4000',
+    apiUrl: 'http://192.168.98.140:8000',
     appID: '55899b9ea53834f2736b65a3582b734b',
+    api2Url: 'https://space-movie-rental-store.herokuapp.com',
     gKey: '',
     config: {
       apiKey: '',

+ 0 - 1
src/index.html

@@ -3,7 +3,6 @@
 <head>
     <base href='/'>
     <meta charset="utf-8" />
-    <link rel="apple-touch-icon" sizes="76x76" href="./assets/img/apple-icon.png" />
     <link rel="icon" type="image/x-icon" href="favicon.ico">
 
     <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />

Някои файлове не бяха показани, защото твърде много файлове са промени