You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@streampipes.apache.org by ri...@apache.org on 2022/02/04 16:11:15 UTC

[incubator-streampipes] branch experimental-module-federation-494 updated: [hotfix] Show possible values of tags in data explorer query config

This is an automated email from the ASF dual-hosted git repository.

riemer pushed a commit to branch experimental-module-federation-494
in repository https://gitbox.apache.org/repos/asf/incubator-streampipes.git


The following commit(s) were added to refs/heads/experimental-module-federation-494 by this push:
     new 29612cb  [hotfix] Show possible values of tags in data explorer query config
29612cb is described below

commit 29612cb4f57db521f0e84285be4541bdb873f836
Author: Dominik Riemer <do...@gmail.com>
AuthorDate: Fri Feb 4 17:10:58 2022 +0100

    [hotfix] Show possible values of tags in data explorer query config
---
 .../dataexplorer/DataLakeManagementV4.java         | 42 +++++++++++++++++++---
 .../apache/streampipes/ps/DataLakeResourceV4.java  |  9 +++++
 .../src/lib/apis/datalake-rest.service.ts          |  6 ++++
 .../filter-selection-panel.component.html          | 22 ++++++++++--
 .../filter-selection-panel.component.ts            | 40 +++++++++++++++++----
 5 files changed, 106 insertions(+), 13 deletions(-)

diff --git a/streampipes-data-explorer/src/main/java/org/apache/streampipes/dataexplorer/DataLakeManagementV4.java b/streampipes-data-explorer/src/main/java/org/apache/streampipes/dataexplorer/DataLakeManagementV4.java
index 11aff0a..9f659f1 100644
--- a/streampipes-data-explorer/src/main/java/org/apache/streampipes/dataexplorer/DataLakeManagementV4.java
+++ b/streampipes-data-explorer/src/main/java/org/apache/streampipes/dataexplorer/DataLakeManagementV4.java
@@ -20,6 +20,7 @@ package org.apache.streampipes.dataexplorer;
 
 import com.google.gson.Gson;
 import com.google.gson.JsonObject;
+import org.apache.streampipes.config.backend.BackendConfig;
 import org.apache.streampipes.dataexplorer.param.RetentionPolicyQueryParams;
 import org.apache.streampipes.dataexplorer.query.DeleteDataQuery;
 import org.apache.streampipes.dataexplorer.query.EditRetentionPolicyQuery;
@@ -31,24 +32,32 @@ import org.apache.streampipes.dataexplorer.v4.SupportedDataLakeQueryParameters;
 import org.apache.streampipes.dataexplorer.v4.params.QueryParamsV4;
 import org.apache.streampipes.dataexplorer.v4.query.DataExplorerQueryV4;
 import org.apache.streampipes.dataexplorer.v4.utils.DataLakeManagementUtils;
-import org.apache.streampipes.model.datalake.*;
+import org.apache.streampipes.model.datalake.DataLakeConfiguration;
+import org.apache.streampipes.model.datalake.DataLakeMeasure;
+import org.apache.streampipes.model.datalake.DataLakeRetentionPolicy;
+import org.apache.streampipes.model.datalake.SpQueryResult;
 import org.apache.streampipes.storage.couchdb.utils.Utils;
+import org.influxdb.InfluxDB;
+import org.influxdb.dto.Query;
 import org.influxdb.dto.QueryResult;
 import org.lightcouch.CouchDbClient;
 
 import java.io.IOException;
 import java.io.OutputStream;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.time.*;
+import java.time.Instant;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.ZonedDateTime;
 import java.time.format.DateTimeFormatter;
 import java.time.format.DateTimeFormatterBuilder;
 import java.time.temporal.ChronoField;
 import java.time.temporal.ChronoUnit;
 import java.time.temporal.TemporalAccessor;
+import java.util.Arrays;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.TimeZone;
+import java.util.stream.Collectors;
 
 import static org.apache.streampipes.dataexplorer.v4.SupportedDataLakeQueryParameters.*;
 
@@ -294,4 +303,27 @@ public class DataLakeManagementV4 {
         return Instant.EPOCH.until(instant, ChronoUnit.MILLIS);
     }
 
+    public Map<String, Object> getTagValues(String measurementId,
+                                            String fields) {
+        InfluxDB influxDB = DataExplorerUtils.getInfluxDBClient();
+        Map<String, Object> tags = new HashMap<>();
+        List<String> fieldList = Arrays.asList(fields.split(","));
+        fieldList.forEach(f -> {
+                String q = "SHOW TAG VALUES ON \"" + BackendConfig.INSTANCE.getInfluxDatabaseName() + "\" FROM \"" +measurementId + "\" WITH KEY = \"" +f + "\"";
+                Query query = new Query(q);
+                QueryResult queryResult = influxDB.query(query);
+                queryResult.getResults().forEach(res -> {
+                    res.getSeries().forEach(series -> {
+                        if (series.getValues().size() > 0) {
+                            String field = series.getValues().get(0).get(0).toString();
+                            List<String> values = series.getValues().stream().map(v -> v.get(1).toString()).collect(Collectors.toList());
+                            tags.put(field, values);
+                        }
+                    });
+                });
+                System.out.println(queryResult.getResults().size());
+        });
+
+        return tags;
+    }
 }
diff --git a/streampipes-platform-services/src/main/java/org/apache/streampipes/ps/DataLakeResourceV4.java b/streampipes-platform-services/src/main/java/org/apache/streampipes/ps/DataLakeResourceV4.java
index 28350d1..4791b4c 100644
--- a/streampipes-platform-services/src/main/java/org/apache/streampipes/ps/DataLakeResourceV4.java
+++ b/streampipes-platform-services/src/main/java/org/apache/streampipes/ps/DataLakeResourceV4.java
@@ -120,6 +120,15 @@ public class DataLakeResourceV4 extends AbstractRestResource {
         return ok(allMeasurements);
     }
 
+    @GET
+    @Path("/measurements/{measurementId}/tags")
+    @Produces(MediaType.APPLICATION_JSON)
+    public Response getTagValues(@PathParam("measurementId") String measurementId,
+                                 @QueryParam("fields") String fields) {
+        Map<String, Object> tagValues = dataLakeManagement.getTagValues(measurementId, fields);
+        return ok(tagValues);
+    }
+
 
     @GET
     @Path("/measurements/{measurementID}")
diff --git a/ui/projects/streampipes/platform-services/src/lib/apis/datalake-rest.service.ts b/ui/projects/streampipes/platform-services/src/lib/apis/datalake-rest.service.ts
index d4f1331..b1adceb 100644
--- a/ui/projects/streampipes/platform-services/src/lib/apis/datalake-rest.service.ts
+++ b/ui/projects/streampipes/platform-services/src/lib/apis/datalake-rest.service.ts
@@ -64,6 +64,12 @@ export class DatalakeRestService {
     return this.http.get<PageResult>(url, { params: queryParams });
   }
 
+  getTagValues(index: string,
+               fieldNames: string[]): Observable<Map<string, string[]>> {
+    return this.http.get(this.dataLakeUrl + '/measurements/' + index + '/tags?fields=' + fieldNames.toString())
+      .pipe(map(r => r as Map<string, string[]>));
+  }
+
   // getGroupedData(index: string, groupingTags: string, aggregationFunction?: string, columns?: string, startDate?: number, endDate?:
   //   number, aggregationTimeUnit?: string, aggregationTimeValue?: number, order?: string, limit?: number):
   //   Observable<SpQueryResult> {
diff --git a/ui/src/app/data-explorer/components/designer-panel/data-settings/filter-selection-panel/filter-selection-panel.component.html b/ui/src/app/data-explorer/components/designer-panel/data-settings/filter-selection-panel/filter-selection-panel.component.html
index 8d360a4..236855a 100644
--- a/ui/src/app/data-explorer/components/designer-panel/data-settings/filter-selection-panel/filter-selection-panel.component.html
+++ b/ui/src/app/data-explorer/components/designer-panel/data-settings/filter-selection-panel/filter-selection-panel.component.html
@@ -65,13 +65,31 @@
                         </mat-option>
                     </mat-select>
                 </mat-form-field>
-                <mat-form-field color="accent" class="w-140-px mr-5">
+                <mat-form-field color="accent" class="w-140-px mr-5" *ngIf="!filter.field || !tagValues.has(filter.field.runtimeName)">
                     <mat-label>Value</mat-label>
-                    <input matInput
+                    <input type="text"
+                           placeholder="Value"
+                           aria-label="Number"
+                           matInput
                            [(ngModel)]="filter.value"
                            (change)="updateWidget()"
                            data-cy="design-panel-data-settings-filter-value">
                 </mat-form-field>
+                <mat-form-field color="accent" class="w-140-px mr-5" *ngIf="filter.field && tagValues.has(filter.field.runtimeName)">
+                    <input type="text"
+                           placeholder="Value"
+                           aria-label="Number"
+                           matInput
+                           [(ngModel)]="filter.value"
+                           (change)="updateWidget()"
+                           data-cy="design-panel-data-settings-filter-value"
+                           [matAutocomplete]="auto">
+                    <mat-autocomplete #auto="matAutocomplete" (optionSelected)="updateWidget()">
+                        <mat-option *ngFor="let value of tagValues.get(filter.field.runtimeName)" [value]="value">
+                            {{value}}
+                        </mat-option>
+                    </mat-autocomplete>
+                </mat-form-field>
                 <button mat-icon-button color="accent"
                         (click)="remove(sourceConfig, filter.index)"
                         data-cy="design-panel-data-settings-remove-filter">
diff --git a/ui/src/app/data-explorer/components/designer-panel/data-settings/filter-selection-panel/filter-selection-panel.component.ts b/ui/src/app/data-explorer/components/designer-panel/data-settings/filter-selection-panel/filter-selection-panel.component.ts
index 51162b6..7b6eff3 100644
--- a/ui/src/app/data-explorer/components/designer-panel/data-settings/filter-selection-panel/filter-selection-panel.component.ts
+++ b/ui/src/app/data-explorer/components/designer-panel/data-settings/filter-selection-panel/filter-selection-panel.component.ts
@@ -16,21 +16,47 @@
  *
  */
 
-import { Component, Input } from '@angular/core';
-import { FieldConfig, SelectedFilter, SourceConfig } from '@streampipes/platform-services';
+import { Component, Input, OnInit } from '@angular/core';
+import { DatalakeRestService, FieldConfig, SelectedFilter, SourceConfig } from '@streampipes/platform-services';
 import { WidgetConfigurationService } from '../../../../services/widget-configuration.service';
+import { DataExplorerFieldProviderService } from '../../../../services/data-explorer-field-provider-service';
 
 @Component({
   selector: 'sp-filter-selection-panel',
   templateUrl: './filter-selection-panel.component.html',
   styleUrls: ['./filter-selection-panel.component.scss']
 })
-export class FilterSelectionPanelComponent {
+export class FilterSelectionPanelComponent implements OnInit {
 
   @Input() sourceConfig: SourceConfig;
   @Input() widgetId: string;
 
-  constructor(private widgetConfigService: WidgetConfigurationService) {
+  tagValues: Map<string, string[]> = new Map<string, string[]>();
+
+  constructor(private widgetConfigService: WidgetConfigurationService,
+              private fieldProviderService: DataExplorerFieldProviderService,
+              private dataLakeRestService: DatalakeRestService) {
+  }
+
+  ngOnInit(): void {
+    this.sourceConfig.queryConfig.fields.forEach(f => {
+      this.tagValues.set(f.runtimeName, []);
+    });
+    const fieldProvider = this.fieldProviderService.generateFieldLists([this.sourceConfig]);
+    this.sourceConfig.queryConfig.fields
+      .filter(f => fieldProvider.booleanFields
+        .find(df => df.measure === this.sourceConfig.measureName && df.runtimeName === f.runtimeName))
+      .forEach(f => this.tagValues.set(f.runtimeName, ['true', 'false']));
+    const fields = this.sourceConfig.queryConfig.fields
+      .filter(f =>
+        fieldProvider.dimensionFields.find(df => (df.measure === this.sourceConfig.measureName && df.runtimeName === f.runtimeName)))
+      .map(f => f.runtimeName);
+    this.dataLakeRestService.getTagValues(this.sourceConfig.measureName, fields).subscribe(response => {
+      Object.keys(response).forEach(key => {
+        this.tagValues.set(key, response[key]);
+      });
+    });
+
   }
 
   addFilter() {
@@ -40,7 +66,7 @@ export class FilterSelectionPanelComponent {
       value: ''
     };
     this.sourceConfig.queryConfig.selectedFilters.push(newFilter);
-    this.widgetConfigService.notify({ widgetId: this.widgetId, refreshData: true, refreshView: true });
+    this.widgetConfigService.notify({widgetId: this.widgetId, refreshData: true, refreshView: true});
     this.updateWidget();
   }
 
@@ -58,11 +84,13 @@ export class FilterSelectionPanelComponent {
     });
 
     if (update) {
-      this.widgetConfigService.notify({ widgetId: this.widgetId, refreshData: true, refreshView: true });
+      this.widgetConfigService.notify({widgetId: this.widgetId, refreshData: true, refreshView: true});
     }
   }
 
   compare(available: FieldConfig, selected: FieldConfig) {
     return (available.runtimeName === selected.runtimeName);
   }
+
+
 }