commit cd2a65f32896e80a2d6585d0a51124e5a0770993
Author: hlavja <hlavjah@gmail.com>
Date:   Tue May 4 23:24:28 2021 +0200

    Re #8793 - Unit page - implementace
    
    + implementation of unit page graphs
    + multiple graphs on one page from one request

diff --git a/src/app/auth/interceptors/auth.interceptor.ts b/src/app/auth/interceptors/auth.interceptor.ts
index e45ed2e..d9c6095 100644
--- a/src/app/auth/interceptors/auth.interceptor.ts
+++ b/src/app/auth/interceptors/auth.interceptor.ts
@@ -27,6 +27,8 @@ export class AuthInterceptor implements HttpInterceptor {
 
     if (!this.cookieService.get(GlobalVariable.SESSION_ID) && !request.url.includes('ControllerServlet')) {
       console.log('No sessionid!');
+      this.cookieService.deleteAll();
+      this.authService.doLogout();
       return of(null);
     }
 
diff --git a/src/app/auth/services/auth.service.ts b/src/app/auth/services/auth.service.ts
index 6fcf5be..88df5cd 100644
--- a/src/app/auth/services/auth.service.ts
+++ b/src/app/auth/services/auth.service.ts
@@ -82,5 +82,6 @@ export class AuthService {
   setSessionStorage(userCookie: UserCookie, username) {
     localStorage.setItem(GlobalVariable.USER_NAME, username)
     localStorage.setItem(GlobalVariable.RIGHTS, userCookie.rightsID.toString());
+    this.cookieService.set('user', username);
   }
 }
diff --git a/src/app/sensor/components/sensor.component.html b/src/app/sensor/components/sensor.component.html
index f15ed03..e0eb29c 100644
--- a/src/app/sensor/components/sensor.component.html
+++ b/src/app/sensor/components/sensor.component.html
@@ -10,7 +10,7 @@ Unit ID {{unitId}}
     <div class="input-group-prepend">
       <span class="input-group-text">From</span>
     </div>
-    <p-calendar [style]="{'width':'100%'}" [inputStyle]="{'width':'100%'}" [(ngModel)]="from" [showTime]="true" (onSelect)="showGraph()" [maxDate]="today"></p-calendar>
+    <p-calendar [style]="{'width':'100%'}" [inputStyle]="{'width':'100%'}" [(ngModel)]="from" [showTime]="true" (onSelect)="showGraph()" [maxDate]="today" showButtonBar="true"></p-calendar>
   </div>
 </div>
 <div class="col">
@@ -18,7 +18,7 @@ Unit ID {{unitId}}
     <div class="input-group-prepend">
       <span class="input-group-text">To</span>
     </div>
-    <p-calendar [style]="{'width':'100%'}" [inputStyle]="{'width':'100%'}" [(ngModel)]="to" [showTime]="true" (onSelect)="showGraph()" [maxDate]="today"></p-calendar>
+    <p-calendar [style]="{'width':'100%'}" [inputStyle]="{'width':'100%'}" [(ngModel)]="to" [showTime]="true" (onSelect)="showGraph()" [maxDate]="today" showButtonBar="true"></p-calendar>
   </div>
 </div>
 <div *ngIf="showAggregation" class="col">
diff --git a/src/app/sensor/components/sensor.component.ts b/src/app/sensor/components/sensor.component.ts
index 331a2d1..38bfeb0 100644
--- a/src/app/sensor/components/sensor.component.ts
+++ b/src/app/sensor/components/sensor.component.ts
@@ -49,7 +49,6 @@ export class SensorComponent implements OnInit {
   }
 
   showGraph() {
-    let agg = 'HOUR';
     const range: Date[] = [moment().subtract(7, 'days').toDate(), moment().toDate()];
 
     if (this.from && !this.to || !this.from && this.to) {
@@ -63,24 +62,18 @@ export class SensorComponent implements OnInit {
 
     if (moment(range[1]).diff(moment(range[0]), 'days') > 7) {
       this.showAggregation = true;
-    }
-
-    if (this.selectedAggregationFunction) {
-      agg = this.selectedAggregationFunction;
-    }
-
-    if (moment(this.to).diff(moment(this.from), 'days') > 7) {
-      this.getAnalytics(range, agg);
+      this.getAnalytics(range);
     } else {
-      this.getObservations(range, agg);
+      this.showAggregation = false;
+      this.getObservations(range);
     }
   }
 
-  getAnalytics(range: Date[], agg: string) {
+  getAnalytics(range: Date[]) {
     this.analyticsService.getAnalytics$Response({
       unit_id: this.unitId, sensor_id: this.sensorId,
       from: moment(range[0]).format('yyyy-MM-DD HH:mm:ssZ').slice(0, -3),
-      to: moment(range[1]).format('yyyy-MM-DD HH:mm:ssZ').slice(0, -3), interval: agg
+      to: moment(range[1]).format('yyyy-MM-DD HH:mm:ssZ').slice(0, -3), interval: this.selectedAggregationFunction
     }).pipe(
       map((response: HttpResponse<any>) => {
         if (response.status === 200) {
@@ -102,7 +95,7 @@ export class SensorComponent implements OnInit {
       }, err => this.toastService.showError(err.error.message));
   }
 
-  getObservations(range: Date[], agg: string) {
+  getObservations(range: Date[]) {
     this.observationService.getObservation$Response({
       unit_id: this.unitId,
       sensor_id: this.sensorId,
diff --git a/src/app/shared/api/endpoints/api.module.ts b/src/app/shared/api/endpoints/api.module.ts
index 92eed2e..6ec0a0e 100644
--- a/src/app/shared/api/endpoints/api.module.ts
+++ b/src/app/shared/api/endpoints/api.module.ts
@@ -6,12 +6,12 @@ import { ApiConfiguration, ApiConfigurationParams } from './api-configuration';
 
 import { LoginService } from './services/login.service';
 import { AdministrationService } from './services/administration.service';
+import { SensorsService } from './services/sensors.service';
 import { ObservationService } from './services/observation.service';
 import { GroupService } from './services/group.service';
 import { DataService } from './services/data.service';
 import { AnalyticsService } from './services/analytics.service';
 import { ManagementService } from './services/management.service';
-import { SensorsService } from './services/sensors.service';
 
 /**
  * Module that provides all services and configuration.
@@ -23,12 +23,12 @@ import { SensorsService } from './services/sensors.service';
   providers: [
     LoginService,
     AdministrationService,
+    SensorsService,
     ObservationService,
     GroupService,
     DataService,
     AnalyticsService,
     ManagementService,
-    SensorsService,
     ApiConfiguration
   ],
 })
diff --git a/src/app/shared/api/endpoints/services.ts b/src/app/shared/api/endpoints/services.ts
index 691bdf8..8a74961 100644
--- a/src/app/shared/api/endpoints/services.ts
+++ b/src/app/shared/api/endpoints/services.ts
@@ -1,8 +1,8 @@
 export { LoginService } from './services/login.service';
 export { AdministrationService } from './services/administration.service';
+export { SensorsService } from './services/sensors.service';
 export { ObservationService } from './services/observation.service';
 export { GroupService } from './services/group.service';
 export { DataService } from './services/data.service';
 export { AnalyticsService } from './services/analytics.service';
 export { ManagementService } from './services/management.service';
-export { SensorsService } from './services/sensors.service';
diff --git a/src/app/shared/api/endpoints/services/sensors.service.ts b/src/app/shared/api/endpoints/services/sensors.service.ts
index 7c216c7..c2d2f4a 100644
--- a/src/app/shared/api/endpoints/services/sensors.service.ts
+++ b/src/app/shared/api/endpoints/services/sensors.service.ts
@@ -10,6 +10,7 @@ import { Observable } from 'rxjs';
 import { map, filter } from 'rxjs/operators';
 
 import { Phenomenon } from '../models/phenomenon';
+import { Sensor } from '../models/sensor';
 
 
 /**
@@ -26,6 +27,60 @@ export class SensorsService extends BaseService {
     super(config, http);
   }
 
+  /**
+   * Path part for operation getUnitSensors
+   */
+  static readonly GetUnitSensorsPath = '/senslog1/SensorService?Operation=GetSensors';
+
+  /**
+   * Get unit sensors.
+   *
+   *
+   *
+   * This method provides access to the full `HttpResponse`, allowing access to response headers.
+   * To access only the response body, use `getUnitSensors()` instead.
+   *
+   * This method doesn't expect any request body.
+   */
+  getUnitSensors$Response(params: {
+    unit_id: number;
+  }): Observable<StrictHttpResponse<Array<Sensor>>> {
+
+    const rb = new RequestBuilder(this.rootUrl, SensorsService.GetUnitSensorsPath, 'get');
+    if (params) {
+      rb.query('unit_id', params.unit_id, {});
+    }
+
+    return this.http.request(rb.build({
+      responseType: 'json',
+      accept: 'application/json'
+    })).pipe(
+      filter((r: any) => r instanceof HttpResponse),
+      map((r: HttpResponse<any>) => {
+        return r as StrictHttpResponse<Array<Sensor>>;
+      })
+    );
+  }
+
+  /**
+   * Get unit sensors.
+   *
+   *
+   *
+   * This method provides access to only to the response body.
+   * To access the full response (for headers, for example), `getUnitSensors$Response()` instead.
+   *
+   * This method doesn't expect any request body.
+   */
+  getUnitSensors(params: {
+    unit_id: number;
+  }): Observable<Array<Sensor>> {
+
+    return this.getUnitSensors$Response(params).pipe(
+      map((r: StrictHttpResponse<Array<Sensor>>) => r.body as Array<Sensor>)
+    );
+  }
+
   /**
    * Path part for operation getPhenomenons
    */
diff --git a/src/app/shared/api/openapi.yaml b/src/app/shared/api/openapi.yaml
index e447ee5..7d666fb 100644
--- a/src/app/shared/api/openapi.yaml
+++ b/src/app/shared/api/openapi.yaml
@@ -88,6 +88,29 @@ paths:
             schema:
               $ref: '#/components/schemas/UserInfo'
 
+  /senslog1/SensorService?Operation=GetSensors:
+    get:
+      tags:
+        - sensors
+      summary: Get unit sensors
+      operationId: getUnitSensors
+      parameters:
+        - in: query
+          name: unit_id
+          required: true
+          schema:
+            type: integer
+      responses:
+        200:
+          description: successful
+          content:
+            application/json:
+              schema:
+                type: array
+                items:
+                  $ref: '#/components/schemas/Sensor'
+
+
   /senslog1/SensorService?Operation=GetObservations:
     get:
       tags:
diff --git a/src/app/unit/components/unit.component.html b/src/app/unit/components/unit.component.html
index 48fe868..d613e4d 100644
--- a/src/app/unit/components/unit.component.html
+++ b/src/app/unit/components/unit.component.html
@@ -5,17 +5,37 @@
 ------
 <br><br>
 
-<div class="row">
-  <div class="col">
-    <p-calendar [style]="{'width':'100%'}" [inputStyle]="{'width':'100%'}" [(ngModel)]="rangeDates" selectionMode="range" [showTime]="true" [numberOfMonths]="3" (onSelect)="showGraph()"></p-calendar>
+<div class="col">
+  <div class="input-group form-group">
+    <div class="input-group-prepend">
+      <span class="input-group-text">From</span>
+    </div>
+    <p-calendar [style]="{'width':'100%'}" [inputStyle]="{'width':'100%'}" [(ngModel)]="from" [showTime]="true" (onSelect)="showGraph()" [maxDate]="today" showButtonBar="true"></p-calendar>
   </div>
-  <div class="col">
-    <p-listbox [options]="aggregationFunction" [(ngModel)]="selectedAggregationFunction" optionLabel="name" optionValue="code" (onClick)="showGraph()"></p-listbox>
+</div>
+<div class="col">
+  <div class="input-group form-group">
+    <div class="input-group-prepend">
+      <span class="input-group-text">To</span>
+    </div>
+    <p-calendar [style]="{'width':'100%'}" [inputStyle]="{'width':'100%'}" [(ngModel)]="to" [showTime]="true" (onSelect)="showGraph()" [maxDate]="today" showButtonBar="true"></p-calendar>
   </div>
 </div>
-
-<div *ngFor="let group of sensorGroups">
-  <div id="vega_container_{{group}}"></div>
+<div *ngIf="showAggregation" class="col">
+  <div class="input-group form-group">
+    <div class="input-group-prepend">
+      <span class="input-group-text">Aggregation</span>
+    </div>
+    <p-listbox [options]="aggregationFunction" [(ngModel)]="selectedAggregationFunction" optionLabel="name" optionValue="code" (onClick)="showGraph()" ></p-listbox>
+  </div>
 </div>
 
-  {{ data | json}}
+<ng-container *ngFor="let group of sensorGroups">
+  Group of sensors:
+  <ng-container *ngFor="let sensor of sensors">
+    <ng-container *ngIf="sensor.sensorId.toString().slice(0, 2) === group">
+      {{ sensor.sensorId }}
+    </ng-container>
+  </ng-container>
+  <div id="vega_container_{{group}}"></div>
+</ng-container>
diff --git a/src/app/unit/components/unit.component.ts b/src/app/unit/components/unit.component.ts
index 56a53e1..aed8bc2 100644
--- a/src/app/unit/components/unit.component.ts
+++ b/src/app/unit/components/unit.component.ts
@@ -1,11 +1,14 @@
 import {Component, OnInit} from '@angular/core';
 import {ActivatedRoute} from '@angular/router';
 import {AnalyticsService} from '../../shared/api/endpoints/services/analytics.service';
-import {tap} from 'rxjs/operators';
-import {Sensors} from '../../shared/api/endpoints/models/sensors';
+import {map, tap} from 'rxjs/operators';
 import {AggreationModel} from '../../shared/models/aggreation.model';
 import * as moment from 'moment-timezone';
 import {GraphLoader} from '../../shared/graph-loading/graphloader';
+import {SensorsService} from '../../shared/api/endpoints/services/sensors.service';
+import {HttpResponse} from '@angular/common/http';
+import {ToastService} from '../../shared/services/toast.service';
+import {Sensor} from '../../shared/api/endpoints/models/sensor';
 
 declare var require: any
 
@@ -19,69 +22,101 @@ export class UnitComponent implements OnInit {
   preselectedSensors: string;
   unitId: number;
   viewCount = 0;
-  data;
+  data = [];
+  time = [];
+  from: Date;
+  to: Date;
+  today: Date;
   sensorGroups = [];
-  rangeDates: Date[];
+  selectedSensors = [];
+  sensors: Sensor[];
+  showAggregation = false;
   aggregationFunction: AggreationModel[];
-  selectedAggregationFunction: string;
+  selectedAggregationFunction = 'HOUR';
 
   constructor(
     private activatedRoute: ActivatedRoute,
-    private analyticsService: AnalyticsService
+    private analyticsService: AnalyticsService,
+    private sensorService: SensorsService,
+    private toastService: ToastService
   ) {
+    this.unitId = parseInt(this.activatedRoute.snapshot.paramMap.get('unitId'), 10);
     this.aggregationFunction = [
       {name: 'Hour', code: 'HOUR'},
       {name: 'Day', code: 'DAY'},
       {name: 'Month', code: 'MONTH'},
       {name: 'Year', code: 'YEAR'}
     ];
+    this.today = moment().toDate();
+    this.sensorService.getUnitSensors({unit_id: this.unitId}).subscribe(
+      sensors => {
+        this.sensors = sensors;
+        if (sensors) {
+          sensors.forEach(sensor => {
+            const sensorType = sensor.sensorId.toString().slice(0, 2);
+            if (!this.sensorGroups.some(group => group === sensorType)) {
+              this.sensorGroups.push(sensorType);
+            }
+            if (!this.selectedSensors.some(sens => sens.toString().slice(0, 2) === sensorType)) {
+              this.selectedSensors.push(sensor.sensorId);
+            }
+          })
+        }
+      }
+    )
   }
 
   ngOnInit(): void {
-/*    this.route.queryParams.subscribe(params => {
-      if(params.sensors)  {
-        this.preselectedSensors = params.sensors;
-      }
-    });*/
-
-    this.unitId = parseInt(this.activatedRoute.snapshot.paramMap.get('unitId'), 10);
-
-    this.showGraph()
+    setTimeout(() => {
+      this.showGraph();
+    }, 0);
   }
 
   showGraph() {
-    let agg = 'HOUR';
-    let range: Date[] = [moment().subtract(6, 'months').toDate(), moment().toDate()];
-    if (this.selectedAggregationFunction) {
-      agg = this.selectedAggregationFunction;
+    const range: Date[] = [moment().subtract(6, 'months').toDate(), moment().toDate()];
+
+    if (this.from && !this.to || !this.from && this.to) {
+      return;
+    }
+
+    if (this.from && this.to) {
+      range[0] = this.from;
+      range[1] = this.to;
     }
 
-    if (this.rangeDates) {
-      range = this.rangeDates;
+    if (moment(range[1]).diff(moment(range[0]), 'days') > 7) {
+      this.showAggregation = true;
+      this.getAnalytics(range);
+    } else {
+      this.showAggregation = false;
+      // this.getObservations(range);
     }
+  }
 
-    this.analyticsService.getAnalytics({unit_id: this.unitId, sensor_id: null,
+  getAnalytics(range: Date[]) {
+    this.analyticsService.getAnalytics$Response({unit_id: this.unitId, sensor_id: null,
       from: moment(range[0]).format('yyyy-MM-DD HH:mm:ssZ').slice(0, -3),
-      to: moment(range[1]).format('yyyy-MM-DD HH:mm:ssZ').slice(0, -3), interval: agg}).pipe(
-      tap(data => {
-        var objectKeys = Object.keys(data);
-        for(const key of objectKeys ) {
-          let element = this.createView();
-          GraphLoader.getGraph(key, data[key]["data"], data[key]["interval"], element);
+      to: moment(range[1]).format('yyyy-MM-DD HH:mm:ssZ').slice(0, -3), interval: this.selectedAggregationFunction}).pipe(
+      map((response: HttpResponse<any>) => {
+        if (response.status === 200) {
+          return response.body;
+        } else if (response.status === 204) {
+          this.toastService.showWarningNoData();
+          return response.body;
+        } else {
+          return false;
         }
       })
-    ).subscribe();
-  }
-
-  createView() {
-    let div = document.createElement("div");
-    let name = "view" + this.viewCount;
-    div.id = name;
-    this.viewCount++;
-
-    let container = document.getElementById("vega_container");
-    container.appendChild(div);
-
-    return '#' + name;
+    ).subscribe(data => {
+        const objectKeys = Object.keys(data);
+        for(const key of objectKeys ) {
+          if (data[key].data) {
+            const view = '#vega_container_' + key.slice(0, 2);
+            if (this.selectedSensors.some(sens => sens.toString() === key)) {
+              GraphLoader.getGraph(key, data[key].data, data[key].interval, view);
+            }
+          }
+        }
+      });
   }
 }
