commit 66c042f15a9ca0e4ff4ed922cd503495b0f7f6d9
Author: Štěpán Červenka <stepan.cervenka1@gmail.com>
Date:   Thu May 13 10:31:25 2021 +0200

    Re #8775 - Agregovat grafy se stejným typem sensoru
    
    * bugs fixed
    * sensors and units sending request to new methods
    * ready for observation data

diff --git a/src/app/sensor/components/dummysensor.json b/src/app/sensor/components/dummysensor.json
new file mode 100644
index 0000000..f859bff
--- /dev/null
+++ b/src/app/sensor/components/dummysensor.json
@@ -0,0 +1,14 @@
+[
+  {
+    "firstObservationTime": "2019-03-07 06:10:16+02",
+    "lastObservationTime": "2021-05-12 18:00:06+03",
+    "phenomenon": {
+      "phenomenonId": "1",
+      "phenomenonName": "Temperature",
+      "unit": "°C"
+    },
+    "sensorId": 340400000,
+    "sensorName": "iMetos HC Air temp",
+    "sensorType": "Thermometer"
+  }
+]
diff --git a/src/app/sensor/components/sensor.component.ts b/src/app/sensor/components/sensor.component.ts
index a4f0f3c..e5a45cb 100644
--- a/src/app/sensor/components/sensor.component.ts
+++ b/src/app/sensor/components/sensor.component.ts
@@ -9,11 +9,16 @@ import {HttpResponse} from '@angular/common/http';
 import {map} from 'rxjs/operators';
 import {ToastService} from '../../shared/services/toast.service';
 
+declare var require: any
+
 @Component({
   selector: 'app-sensor',
   templateUrl: './sensor.component.html',
   styleUrls: ['./sensor.component.scss']
 })
+
+
+
 export class SensorComponent implements OnInit {
 
   sensorId: number;
@@ -89,9 +94,9 @@ export class SensorComponent implements OnInit {
       observations => {
         if (observations) {
         //  GraphLoader.getGraph(this.sensorId, observations[this.sensorId].data, observations[this.sensorId].interval, '#view');
-          GraphLoader.getGraph(this.sensorId, observations[this.sensorId].data, '#view', true);
+          GraphLoader.getGraph(this.sensorId, observations, this.getDummySensor(), '#view', true);
         } else {
-          GraphLoader.getGraph(null, null, '#view', null);
+          GraphLoader.getGraph(null, null, null, '#view', null);
         }
       }, err => this.toastService.showError(err.error.message));
   }
@@ -117,11 +122,15 @@ export class SensorComponent implements OnInit {
       observations => {
         if (observations) {
          // GraphLoader.getObservationGraph(this.sensorId, observations, '#view');
-          GraphLoader.getGraph(this.sensorId, observations[this.sensorId].data, '#view', false);
+          GraphLoader.getGraph(this.sensorId, observations, this.getDummySensor(), '#view', false);
         } else {
          // GraphLoader.getObservationGraph(null, null, null);
-          GraphLoader.getGraph(null, null, '#view', null);
+          GraphLoader.getGraph(null, null, null,'#view', null);
         }
       }, err => this.toastService.showError(err.error.message));
   }
+
+  getDummySensor() {
+    return require('/src/app/sensor/components/dummysensor.json');
+  }
 }
diff --git a/src/app/shared/graph-loading/emptygraph.ts b/src/app/shared/graph-loading/emptygraph.ts
index 7354e12..ff34238 100644
--- a/src/app/shared/graph-loading/emptygraph.ts
+++ b/src/app/shared/graph-loading/emptygraph.ts
@@ -24,4 +24,12 @@ export class EmptyGraph implements Graph{
     return rvalue;
   }
 
+  setData(spec, data) {
+    //DO NOTHING
+  }
+
+  setLegendInfo(spec, legend) {
+    //DO NOTHING
+  }
+
 }
diff --git a/src/app/shared/graph-loading/graphloader.ts b/src/app/shared/graph-loading/graphloader.ts
index f08acc5..55af58e 100644
--- a/src/app/shared/graph-loading/graphloader.ts
+++ b/src/app/shared/graph-loading/graphloader.ts
@@ -10,30 +10,30 @@ declare var require: any
 export class GraphLoader {
 
 
-  static getGraphType(sensors, data, isAnalytics): Graph {
+  static getGraphType(sensors, data, legend, isAnalytics): Graph {
     if (sensors == null) {
       return new EmptyGraph("Selected no sensors.");
 
-    } else if (Array.isArray(sensors)) {
+    }  else if (Array.isArray(sensors)) {
       if (sensors.length == 0) {
         return new EmptyGraph("Selected no sensors.");
       } else if (sensors.length == 1) {
-        return new SingleGraph(sensors[0], isAnalytics, data, 10000);
+        return new SingleGraph(sensors[0], isAnalytics, data, legend,10000);
       } else {
-        return new MultiGraph(isAnalytics, data, 10000);
+        return new MultiGraph(isAnalytics, data, legend,10000);
       }
 
     } else {
-      return new SingleGraph(sensors, isAnalytics, data, 10000);
+      return new SingleGraph(sensors, isAnalytics, data, legend, 10000);
     }
   }
 
 
-  static getGraph(sensors, data, element, isAnalytics) {
-    let graph = this.getGraphType(sensors,data, isAnalytics);
+  static getGraph(sensors, data, legendInfo, element, isAnalytics) {
+    let graph = this.getGraphType(sensors,data, legendInfo, isAnalytics);
     let config = graph.getConfig();
     let spec = graph.getSpec();
-    spec['data'][0].values = data;
+
 
     this.showGraph(spec, config, element);
 
diff --git a/src/app/shared/graph-loading/multigraph.ts b/src/app/shared/graph-loading/multigraph.ts
index fde2e71..f733e71 100644
--- a/src/app/shared/graph-loading/multigraph.ts
+++ b/src/app/shared/graph-loading/multigraph.ts
@@ -7,11 +7,13 @@ export class MultiGraph implements Graph{
   isAnalytics: boolean;
   data: any [];
   interval: number;
+  legend: {};
 
-  constructor(isAnalytics: boolean, data: any [], interval: number) {
+  constructor(isAnalytics: boolean, data: any [], legend: {}, interval: number) {
     this.isAnalytics = isAnalytics;
     this.data = data;
     this.interval = interval;
+    this.legend = this.getLegend(legend);
 
   }
 
@@ -22,6 +24,7 @@ export class MultiGraph implements Graph{
     let config1 = require('/src/vega/config/config.json');
     lodash.merge(rvalue, config1);
     let config2 = require('/src/vega/config/config-multiline.json');
+    let config3 = require('/src/vega/config/config-barline.json');
 
 
     for(let key in config2.signals) {
@@ -29,7 +32,12 @@ export class MultiGraph implements Graph{
       rvalue.signals.push(obj);
     }
 
-    return config1;
+    for(let key in config3.signals) {
+      let obj = config3.signals[key];
+      rvalue.signals.push(obj);
+    }
+
+    return rvalue;
   }
 
   getSpec(): {} {
@@ -37,11 +45,13 @@ export class MultiGraph implements Graph{
     const rvalue: any = {};
     const base = require('/src/vega/base/default.json');
     const body = require('/src/vega/body/multilinechart.json');
-    const tooltip = require('/src/vega/tooltip/multiline-tooltip.json');
+    const legend = require('/src/vega/miscs/legend.json');
+    const tooltip = require('/src/vega/miscs/multiline-tooltip.json');
 
-    lodash.merge(rvalue, base, body, tooltip);
+    lodash.merge(rvalue, base, body, legend, tooltip);
 
-    rvalue.data[0].values = this.data;
+    rvalue.data[1].values = this.data;
+    rvalue.data[0].values = this.legend;
     rvalue.signals[0].value = this.interval;
     rvalue.marks[0].marks[0].marks[0].marks[2].encode.enter.tooltip.signal = this.getTooltipMessage();
 
@@ -58,4 +68,13 @@ export class MultiGraph implements Graph{
     return message;
   }
 
+  private getLegend(legend: any) {
+    if(Array.isArray(legend)) {
+      return legend[0];
+    } else {
+      return legend;
+    }
+  }
+
+
 }
diff --git a/src/app/shared/graph-loading/singlegraph.ts b/src/app/shared/graph-loading/singlegraph.ts
index e724cbf..612baad 100644
--- a/src/app/shared/graph-loading/singlegraph.ts
+++ b/src/app/shared/graph-loading/singlegraph.ts
@@ -1,38 +1,63 @@
 import {Graph} from "./graph";
+import {SingleGraphType} from "./singlegraphtype";
 
 declare var require: any
 
-export class SingleGraph implements Graph{
+export class SingleGraph implements Graph {
   isAnalytics: boolean;
   sensorId: number;
   interval: number;
   data: any [];
+  legend: {};
+  type: SingleGraphType;
 
-  constructor(sensorId: number, isAnalytics: boolean, data: any[], interval: number) {
+  constructor(sensorId: number, isAnalytics: boolean, data: any[], legend: {}, interval: number) {
     this.sensorId = sensorId;
     this.isAnalytics = isAnalytics;
     this.interval = interval;
     this.data = data;
+    this.legend = this.getLegend(legend);
+    this.type = this.getGraphType();
+
   }
 
+
   getConfig(): {} {
     const lodash = require('lodash/object');
     const rvalue: any = {};
     let config1 = require('/src/vega/config/config.json');
     lodash.merge(rvalue, config1);
+
     let config2;
-    if(this.isAnalytics) {
+    if (this.isAnalytics) {
       config2 = require('/src/vega/config/config-analytics.json');
     } else {
       config2 = require('/src/vega/config/config-observations.json');
     }
 
-    for(let key in config2.signals) {
+    let config3;
+    switch (this.type) {
+      case SingleGraphType.LINECHART:
+      case SingleGraphType.BARCHART:
+        config3 = require('/src/vega/config/config-barline.json');
+        break;
+      case SingleGraphType.WINDCHART:
+        config3 = require('/src/vega/config/config-wind.json');
+        break;
+    }
+
+
+    for (let key in config2.signals) {
       let obj = config2.signals[key];
       rvalue.signals.push(obj);
     }
 
-    return config1;
+    for (let key in config3.signals) {
+      let obj = config3.signals[key];
+      rvalue.signals.push(obj);
+    }
+
+    return rvalue;
   }
 
   getSpec(): {} {
@@ -40,36 +65,99 @@ export class SingleGraph implements Graph{
     const rvalue: any = {};
     const base = require('/src/vega/base/default.json');
     const body = this.getBodySpec();
+    const legend = this.getLegendSpec();
     const tooltip = this.getTooltipSpec();
-    lodash.merge(rvalue, base, body, tooltip);
+    lodash.merge(rvalue, base, body, legend, tooltip);
 
 
-    rvalue.data[0].values = this.data;
+    this.setData(rvalue, this.data);
+    rvalue['data'][0].values = this.legend;
     rvalue.signals[0].value = this.interval;
 
     return rvalue;
   }
 
 
- private getBodySpec() {
+  private getLegendSpec() {
+    switch (this.type) {
+      case SingleGraphType.BARCHART:
+      case SingleGraphType.LINECHART:
+        return require('/src/vega/miscs/legend.json');
+      case SingleGraphType.WINDCHART:
+        return {};
+    }
+  }
+
+  private getBodySpec() {
+    switch (this.type) {
+      case SingleGraphType.BARCHART:
+        return require('/src/vega/body/barchart.json');
+      case SingleGraphType.WINDCHART:
+        return require('/src/vega/body/windchart.json');
+      case SingleGraphType.LINECHART:
+        //TODO pridat min/max
+        return require('/src/vega/body/linechart.json');
+    }
+  }
+
+
+  private getTooltipSpec() {
+    let lodash = require('lodash');
+    let tooltipMessage;
+    let rvalue: any = {};
+    if (this.isAnalytics) {
+      lodash.merge(rvalue, require('/src/vega/miscs/samm-tooltip.json'));
+      tooltipMessage = this.getSammTooltip();
+    } else {
+      lodash.merge(rvalue, require('/src/vega/miscs/value-tooltip.json'));
+      tooltipMessage = this.getValueTooltip();
+    }
+
+    rvalue.marks[0].marks[0].marks[0].encode.enter.tooltip.signal = tooltipMessage;
+    return rvalue;
+  }
+
+
+  private getValueTooltip() {
+    return "{title: timeFormat(datum.dateTime, '%A, %e. %B %Y, %X')  ,  'value': datum.value + ' " + this.legend['phenomenon']['unit'] + "', 'gid': datum.gid }"
+  }
+
+  private getSammTooltip() {
+    return "{title: timeFormat(datum.dateTime, '%A, %e. %B %Y, %X') " +
+      " , 'avg': datum.avg + ' " + this.legend['phenomenon']['unit'] +
+      "', 'sum': datum.sum + ' " + this.legend['phenomenon']['unit'] +
+      "', 'max': datum.max + ' " + this.legend['phenomenon']['unit'] +
+      "', 'min': datum.min + ' " + this.legend['phenomenon']['unit'] + "'}"
+  }
+
+
+  private setData(spec: any, data: any) {
+    if(data.length > 0 && 'data' in data[0]) {
+      spec['data'][1].values = data[0].data;
+    } else {
+      spec['data'][1].values = data;
+    }
+  }
+
+  private getLegend(legend: any) {
+    if (Array.isArray(legend)) {
+      return legend[0];
+    } else {
+      return legend;
+    }
+  }
+
+  private getGraphType() {
     if (this.sensorId >= 480000000 && this.sensorId < 490000000) {
-      return require('/src/vega/body/barchart.json');
+      return SingleGraphType.BARCHART;
     } else if ((this.sensorId >= 470020000 && this.sensorId < 470030000) || (this.sensorId >= 470060000 && this.sensorId < 470090000) ||
       (this.sensorId >= 470130000 && this.sensorId < 470140000) || (this.sensorId >= 470180000 && this.sensorId < 470190000)) {
-      return require('/src/vega/body/windchart.json');
+      return SingleGraphType.WINDCHART;
     } else {
       //TODO pridat min/max
-      return require('/src/vega/body/linechart.json');
+      return SingleGraphType.LINECHART;
     }
   }
 
 
-  private getTooltipSpec() {
-      if(this.isAnalytics) {
-        return require('/src/vega/tooltip/samm-tooltip.json');
-      } else {
-        return require('/src/vega/tooltip/value-tooltip.json');
-      }
-    }
-
 }
diff --git a/src/app/shared/graph-loading/singlegraphtype.ts b/src/app/shared/graph-loading/singlegraphtype.ts
new file mode 100644
index 0000000..1fe710e
--- /dev/null
+++ b/src/app/shared/graph-loading/singlegraphtype.ts
@@ -0,0 +1,5 @@
+export enum SingleGraphType{
+  LINECHART,
+  BARCHART,
+  WINDCHART
+}
diff --git a/src/app/unit/components/unit.component.ts b/src/app/unit/components/unit.component.ts
index cea101e..3155d7b 100644
--- a/src/app/unit/components/unit.component.ts
+++ b/src/app/unit/components/unit.component.ts
@@ -65,7 +65,7 @@ export class UnitComponent implements OnInit {
               this.sensorGroups.push(sensorType);
               setTimeout(() => {
                 //GraphLoader.getAnalyticsGraph(null, null, null, '#vega_container_' + sensor.sensorId.toString().slice(0, 5));
-                GraphLoader.getGraph(null, null, '#vega_container_' + sensor.sensorId.toString().slice(0, 5),null );
+                GraphLoader.getGraph(null, null, null, '#vega_container_' + sensor.sensorId.toString().slice(0, 5),null );
               }, 0);
             }
           });
@@ -101,6 +101,7 @@ export class UnitComponent implements OnInit {
   }
 
   getAnalytics(range: Date[], changedDate: boolean, changedSensor: string) {
+    const groupId = changedSensor.toString().slice(0, 5);
     if (changedDate) {
       this.selectedSensors.forEach(selectSens => {
         this.analyticsService.getAnalytics$Response({unit_id: this.unitId, sensor_id: parseInt(selectSens, 10),
@@ -111,7 +112,7 @@ export class UnitComponent implements OnInit {
               return response.body;
             } else if (response.status === 204) {
               //GraphLoader.getAnalyticsGraph(null, null, null, '#vega_container_' + selectSens.toString().slice(0, 5));
-              GraphLoader.getGraph(null, null, '#vega_container_' + selectSens.toString().slice(0, 5),null );
+              GraphLoader.getGraph(null, null, null, '#vega_container_' + selectSens.toString().slice(0, 5),null );
               this.toastService.showWarningNoData();
               return response.body;
             } else {
@@ -129,7 +130,7 @@ export class UnitComponent implements OnInit {
                   //GraphLoader.getAnalyticsGraph(key, data[key].data, data[key].interval, view);
                   //GraphLoader.getGraph(this.selectedSensors, this.filteredAnalyticsData(groupId), view, true);
                 } else {
-                  GraphLoader.getGraph(null, null, view, null);
+                  GraphLoader.getGraph(null, null, null, view, null);
                 }
               }
             }
@@ -159,10 +160,10 @@ export class UnitComponent implements OnInit {
               const view = '#vega_container_' + key.slice(0, 5);
               if (this.selectedSensors.some(sens => sens.toString() === key)) {
                // GraphLoader.getAnalyticsGraph(key, data[key].data, data[key].interval, view);
-                GraphLoader.getGraph(this.selectedSensors, this.analyticsData, view, true);
+                GraphLoader.getGraph(this.selectedSensors, this.analyticsData, this.filteredSensorsInfos(groupId), view, true);
               } else {
                 //GraphLoader.getAnalyticsGraph(null, null, null, view);
-                GraphLoader.getGraph(null, null, view, null);
+                GraphLoader.getGraph(null, null, null, view, null);
               }
             }
           }
@@ -181,14 +182,14 @@ export class UnitComponent implements OnInit {
     const sensorGroupElement = '#vega_container_' + groupId;
     if (!this.selectedSensors.find(sensId => sensId.toString().slice(0, 5) === groupId)) { // if group of sensors is empty show empty graph
       //GraphLoader.getAnalyticsGraph(null, null, null, sensorGroupElement);
-      GraphLoader.getGraph(null, null, sensorGroupElement, null);
+      GraphLoader.getGraph(null, null, null, sensorGroupElement, null);
     } else {
       if (this.useAnalyticsData) { // use analytics data
         if (event.checked) { // if checked > add to graph
           if (this.analyticsData.some(sens => sens.sensorId === sensorId)) { // if already data for selected sensor in memory
             //GraphLoader.getAnalyticsGraph(sensorId, this.analyticsData.find(sens => sens.sensorId === sensorId).data,
             // this.analyticsData.find((sens => sens.sensorId === sensorId).interval, sensorGroupElement);
-            GraphLoader.getGraph(this.selectedSensors, this.analyticsData, sensorGroupElement, true);
+            GraphLoader.getGraph(this.selectedSensors, this.analyticsData, this.filteredSensorsInfos(groupId), sensorGroupElement, true);
 
           } else { // get data from server for added sensor and show graph for selected sensors
             this.showGraph(false, sensorId);
@@ -196,20 +197,21 @@ export class UnitComponent implements OnInit {
         } else { // remove sensor from graph
           //GraphLoader.getAnalyticsGraph(sensorId, this.analyticsData.find(sens => sens.sensorId === sensorId).data,
           // this.analyticsData.find(sens => sens.sensorId === sensorId).interval, sensorGroupElement);
-          GraphLoader.getGraph(this.selectedSensors, this.analyticsData, sensorGroupElement, true);
+          GraphLoader.getGraph(this.selectedSensors, this.analyticsData, this.filteredSensorsInfos(groupId), sensorGroupElement, true);
 
         }
       } else { // use observations data
         if (event.checked) { // if checked > add to graph
           if (this.observationsData.some(sens => sens.sensorId.toString() === sensorId)) { // if already data for selected sensor in memory
-            GraphLoader.getGraph(this.selectedSensors, this.filteredObservationData(groupId), sensorGroupElement, false);
+            GraphLoader.getGraph(this.filteredSelectedSensors(groupId), this.filteredObservationData(groupId), this.filteredSensorsInfos(groupId), sensorGroupElement, false);
             //GraphLoader.getMultilineGraph(this.selectedSensors, this.filteredObservationData(groupId), sensorGroupElement)
           } else { // get data from server for added sensor and show graph for selected sensors
             this.showGraph(false, sensorId);
           }
         } else { // remove sensor from graph
           //GraphLoader.getMultilineGraph(this.selectedSensors, this.filteredObservationData(groupId), sensorGroupElement)
-          GraphLoader.getGraph(this.selectedSensors, this.filteredObservationData(groupId), sensorGroupElement, false);
+          GraphLoader.getGraph(this.filteredSelectedSensors(groupId), this.filteredObservationData(groupId), this.filteredSensorsInfos(groupId), sensorGroupElement, false);
+
         }
       }
     }
@@ -232,7 +234,18 @@ export class UnitComponent implements OnInit {
       sen.sensorId.toString().slice(0, 5) === sensorGroupId);
   }
 
+
+  filteredSelectedSensors(sensorGroupId: string): any {
+    return this.selectedSensors.filter(sen => sen.toString().slice(0, 5) == sensorGroupId );
+  }
+
+  filteredSensorsInfos(sensorGroupId: string): any {
+    return this.sensors.filter(sen => this.selectedSensors.includes(sen.sensorId.toString()) &&
+      sen.sensorId.toString().slice(0, 5) == sensorGroupId);
+  }
+
   private getObservations(range: Date[], changedDate: boolean, changedSensorId: string) {
+    const groupId = changedSensorId.toString().slice(0, 5);
     if (changedDate) { // if changed date we need new data for all sensors
       this.observationsData = []; // empty observation data
       this.selectedSensors.forEach(selectSens => {
@@ -264,7 +277,7 @@ export class UnitComponent implements OnInit {
               setTimeout(() => {
                 console.log(this.selectedSensors);
                 //GraphLoader.getMultilineGraph(this.selectedSensors, this.filteredObservationData(selectSens.toString().slice(0, 5)), view);
-                GraphLoader.getGraph(this.selectedSensors,  this.filteredObservationData(changedSensorId.toString().slice(0, 5)), view, false);
+                GraphLoader.getGraph(this.filteredSelectedSensors(groupId),  this.filteredObservationData(groupId), this.filteredSensorsInfos(groupId), view, false);
               }, 10);
             }
           })
@@ -292,14 +305,8 @@ export class UnitComponent implements OnInit {
           this.observationsData.push({sensorId: changedSensorId, sensor:
               this.sensors.find(sens => sens.sensorId.toString() === changedSensorId.toString()), data: observations});
           const view = '#vega_container_' + changedSensorId.toString().slice(0, 5);
-          if (observations) {
-            console.log(this.observationsData);
-            GraphLoader.getGraph(this.selectedSensors,  this.filteredObservationData(changedSensorId.toString().slice(0, 5)), view, false);
-            //GraphLoader.getMultilineGraph(this.selectedSensors, this.filteredObservationData(changedSensorId.toString().slice(0, 5)), view);
-          } else {
-            //GraphLoader.getMultilineGraph(null, null, null);
-            GraphLoader.getGraph(this.selectedSensors,  this.filteredObservationData(changedSensorId.toString().slice(0, 5)), view, false);
-          }
+
+            GraphLoader.getGraph(this.filteredSelectedSensors(groupId),  this.filteredObservationData(groupId), this.filteredSensorsInfos(groupId), view, false);
         }, err => this.toastService.showError(err.error.message));
     }
   }
diff --git a/src/vega/base/default.json b/src/vega/base/default.json
index d8074d0..ab5a4ad 100644
--- a/src/vega/base/default.json
+++ b/src/vega/base/default.json
@@ -1,5 +1,9 @@
 {
   "data": [
+    {
+      "name": "legend",
+      "values": null
+    },
     {
       "name": "source",
       "values": null
@@ -43,12 +47,12 @@
         },
         {
           "type": "formula",
-          "expr":"time(datum[\"dateMinTemp\"]) - (timeStep * 500)",
+          "expr":"time(datum[\"dateMinTemp\"]) - timeWindow",
           "as": "dateMin"
         },
         {
           "type": "formula",
-          "expr":"time(datum[\"dateMaxTemp\"]) + (timeStep * 500)",
+          "expr":"time(datum[\"dateMaxTemp\"]) + timeWindow",
           "as": "dateMax"
         },
         {
@@ -61,10 +65,6 @@
   ],
 
   "signals": [
-    {
-      "name": "timeStep",
-      "value": null
-    },
     {
       "name": "detailDomain"
     }
@@ -87,7 +87,13 @@
           "name": "xDetail",
           "type": "time",
           "range": "width",
-          "domain": {"data": "table", "field": "dateTime"},
+          "domain": {
+          "data": "range",
+          "fields": [
+            "dateMin",
+            "dateMax"
+          ]
+        },
           "domainRaw": {"signal": "detailDomain"}
         }
       ],
@@ -124,9 +130,9 @@
       "encode": {
         "enter": {
           "x": {"value": 0},
-          "y": {"value": 430},
-          "height": {"value": 70},
-          "width": {"value": 720},
+          "y": {"signal":  "overviewHeightStart"},
+          "height": {"signal": "overviewHeight"},
+          "width": {"signal":  "width"},
           "fill": {"value": "transparent"}
         }
       },
diff --git a/src/vega/base/empty.json b/src/vega/base/empty.json
index f59486d..dd79c24 100644
--- a/src/vega/base/empty.json
+++ b/src/vega/base/empty.json
@@ -1,6 +1,10 @@
 {
 
   "data":[
+    {
+      "name": "legend",
+      "values": null
+    },
     {
       "name": "source",
       "values": null
diff --git a/src/vega/body/barchart.json b/src/vega/body/barchart.json
index e2877aa..2ccf2f6 100644
--- a/src/vega/body/barchart.json
+++ b/src/vega/body/barchart.json
@@ -1,36 +1,92 @@
 {
   "data": [
+    {},
+    {},
+    {},
+    {},
     {},
     {
+      "name": "ranks",
+      "source": "table",
       "transform": [
-        {},
-        {},
-        {},
-        {},
         {
-          "type": "timeunit",
-          "field": "dateTime",
-          "units": [
-            "year",
-            "month",
-            "date",
-            "hours",
-            "minutes",
-            "seconds"
+          "type": "window",
+          "sort": {
+            "field": "dateTime",
+            "order": "ascending"
+          },
+          "ops": [
+            "rank"
           ],
-          "step": {
-            "signal": "timeStep"
-          }
+          "fields": [
+            "value"
+          ],
+          "as": [
+            "rank"
+          ]
         },
         {
           "type": "formula",
-          "expr": "time(datum[\"unit0\"] + (timeStep * 100))",
-          "as": "barStart"
+          "expr": "datum.rank + 1",
+          "as": "nextRank"
         },
         {
           "type": "formula",
-          "expr": "time(datum[\"unit1\"] - (timeStep * 100))",
-          "as": "barEnd"
+          "expr": "datum.rank - 1",
+          "as": "prevRank"
+        }
+      ]
+    },
+    {
+      "name": "lookup",
+      "source": "ranks",
+      "transform": [
+        {
+          "type": "lookup",
+          "from": "ranks",
+          "key": "rank",
+          "fields": [
+            "nextRank"
+          ],
+          "as": [
+            "nextObj"
+          ]
+        },
+        {
+          "type": "lookup",
+          "from": "ranks",
+          "key": "rank",
+          "fields": [
+            "prevRank"
+          ],
+          "as": [
+            "prevObj"
+          ]
+        },
+        {
+          "type": "formula",
+          "expr": "datum.prevObj == null ?  data('range')[0].dateMin : (time(datum.prevObj.dateTime) + time(datum.dateTime)) / 2",
+          "as": "tempDateStart"
+        },
+        {
+          "type": "formula",
+          "expr": "datum.nextObj == null ?  data('range')[0].dateMax : (time(datum.nextObj.dateTime) + time(datum.dateTime)) / 2",
+          "as": "tempDateEnd"
+        },
+        {
+          "type": "formula",
+          "expr": "(datum.tempDateEnd - datum.tempDateStart) * 0.05",
+          "as": "tempDateToAdd"
+        },
+        {
+          "type": "formula",
+          "expr": "datum.tempDateStart + datum.tempDateToAdd",
+          "as": "dateStart"
+        },
+        {
+          "type": "formula",
+          "expr": "datum.tempDateEnd - datum.tempDateToAdd",
+          "as": "dateEnd"
         }
       ]
     }
@@ -47,8 +103,10 @@
             0
           ],
           "domain": {
-            "data": "table",
-            "field": "value"
+            "fields": [
+              {"data": "range", "field": "valueMax"},
+              {"data":  "table", "field": "value"}
+            ]
           },
           "nice": true,
           "zero": true
@@ -67,26 +125,26 @@
             {
               "type": "rect",
               "from": {
-                "data": "table"
+                "data": "lookup"
               },
               "encode": {
                 "enter": {
                   "tooltip": {
-                    "signal": "{title: timeFormat(datum.dateTime, '%A, %e. %B %Y, %X') }"
+                    "signal": "{title: timeFormat(datum.dateTime, '%A, %e. %B %Y, %X')  ,  'value': datum.value + 'mm', 'gid': datum.gid }"
                   }
                 },
                 "update": {
                   "x": {
                     "scale": "xDetail",
-                    "field": "barStart"
+                    "field": "dateStart"
                   },
                   "x2": {
                     "scale": "xDetail",
-                    "field": "barEnd"
+                    "field": "dateEnd"
                   },
                   "y": {
                     "scale": "yDetail",
-                    "field": "avg"
+                    "field": "value"
                   },
                   "y2": {
                     "scale": "yDetail",
@@ -129,6 +187,43 @@
             }
           ]
         }
+      ],
+      "marks": [
+        {},
+        {},
+        {},
+        {
+          "type": "rect",
+          "from": {
+            "data": "lookup"
+          },
+          "encode": {
+            "update": {
+              "x": {
+                "scale": "xOverview",
+                "field": "dateStart"
+              },
+              "x2": {
+                "scale": "xOverview",
+                "field": "dateEnd"
+              },
+              "y": {
+                "scale": "yOverview",
+                "field": "value"
+              },
+              "y2": {
+                "scale": "yOverview",
+                "value": 0
+              },
+              "color": {
+                "value": "both"
+              },
+              "fill": {
+                "value": "steelBlue"
+              }
+            }
+          }
+        }
       ]
     }
   ]
diff --git a/src/vega/body/linechart.json b/src/vega/body/linechart.json
index 651793c..4702a5b 100644
--- a/src/vega/body/linechart.json
+++ b/src/vega/body/linechart.json
@@ -4,6 +4,7 @@
     {},
     {},
     {},
+    {},
     {
       "name": "ranks",
       "source": "table",
@@ -28,6 +29,11 @@
           "type": "formula",
           "expr": "datum.rank + 1",
           "as": "nextRank"
+        },
+        {
+          "type": "formula",
+          "expr": "datum.rank - 1",
+          "as": "prevRank"
         }
       ]
     },
@@ -37,7 +43,7 @@
       "transform": [
         {
           "type": "lookup",
-          "from": "table",
+          "from": "ranks",
           "key": "rank",
           "fields": [
             "nextRank"
@@ -48,7 +54,7 @@
         },
         {
           "type": "lookup",
-          "from": "table",
+          "from": "ranks",
           "key": "rank",
           "fields": [
             "prevRank"
@@ -77,7 +83,6 @@
   ],
 
   "signals": [
-    {},
     {},
     {
       "name": "tooltipSignal",
diff --git a/src/vega/body/multilinechart.json b/src/vega/body/multilinechart.json
index 02bc9f3..3ae69cd 100644
--- a/src/vega/body/multilinechart.json
+++ b/src/vega/body/multilinechart.json
@@ -1,5 +1,6 @@
 {
   "data": [
+    {},
     {},
     {
       "transform": [
@@ -26,20 +27,12 @@
             },
             {
               "signal": "sensorPath"
-            },
-            {
-              "signal": "axeLegendPath"
-            },
-            {
-              "signal": "axeLegendUnit"
             }
           ],
           "as": [
             "value",
             "timestamp",
-            "sensor",
-            "axeLegend",
-            "axeUnit"
+            "sensor"
           ]
         }
       ]
@@ -191,7 +184,6 @@
     }
   ],
   "signals": [
-    {},
     {},
     {
       "name": "tooltipSignal",
@@ -269,16 +261,7 @@
         {},
         {
           "orient": "left",
-          "scale": "yDetail",
-          "grid": true,
-          "title": {"signal":  "data('table')[0].axeLegend"},
-          "encode": {
-          "labels": {
-            "update": {
-              "text":  {"signal": "datum.value + ' ' + data('table')[0].axeUnit"}
-            }
-          }
-        }
+          "scale": "yDetail"
         }
       ],
       "marks": [
diff --git a/src/vega/body/windchart.json b/src/vega/body/windchart.json
index 207cf12..7bbb054 100644
--- a/src/vega/body/windchart.json
+++ b/src/vega/body/windchart.json
@@ -1,13 +1,8 @@
 {
   "signals": [
-    {},
     {
       "name": "detailDomain",
-      "update": "[time(data('range')[0].dateMin), time(data('range')[0].dateMin) + ((timeStep * 1000) * arrowCount)] "
-    },
-    {
-      "name": "arrowCount",
-      "value": 25
+      "update": "[time(data('range')[0].dateMin), time(data('range')[0].dateMin) + (timeWindow * arrowCount)] "
     },
     {
       "name": "minMaxRange",
@@ -15,7 +10,7 @@
     },
     {
       "name": "selectionWidth",
-      "update": "floor((arrowCount * (timeStep * 1000) * width) / minMaxRange)"
+      "update": "floor((arrowCount * timeWindow * width) / minMaxRange)"
     }
 
   ],
@@ -45,17 +40,17 @@
                     "value": "arrow"
                   },
                   "size": {
-                    "value": 500
+                    "value": 700
                   },
                   "x": {
                     "scale": "xDetail",
                     "field": "dateTime"
                   },
                   "y": {
-                    "value": 30
+                    "signal":  "detailHeight / 2"
                   },
                   "angle": {
-                    "field": "avg"
+                    "field": "value"
                   },
                   "color": {
                     "value": "both"
@@ -78,6 +73,40 @@
         {
           "update": "[0,selectionWidth]"
         }
+      ],
+      "marks": [
+        {},
+        {},
+        {},
+        {
+          "type": "symbol",
+          "from": {
+            "data": "table"
+          },
+          "encode": {
+            "update": {
+            "size": {
+              "value": 10
+            },
+            "x": {
+              "scale": "xOverview",
+              "field": "dateTime"
+            },
+            "y": {
+              "signal":  "overviewHeight / 2"
+            },
+            "color": {
+              "value": "both"
+            },
+            "strokeWidth": {
+              "value": 1
+            },
+            "fill": {
+              "value": "steelblue"
+            }
+          }
+          }
+        }
       ]
     }
   ]
diff --git a/src/vega/config/config-barline.json b/src/vega/config/config-barline.json
new file mode 100644
index 0000000..15737de
--- /dev/null
+++ b/src/vega/config/config-barline.json
@@ -0,0 +1,6 @@
+{
+  "signals": [
+    {"name":  "detailHeight", "value": 390},
+    {"name":  "overviewHeightStart", "value" : 430}
+  ]
+}
diff --git a/src/vega/config/config-multiline.json b/src/vega/config/config-multiline.json
index 2bd0b3d..24d96e1 100644
--- a/src/vega/config/config-multiline.json
+++ b/src/vega/config/config-multiline.json
@@ -3,8 +3,6 @@
     {"name":  "dataPath", "value":  "data"},
     {"name": "valuePath", "value": "data.value"},
     {"name":  "timestampPath", "value":  "data.time"},
-    {"name":  "sensorPath", "value":  "sensor.sensorName"},
-    {"name":  "axeLegendPath", "value":  "sensor.phenomenon.phenomenonName"},
-    {"name":  "axeLegendUnit", "value":  "sensor.phenomenon.unit"}
+    {"name":  "sensorPath", "value":  "sensor.sensorName"}
   ]
 }
diff --git a/src/vega/config/config-wind.json b/src/vega/config/config-wind.json
new file mode 100644
index 0000000..bc9e2a8
--- /dev/null
+++ b/src/vega/config/config-wind.json
@@ -0,0 +1,7 @@
+{
+  "signals": [
+    {"name":  "detailHeight", "value": 100},
+    {"name":  "overviewHeightStart", "value" : 140},
+    {"name":  "arrowCount", "value": 20}
+  ]
+}
diff --git a/src/vega/config/config.json b/src/vega/config/config.json
index c7be005..68843d6 100644
--- a/src/vega/config/config.json
+++ b/src/vega/config/config.json
@@ -1,12 +1,12 @@
 {
   "$schema": "https://vega.github.io/schema/vega/v5.json",
   "width": 800,
-  "height": 200,
-  "padding": 5,
+  "height": 300,
   "signals": [
-    {"name":  "detailHeight", "value": 390},
     {"name": "overviewHeight", "value":  70},
-    {"name":  "overviewHeightStart", "value" : 430},
-    {"name":  "maxTimeDifference", "value": 10000000}
+    {"name":  "maxTimeDifference", "value": 10000000},
+    {"name":  "axeLegendPath", "value":  "phenomenon.phenomenonName"},
+    {"name":  "axeUnitPath", "value":  "phenomenon.unit"},
+    {"name": "timeWindow", "value": 1800000}
   ]
 }
diff --git a/src/vega/miscs/legend.json b/src/vega/miscs/legend.json
new file mode 100644
index 0000000..6929a88
--- /dev/null
+++ b/src/vega/miscs/legend.json
@@ -0,0 +1,41 @@
+{
+  "data": [
+    {
+      "transform": [
+        {
+          "type": "project",
+          "fields": [
+            {
+              "signal": "axeLegendPath"
+            },
+            {
+              "signal": "axeUnitPath"
+            }
+          ],
+          "as": [
+            "axeLegend",
+            "axeUnit"
+          ]
+        }
+      ]
+    }
+  ],
+  "marks": [
+    {
+      "axes": [
+        {},
+        {
+          "grid": true,
+          "title": {"signal":  "data('legend')[0].axeLegend"},
+          "encode": {
+            "labels": {
+              "update": {
+                "text":  {"signal": "datum.value + ' ' + data('legend')[0].axeUnit"}
+              }
+            }
+          }
+        }
+      ]
+    }
+  ]
+}
diff --git a/src/vega/miscs/multiline-tooltip.json b/src/vega/miscs/multiline-tooltip.json
new file mode 100644
index 0000000..03a7631
--- /dev/null
+++ b/src/vega/miscs/multiline-tooltip.json
@@ -0,0 +1,27 @@
+{
+  "marks": [
+    {
+      "marks": [
+        {
+          "marks": [
+            {
+              "marks": [
+                {},
+                {},
+                {
+                  "encode": {
+                    "enter": {
+                      "tooltip": {
+                        "signal": null
+                      }
+                    }
+                  }
+                }
+              ]
+            }
+          ]
+        }
+      ]
+    }
+  ]
+}
diff --git a/src/vega/miscs/samm-tooltip.json b/src/vega/miscs/samm-tooltip.json
new file mode 100644
index 0000000..333eb69
--- /dev/null
+++ b/src/vega/miscs/samm-tooltip.json
@@ -0,0 +1,50 @@
+{
+  "data": [
+    {},
+    {},
+    {},
+    {
+      "transform": [
+        {
+          "fields": [
+            {"signal" :  "valuePath"},
+            {"signal":  "timestampPath"},
+            "sum",
+            "avg",
+            "min",
+            "max"
+
+          ],
+          "as": [
+            "value",
+            "timestamp",
+            "sum",
+            "avg",
+            "min",
+            "max"
+          ]
+        }
+      ]
+    }
+  ],
+  "marks": [
+    {
+      "marks": [
+        {
+          "marks": [
+            {
+              "encode": {
+                "enter": {
+                  "tooltip": {
+                    "signal": null
+                  }}
+              }
+
+
+            }
+          ]
+        }
+      ]
+    }
+  ]
+}
diff --git a/src/vega/miscs/value-tooltip.json b/src/vega/miscs/value-tooltip.json
new file mode 100644
index 0000000..91100b3
--- /dev/null
+++ b/src/vega/miscs/value-tooltip.json
@@ -0,0 +1,43 @@
+{
+  "data": [
+    {},
+    {},
+    {},
+    {
+      "transform": [
+        {
+          "fields": [
+            {"signal" :  "valuePath"},
+            {"signal":  "timestampPath"},
+            {"signal":  "gidPath"}
+          ],
+          "as": [
+            "value",
+            "timestamp",
+            "gid"
+          ]
+        }
+      ]
+    }
+  ],
+  "marks": [
+    {
+      "marks": [
+        {
+          "marks": [
+            {
+              "encode": {
+                "enter": {
+                  "tooltip": {
+                    "signal": null
+                  }}
+              }
+
+
+            }
+          ]
+        }
+      ]
+    }
+  ]
+}
diff --git a/src/vega/tooltip/multiline-tooltip.json b/src/vega/tooltip/multiline-tooltip.json
deleted file mode 100644
index 03a7631..0000000
--- a/src/vega/tooltip/multiline-tooltip.json
+++ /dev/null
@@ -1,27 +0,0 @@
-{
-  "marks": [
-    {
-      "marks": [
-        {
-          "marks": [
-            {
-              "marks": [
-                {},
-                {},
-                {
-                  "encode": {
-                    "enter": {
-                      "tooltip": {
-                        "signal": null
-                      }
-                    }
-                  }
-                }
-              ]
-            }
-          ]
-        }
-      ]
-    }
-  ]
-}
diff --git a/src/vega/tooltip/samm-tooltip.json b/src/vega/tooltip/samm-tooltip.json
deleted file mode 100644
index 135ce0c..0000000
--- a/src/vega/tooltip/samm-tooltip.json
+++ /dev/null
@@ -1,49 +0,0 @@
-{
-  "data": [
-    {},
-    {},
-    {
-      "transform": [
-        {
-          "fields": [
-            {"signal" :  "valuePath"},
-            {"signal":  "timestampPath"},
-            "sum",
-            "avg",
-            "min",
-            "max"
-
-          ],
-          "as": [
-            "value",
-            "timestamp",
-            "sum",
-            "avg",
-            "min",
-            "max"
-          ]
-        }
-      ]
-    }
-  ],
-  "marks": [
-    {
-      "marks": [
-        {
-          "marks": [
-            {
-              "encode": {
-                "enter": {
-                  "tooltip": {
-                    "signal": "{title: timeFormat(datum.dateTime, '%A, %e. %B %Y, %X')  ,  'avg': datum.avg, 'sum': datum.sum, 'max': datum.max, 'min': datum.min }"
-                  }}
-              }
-
-
-            }
-          ]
-        }
-      ]
-    }
-  ]
-}
diff --git a/src/vega/tooltip/value-tooltip.json b/src/vega/tooltip/value-tooltip.json
deleted file mode 100644
index 681d821..0000000
--- a/src/vega/tooltip/value-tooltip.json
+++ /dev/null
@@ -1,42 +0,0 @@
-{
-  "data": [
-    {},
-    {},
-    {
-      "transform": [
-        {
-          "fields": [
-            {"signal" :  "valuePath"},
-            {"signal":  "timestampPath"},
-            {"signal":  "gidPath"}
-          ],
-          "as": [
-            "value",
-            "timestamp",
-            "gid"
-          ]
-        }
-      ]
-    }
-  ],
-  "marks": [
-    {
-      "marks": [
-        {
-          "marks": [
-            {
-              "encode": {
-                "enter": {
-                  "tooltip": {
-                    "signal": "{title: timeFormat(datum.dateTime, '%A, %e. %B %Y, %X')  ,  'value': datum.value, 'gid': datum.gid }"
-                  }}
-              }
-
-
-            }
-          ]
-        }
-      ]
-    }
-  ]
-}
