Update RestClient getTimeseries method. UI: Improve dynamic form - allow to trim default values from value.
This commit is contained in:
		
							parent
							
								
									052b5cddb8
								
							
						
					
					
						commit
						178b2849ed
					
				@ -127,6 +127,7 @@ import org.thingsboard.server.common.data.id.WidgetTypeId;
 | 
				
			|||||||
import org.thingsboard.server.common.data.id.WidgetsBundleId;
 | 
					import org.thingsboard.server.common.data.id.WidgetsBundleId;
 | 
				
			||||||
import org.thingsboard.server.common.data.kv.Aggregation;
 | 
					import org.thingsboard.server.common.data.kv.Aggregation;
 | 
				
			||||||
import org.thingsboard.server.common.data.kv.AttributeKvEntry;
 | 
					import org.thingsboard.server.common.data.kv.AttributeKvEntry;
 | 
				
			||||||
 | 
					import org.thingsboard.server.common.data.kv.IntervalType;
 | 
				
			||||||
import org.thingsboard.server.common.data.kv.TsKvEntry;
 | 
					import org.thingsboard.server.common.data.kv.TsKvEntry;
 | 
				
			||||||
import org.thingsboard.server.common.data.mobile.app.MobileApp;
 | 
					import org.thingsboard.server.common.data.mobile.app.MobileApp;
 | 
				
			||||||
import org.thingsboard.server.common.data.mobile.bundle.MobileAppBundle;
 | 
					import org.thingsboard.server.common.data.mobile.bundle.MobileAppBundle;
 | 
				
			||||||
@ -2476,7 +2477,12 @@ public class RestClient implements Closeable {
 | 
				
			|||||||
        return getTimeseries(entityId, keys, interval, agg, sortOrder != null ? sortOrder.getDirection() : null, pageLink.getStartTime(), pageLink.getEndTime(), 100, useStrictDataTypes);
 | 
					        return getTimeseries(entityId, keys, interval, agg, sortOrder != null ? sortOrder.getDirection() : null, pageLink.getStartTime(), pageLink.getEndTime(), 100, useStrictDataTypes);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Deprecated
 | 
				
			||||||
    public List<TsKvEntry> getTimeseries(EntityId entityId, List<String> keys, Long interval, Aggregation agg, SortOrder.Direction sortOrder, Long startTime, Long endTime, Integer limit, boolean useStrictDataTypes) {
 | 
					    public List<TsKvEntry> getTimeseries(EntityId entityId, List<String> keys, Long interval, Aggregation agg, SortOrder.Direction sortOrder, Long startTime, Long endTime, Integer limit, boolean useStrictDataTypes) {
 | 
				
			||||||
 | 
					        return getTimeseries(entityId, keys, interval, null, null, agg, sortOrder, startTime, endTime, limit, useStrictDataTypes);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public List<TsKvEntry> getTimeseries(EntityId entityId, List<String> keys, Long interval, IntervalType intervalType, String timeZone, Aggregation agg, SortOrder.Direction sortOrder, Long startTime, Long endTime, Integer limit, boolean useStrictDataTypes) {
 | 
				
			||||||
        Map<String, String> params = new HashMap<>();
 | 
					        Map<String, String> params = new HashMap<>();
 | 
				
			||||||
        params.put("entityType", entityId.getEntityType().name());
 | 
					        params.put("entityType", entityId.getEntityType().name());
 | 
				
			||||||
        params.put("entityId", entityId.getId().toString());
 | 
					        params.put("entityId", entityId.getId().toString());
 | 
				
			||||||
@ -2490,6 +2496,16 @@ public class RestClient implements Closeable {
 | 
				
			|||||||
        StringBuilder urlBuilder = new StringBuilder(baseURL);
 | 
					        StringBuilder urlBuilder = new StringBuilder(baseURL);
 | 
				
			||||||
        urlBuilder.append("/api/plugins/telemetry/{entityType}/{entityId}/values/timeseries?keys={keys}&interval={interval}&limit={limit}&agg={agg}&useStrictDataTypes={useStrictDataTypes}&orderBy={orderBy}");
 | 
					        urlBuilder.append("/api/plugins/telemetry/{entityType}/{entityId}/values/timeseries?keys={keys}&interval={interval}&limit={limit}&agg={agg}&useStrictDataTypes={useStrictDataTypes}&orderBy={orderBy}");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (intervalType != null) {
 | 
				
			||||||
 | 
					            urlBuilder.append("&intervalType={intervalType}");
 | 
				
			||||||
 | 
					            params.put("intervalType", intervalType.name());
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (timeZone != null) {
 | 
				
			||||||
 | 
					            urlBuilder.append("&timeZone={timeZone}");
 | 
				
			||||||
 | 
					            params.put("timeZone", timeZone);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (startTime != null) {
 | 
					        if (startTime != null) {
 | 
				
			||||||
            urlBuilder.append("&startTs={startTs}");
 | 
					            urlBuilder.append("&startTs={startTs}");
 | 
				
			||||||
            params.put("startTs", String.valueOf(startTime));
 | 
					            params.put("startTs", String.valueOf(startTime));
 | 
				
			||||||
 | 
				
			|||||||
@ -958,3 +958,28 @@ export const unwrapModule = (module: any) : any => {
 | 
				
			|||||||
    return module;
 | 
					    return module;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const trimDefaultValues = (input: Record<string, any>, defaults: Record<string, any>): Record<string, any> => {
 | 
				
			||||||
 | 
					  const result: Record<string, any> = {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  for (const key in input) {
 | 
				
			||||||
 | 
					    if (!(key in defaults)) {
 | 
				
			||||||
 | 
					      result[key] = input[key];
 | 
				
			||||||
 | 
					    } else if (typeof defaults[key] === 'object' && defaults[key] !== null && typeof input[key] === 'object' && input[key] !== null) {
 | 
				
			||||||
 | 
					      const subPatch = trimDefaultValues(input[key], defaults[key]);
 | 
				
			||||||
 | 
					      if (Object.keys(subPatch).length > 0) {
 | 
				
			||||||
 | 
					        result[key] = subPatch;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    } else if (defaults[key] !== input[key]) {
 | 
				
			||||||
 | 
					      result[key] = input[key];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  for (const key in defaults) {
 | 
				
			||||||
 | 
					    if (!(key in input)) {
 | 
				
			||||||
 | 
					      delete result[key];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return result;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -37,7 +37,7 @@ import {
 | 
				
			|||||||
} from '@angular/forms';
 | 
					} from '@angular/forms';
 | 
				
			||||||
import { Store } from '@ngrx/store';
 | 
					import { Store } from '@ngrx/store';
 | 
				
			||||||
import { AppState } from '@core/core.state';
 | 
					import { AppState } from '@core/core.state';
 | 
				
			||||||
import { isDefinedAndNotNull, mergeDeep } from '@core/utils';
 | 
					import { isDefinedAndNotNull, mergeDeep, trimDefaultValues } from '@core/utils';
 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
  defaultFormProperties,
 | 
					  defaultFormProperties,
 | 
				
			||||||
  FormProperty,
 | 
					  FormProperty,
 | 
				
			||||||
@ -106,10 +106,16 @@ export class DynamicFormComponent implements OnInit, OnChanges, ControlValueAcce
 | 
				
			|||||||
  @coerceBoolean()
 | 
					  @coerceBoolean()
 | 
				
			||||||
  noBorder = false;
 | 
					  noBorder = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @Input()
 | 
				
			||||||
 | 
					  @coerceBoolean()
 | 
				
			||||||
 | 
					  trimDefaults = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  private modelValue: {[id: string]: any};
 | 
					  private modelValue: {[id: string]: any};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  private propagateChange = null;
 | 
					  private propagateChange = null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  private defaults: {[id: string]: any};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  private validatorTriggers: string[];
 | 
					  private validatorTriggers: string[];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  public propertiesFormGroup: UntypedFormGroup;
 | 
					  public propertiesFormGroup: UntypedFormGroup;
 | 
				
			||||||
@ -180,11 +186,13 @@ export class DynamicFormComponent implements OnInit, OnChanges, ControlValueAcce
 | 
				
			|||||||
  private loadMetadata() {
 | 
					  private loadMetadata() {
 | 
				
			||||||
    this.validatorTriggers = [];
 | 
					    this.validatorTriggers = [];
 | 
				
			||||||
    this.propertyGroups = [];
 | 
					    this.propertyGroups = [];
 | 
				
			||||||
 | 
					    this.defaults = {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (const control of Object.keys(this.propertiesFormGroup.controls)) {
 | 
					    for (const control of Object.keys(this.propertiesFormGroup.controls)) {
 | 
				
			||||||
      this.propertiesFormGroup.removeControl(control, {emitEvent: false});
 | 
					      this.propertiesFormGroup.removeControl(control, {emitEvent: false});
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (this.properties) {
 | 
					    if (this.properties) {
 | 
				
			||||||
 | 
					      this.defaults = defaultFormProperties(this.properties);
 | 
				
			||||||
      for (let property of this.properties) {
 | 
					      for (let property of this.properties) {
 | 
				
			||||||
        property.disabled = false;
 | 
					        property.disabled = false;
 | 
				
			||||||
        property.visible = true;
 | 
					        property.visible = true;
 | 
				
			||||||
@ -282,8 +290,7 @@ export class DynamicFormComponent implements OnInit, OnChanges, ControlValueAcce
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  private setupValue() {
 | 
					  private setupValue() {
 | 
				
			||||||
    if (this.properties) {
 | 
					    if (this.properties) {
 | 
				
			||||||
      const defaults = defaultFormProperties(this.properties);
 | 
					      this.modelValue = mergeDeep<{[id: string]: any}>({}, this.defaults, this.modelValue);
 | 
				
			||||||
      this.modelValue = mergeDeep<{[id: string]: any}>(defaults, this.modelValue);
 | 
					 | 
				
			||||||
      this.propertiesFormGroup.patchValue(
 | 
					      this.propertiesFormGroup.patchValue(
 | 
				
			||||||
        this.modelValue, {emitEvent: false}
 | 
					        this.modelValue, {emitEvent: false}
 | 
				
			||||||
      );
 | 
					      );
 | 
				
			||||||
@ -295,7 +302,11 @@ export class DynamicFormComponent implements OnInit, OnChanges, ControlValueAcce
 | 
				
			|||||||
  private updateModel() {
 | 
					  private updateModel() {
 | 
				
			||||||
    this.modelValue = this.propertiesFormGroup.getRawValue();
 | 
					    this.modelValue = this.propertiesFormGroup.getRawValue();
 | 
				
			||||||
    this.calculateControlsState(true);
 | 
					    this.calculateControlsState(true);
 | 
				
			||||||
    this.propagateChange(this.modelValue);
 | 
					    let result = this.modelValue;
 | 
				
			||||||
 | 
					    if (this.trimDefaults) {
 | 
				
			||||||
 | 
					      result = trimDefaultValues(this.modelValue, this.defaults);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    this.propagateChange(result);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user