From 48e5aed0b628f98b009fc625d42869da08b02512 Mon Sep 17 00:00:00 2001 From: Artem Babak Date: Wed, 6 Jul 2022 14:33:18 +0300 Subject: [PATCH 001/108] Rate limits implementation --- .../home/components/home-components.module.ts | 16 +- ...enant-profile-configuration.component.html | 118 +++++-------- ...-tenant-profile-configuration.component.ts | 3 + .../rate-limits-details-dialog.component.html | 52 ++++++ .../rate-limits-details-dialog.component.ts | 83 +++++++++ .../rate-limits-list.component.html | 61 +++++++ .../rate-limits-list.component.scss | 47 +++++ .../rate-limits/rate-limits-list.component.ts | 161 ++++++++++++++++++ .../rate-limits-text.component.html | 19 +++ .../rate-limits-text.component.scss | 49 ++++++ .../rate-limits/rate-limits-text.component.ts | 98 +++++++++++ .../rate-limits/rate-limits.component.html | 34 ++++ .../rate-limits/rate-limits.component.scss | 31 ++++ .../rate-limits/rate-limits.component.ts | 153 +++++++++++++++++ .../app/shared/models/rate-limits.models.ts | 137 +++++++++++++++ .../assets/locale/locale.constant-en_US.json | 36 +++- 16 files changed, 1018 insertions(+), 80 deletions(-) create mode 100644 ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-details-dialog.component.html create mode 100644 ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-details-dialog.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-list.component.html create mode 100644 ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-list.component.scss create mode 100644 ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-list.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-text.component.html create mode 100644 ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-text.component.scss create mode 100644 ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-text.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits.component.html create mode 100644 ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits.component.scss create mode 100644 ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits.component.ts create mode 100644 ui-ngx/src/app/shared/models/rate-limits.models.ts diff --git a/ui-ngx/src/app/modules/home/components/home-components.module.ts b/ui-ngx/src/app/modules/home/components/home-components.module.ts index d195137509..9468289df8 100644 --- a/ui-ngx/src/app/modules/home/components/home-components.module.ts +++ b/ui-ngx/src/app/modules/home/components/home-components.module.ts @@ -166,6 +166,10 @@ import { EntityTypesVersionLoadComponent } from '@home/components/vc/entity-type import { ComplexVersionLoadComponent } from '@home/components/vc/complex-version-load.component'; import { RemoveOtherEntitiesConfirmComponent } from '@home/components/vc/remove-other-entities-confirm.component'; import { AutoCommitSettingsComponent } from '@home/components/vc/auto-commit-settings.component'; +import { RateLimitsListComponent } from '@home/components/profile/tenant/rate-limits/rate-limits-list.component'; +import { RateLimitsComponent } from '@home/components/profile/tenant/rate-limits/rate-limits.component'; +import { RateLimitsTextComponent } from '@home/components/profile/tenant/rate-limits/rate-limits-text.component'; +import { RateLimitsDetailsDialogComponent } from '@home/components/profile/tenant/rate-limits/rate-limits-details-dialog.component'; @NgModule({ declarations: @@ -302,7 +306,11 @@ import { AutoCommitSettingsComponent } from '@home/components/vc/auto-commit-set EntityTypesVersionLoadComponent, ComplexVersionLoadComponent, RemoveOtherEntitiesConfirmComponent, - AutoCommitSettingsComponent + AutoCommitSettingsComponent, + RateLimitsListComponent, + RateLimitsComponent, + RateLimitsTextComponent, + RateLimitsDetailsDialogComponent ], imports: [ CommonModule, @@ -432,7 +440,11 @@ import { AutoCommitSettingsComponent } from '@home/components/vc/auto-commit-set EntityTypesVersionLoadComponent, ComplexVersionLoadComponent, RemoveOtherEntitiesConfirmComponent, - AutoCommitSettingsComponent + AutoCommitSettingsComponent, + RateLimitsListComponent, + RateLimitsComponent, + RateLimitsTextComponent, + RateLimitsDetailsDialogComponent ], providers: [ WidgetComponentService, diff --git a/ui-ngx/src/app/modules/home/components/profile/tenant/default-tenant-profile-configuration.component.html b/ui-ngx/src/app/modules/home/components/profile/tenant/default-tenant-profile-configuration.component.html index 0e1553806a..5484aaed28 100644 --- a/ui-ngx/src/app/modules/home/components/profile/tenant/default-tenant-profile-configuration.component.html +++ b/ui-ngx/src/app/modules/home/components/profile/tenant/default-tenant-profile-configuration.component.html @@ -418,38 +418,24 @@
- Rate limits + + {{ 'tenant-profile.rate-limits.rate-limits' | translate }} +
- - tenant-profile.transport-tenant-msg-rate-limit - - - {{ 'tenant-profile.incorrect-pattern-for-rate-limits' | translate}} - - - - tenant-profile.transport-device-msg-rate-limit - - - {{ 'tenant-profile.incorrect-pattern-for-rate-limits' | translate}} - - + + + +
- - tenant-profile.transport-tenant-telemetry-msg-rate-limit - - - {{ 'tenant-profile.incorrect-pattern-for-rate-limits' | translate}} - - - - tenant-profile.transport-device-telemetry-msg-rate-limit - - - {{ 'tenant-profile.incorrect-pattern-for-rate-limits' | translate}} - - + + + +
@@ -459,40 +445,28 @@
- - tenant-profile.transport-tenant-telemetry-data-points-rate-limit - - - {{ 'tenant-profile.incorrect-pattern-for-rate-limits' | translate}} - - - - tenant-profile.transport-device-telemetry-data-points-rate-limit - - - {{ 'tenant-profile.incorrect-pattern-for-rate-limits' | translate}} - - + + + +
- - tenant-profile.tenant-rest-limits - - - {{ 'tenant-profile.incorrect-pattern-for-rate-limits' | translate}} - - - - tenant-profile.customer-rest-limits - - - {{ 'tenant-profile.incorrect-pattern-for-rate-limits' | translate}} - - + + + + +
+
+ + + +
@@ -503,22 +477,12 @@ tenant-profile.tenant-entity-import-rate-limit -
-
- - tenant-profile.ws-limit-updates-per-session - - - {{ 'tenant-profile.incorrect-pattern-for-rate-limits' | translate}} - - - - tenant-profile.cassandra-tenant-limits-configuration - - - {{ 'tenant-profile.incorrect-pattern-for-rate-limits' | translate}} - - +
diff --git a/ui-ngx/src/app/modules/home/components/profile/tenant/default-tenant-profile-configuration.component.ts b/ui-ngx/src/app/modules/home/components/profile/tenant/default-tenant-profile-configuration.component.ts index 65f030a3a6..ac2702ca43 100644 --- a/ui-ngx/src/app/modules/home/components/profile/tenant/default-tenant-profile-configuration.component.ts +++ b/ui-ngx/src/app/modules/home/components/profile/tenant/default-tenant-profile-configuration.component.ts @@ -21,6 +21,7 @@ import { AppState } from '@app/core/core.state'; import { coerceBooleanProperty } from '@angular/cdk/coercion'; import { DefaultTenantProfileConfiguration, TenantProfileConfiguration } from '@shared/models/tenant.model'; import { isDefinedAndNotNull } from '@core/utils'; +import { RateLimitsType } from '@shared/models/rate-limits.models'; @Component({ selector: 'tb-default-tenant-profile-configuration', @@ -49,6 +50,8 @@ export class DefaultTenantProfileConfigurationComponent implements ControlValueA @Input() disabled: boolean; + rateLimitsType = RateLimitsType; + private propagateChange = (v: any) => { }; constructor(private store: Store, diff --git a/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-details-dialog.component.html b/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-details-dialog.component.html new file mode 100644 index 0000000000..911b44ecd8 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-details-dialog.component.html @@ -0,0 +1,52 @@ + +
+ +

{{ title }}

+ + +
+ + +
+
+
+ + +
+
+
+
+ + +
+
diff --git a/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-details-dialog.component.ts b/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-details-dialog.component.ts new file mode 100644 index 0000000000..69bf5cda4f --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-details-dialog.component.ts @@ -0,0 +1,83 @@ +/// +/// Copyright © 2016-2022 The Thingsboard Authors +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +/// See the License for the specific language governing permissions and +/// limitations under the License. +/// + +import { Component, Inject, OnInit, SkipSelf } from '@angular/core'; +import { ErrorStateMatcher } from '@angular/material/core'; +import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; +import { Store } from '@ngrx/store'; +import { AppState } from '@core/core.state'; +import { FormBuilder, FormControl, FormGroup, FormGroupDirective, NgForm } from '@angular/forms'; +import { Router } from '@angular/router'; +import { DialogComponent } from '@app/shared/components/dialog.component'; +import { TranslateService } from '@ngx-translate/core'; + +export interface RateLimitsDetailsDialogData { + rateLimits: string; + title: string; + readonly: boolean; +} + +@Component({ + templateUrl: './rate-limits-details-dialog.component.html', + providers: [{provide: ErrorStateMatcher, useExisting: RateLimitsDetailsDialogComponent}] +}) +export class RateLimitsDetailsDialogComponent extends DialogComponent + implements OnInit, ErrorStateMatcher { + + editDetailsFormGroup: FormGroup; + + submitted: boolean = false; + + rateLimits: string = this.data.rateLimits; + + title: string = this.data.title; + + constructor(protected store: Store, + protected router: Router, + @Inject(MAT_DIALOG_DATA) public data: RateLimitsDetailsDialogData, + @SkipSelf() private errorStateMatcher: ErrorStateMatcher, + public dialogRef: MatDialogRef, + private fb: FormBuilder, + public translate: TranslateService) { + super(store, router, dialogRef); + + this.editDetailsFormGroup = this.fb.group({ + rateLimits: [this.rateLimits, []] + }); + if (this.data.readonly) { + this.editDetailsFormGroup.disable(); + } + } + + ngOnInit(): void { + } + + isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean { + const originalErrorState = this.errorStateMatcher.isErrorState(control, form); + const customErrorState = !!(control && control.invalid && this.submitted); + return originalErrorState || customErrorState; + } + + cancel(): void { + this.dialogRef.close(null); + } + + save(): void { + this.submitted = true; + this.dialogRef.close(this.editDetailsFormGroup.get('rateLimits').value); + } + +} diff --git a/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-list.component.html b/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-list.component.html new file mode 100644 index 0000000000..c0923927d8 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-list.component.html @@ -0,0 +1,61 @@ + +
+
+
+ tenant-profile.rate-limits.but-less-than +
+
+ + tenant-profile.rate-limits.number-of-messages + + + {{ 'tenant-profile.rate-limits.number-of-messages-required' | translate }} + + + + tenant-profile.rate-limits.per-seconds + + + {{ 'tenant-profile.rate-limits.per-seconds-required' | translate }} + + + +
+
+
+ +
+
+ tenant-profile.rate-limits.preview +
+ +
+
+
diff --git a/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-list.component.scss b/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-list.component.scss new file mode 100644 index 0000000000..0db3694166 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-list.component.scss @@ -0,0 +1,47 @@ +/** + * Copyright © 2016-2022 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +:host { + button { + min-width: 40px; + mat-icon { + margin-top: 0.6em; + } + } + .tb-rate-limits-preview { + margin-top: 1.5em; + span { + padding-left: 1em; + } + div { + border: 1px groove rgba(0, 0, 0, .25); + border-radius: 4px; + padding: 1em; + } + } + .tb-rate-limits-operation { + font-size: 12px; + color: rgba(0,0,0,.54); + margin-bottom: 16px; + } +} + +:host ::ng-deep { + mat-form-field { + .mat-form-field-wrapper { + padding-bottom: 1em; + } + } +} diff --git a/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-list.component.ts b/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-list.component.ts new file mode 100644 index 0000000000..eb7a37cfde --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-list.component.ts @@ -0,0 +1,161 @@ +/// +/// Copyright © 2016-2022 The Thingsboard Authors +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +/// See the License for the specific language governing permissions and +/// limitations under the License. +/// + +import { Component, forwardRef, Input, OnInit } from '@angular/core'; +import { + ControlValueAccessor, + FormArray, + FormBuilder, + FormControl, + FormGroup, + NG_VALIDATORS, + NG_VALUE_ACCESSOR, + ValidationErrors, + Validator, + Validators +} from '@angular/forms'; +import { Subscription } from 'rxjs'; +import { + RateLimits, + rateLimitsArrayToString, + stringToRateLimitsArray +} from '@shared/models/rate-limits.models'; +import { isDefinedAndNotNull } from '@core/utils'; + +@Component({ + selector: 'tb-rate-limits-list', + templateUrl: './rate-limits-list.component.html', + styleUrls: ['./rate-limits-list.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => RateLimitsListComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => RateLimitsListComponent), + multi: true + } + ] +}) +export class RateLimitsListComponent implements ControlValueAccessor, Validator, OnInit { + + @Input() disabled: boolean; + + rateLimitsListFormGroup: FormGroup; + + rateLimitsControl: FormControl; + + private propagateChange = (v: any) => { }; + + private valueChangeSubscription: Subscription = null; + + constructor(private fb: FormBuilder) { + } + + ngOnInit(): void { + this.rateLimitsListFormGroup = this.fb.group({}); + this.rateLimitsListFormGroup.addControl('rateLimits', + this.fb.array([])); + this.rateLimitsControl = this.fb.control(null); + this.rateLimitsListFormGroup.valueChanges.subscribe((value) => { + this.updateView(value?.rateLimits); + } + ); + } + + rateLimitsFormArray(): FormArray { + return this.rateLimitsListFormGroup.get('rateLimits') as FormArray; + } + + registerOnChange(fn: any): void { + this.propagateChange = fn; + } + + registerOnTouched(fn: any): void { + } + + setDisabledState?(isDisabled: boolean): void { + this.disabled = isDisabled; + if (this.disabled) { + this.rateLimitsListFormGroup.disable({emitEvent: false}); + this.rateLimitsControl.disable({emitEvent: false}); + } else { + this.rateLimitsListFormGroup.enable({emitEvent: false}); + this.rateLimitsControl.enable({emitEvent: false}); + } + } + + validate(): ValidationErrors | null { + return this.rateLimitsListFormGroup.valid && this.rateLimitsControl.valid ? null : { + rateLimitsList: {valid: false} + }; + } + + writeValue(value: string) { + if (this.valueChangeSubscription) { + this.valueChangeSubscription.unsubscribe(); + } + const rateLimitsControls: Array = []; + if (value) { + let rateLimitsArray = value.split(','); + for (let i = 0; i < rateLimitsArray.length; i++) { + let valueTime = rateLimitsArray[i].split(':'); + let value = valueTime[0]; + let time = valueTime[1]; + const rateLimitsControl = this.fb.group({ + value: [value, [Validators.required]], + time: [time, [Validators.required]] + }); + if (this.disabled) { + rateLimitsControl.disable(); + } + rateLimitsControls.push(rateLimitsControl); + } + } + this.rateLimitsListFormGroup.setControl('rateLimits', this.fb.array(rateLimitsControls)); + this.rateLimitsControl.patchValue(stringToRateLimitsArray(value), {emitEvent: false}); + this.valueChangeSubscription = this.rateLimitsListFormGroup.valueChanges.subscribe((value) => { + this.updateView(value?.rateLimits); + }); + } + + public removeRateLimits(index: number) { + (this.rateLimitsListFormGroup.get('rateLimits') as FormArray).removeAt(index); + } + + public addRateLimits() { + const rateLimitsArray = this.rateLimitsListFormGroup.get('rateLimits') as FormArray; + rateLimitsArray.push(this.fb.group({ + value: [null, [Validators.required]], + time: [null, [Validators.required]] + })); + this.rateLimitsListFormGroup.updateValueAndValidity(); + } + + updateView(rateLimitsArray: Array) { + if (rateLimitsArray.length > 0) { + const notNullRateLimits = rateLimitsArray.filter(rateLimits => isDefinedAndNotNull(rateLimits.value) && isDefinedAndNotNull(rateLimits.time)); + const rateLimitsString = rateLimitsArrayToString(notNullRateLimits); + this.propagateChange(rateLimitsString); + this.rateLimitsControl.patchValue(stringToRateLimitsArray(rateLimitsString), {emitEvent: false}); + } else { + this.propagateChange(null); + this.rateLimitsControl.patchValue(null, {emitEvent: false}); + } + } +} diff --git a/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-text.component.html b/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-text.component.html new file mode 100644 index 0000000000..98a30b055e --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-text.component.html @@ -0,0 +1,19 @@ + +
diff --git a/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-text.component.scss b/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-text.component.scss new file mode 100644 index 0000000000..a8f8f8553f --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-text.component.scss @@ -0,0 +1,49 @@ +/** + * Copyright © 2016-2022 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +:host { + .tb-rate-limits-text { + overflow: hidden; + + &.disabled { + opacity: 0.7; + } + &.required { + color: #f44336; + padding: 0 4px; + } + &.nowrap { + white-space: nowrap; + overflow: hidden; + } + } +} + +:host ::ng-deep { + .tb-rate-limits-text { + span { + font-size: 14px; + line-height: 1.8em; + } + .tb-rate-limits-value { + font-weight: bold; + border: 1px groove rgba(0, 0, 0, .25); + border-radius: 4px; + padding-left: 4px; + padding-right: 4px; + color: #305680; + } + } +} diff --git a/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-text.component.ts b/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-text.component.ts new file mode 100644 index 0000000000..9ab7e9b56b --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-text.component.ts @@ -0,0 +1,98 @@ +/// +/// Copyright © 2016-2022 The Thingsboard Authors +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +/// See the License for the specific language governing permissions and +/// limitations under the License. +/// + +import { Component, forwardRef, Input, OnInit } from '@angular/core'; +import { ControlValueAccessor, FormBuilder, NG_VALUE_ACCESSOR } from '@angular/forms'; +import { MatDialog } from '@angular/material/dialog'; +import { TranslateService } from '@ngx-translate/core'; +import { coerceBooleanProperty } from '@angular/cdk/coercion'; +import { RateLimits, rateLimitsArrayToHtml } from '@shared/models/rate-limits.models'; + +@Component({ + selector: 'tb-rate-limits-text', + templateUrl: './rate-limits-text.component.html', + styleUrls: ['./rate-limits-text.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => RateLimitsTextComponent), + multi: true + } + ] +}) +export class RateLimitsTextComponent implements ControlValueAccessor, OnInit { + + private requiredValue: boolean; + get required(): boolean { + return this.requiredValue; + } + @Input() + set required(value: boolean) { + this.requiredValue = coerceBooleanProperty(value); + } + + @Input() + disabled: boolean; + + @Input() + noRateLimitsText = this.translate.instant('tenant-profile.rate-limits.not-set'); + + @Input() + nowrap = false; + + requiredClass = false; + + public rateLimitsText: string; + + private propagateChange = (v: any) => { }; + + constructor(private dialog: MatDialog, + private fb: FormBuilder, + private translate: TranslateService) { + } + + registerOnChange(fn: any): void { + this.propagateChange = fn; + } + + registerOnTouched(fn: any): void { + } + + ngOnInit() { + } + + setDisabledState(isDisabled: boolean): void { + this.disabled = isDisabled; + } + + writeValue(value: Array): void { + this.updateText(value); + } + + private updateText(value: Array) { + this.requiredClass = false; + if (value && value.length) { + this.rateLimitsText = rateLimitsArrayToHtml(this.translate, value); + } else { + if (this.required && !this.disabled) { + this.requiredClass = true; + } else { + this.rateLimitsText = this.noRateLimitsText; + } + } + } + +} diff --git a/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits.component.html b/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits.component.html new file mode 100644 index 0000000000..3f1b698553 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits.component.html @@ -0,0 +1,34 @@ + +
+
+ {{ label | translate }} +
+ +
+
+
+ +
+
diff --git a/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits.component.scss b/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits.component.scss new file mode 100644 index 0000000000..6d45b33b73 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits.component.scss @@ -0,0 +1,31 @@ +/** + * Copyright © 2016-2022 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +:host { + padding: 12px 0 12px 0; + + .fieldset-element { + cursor: pointer; + padding: 0.5em; + border: 1px groove rgba(0, 0, 0, 0.25); + border-radius: 4px; + width: 100%; + + .legend-element { + color: rgba(0, 0, 0, 0.54); + font-size: 12px; + } + } +} diff --git a/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits.component.ts b/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits.component.ts new file mode 100644 index 0000000000..34cbadb755 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits.component.ts @@ -0,0 +1,153 @@ +/// +/// Copyright © 2016-2022 The Thingsboard Authors +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +/// See the License for the specific language governing permissions and +/// limitations under the License. +/// + +import { Component, forwardRef, Input, OnInit } from '@angular/core'; +import { + ControlValueAccessor, + FormBuilder, + FormControl, + FormGroup, + NG_VALIDATORS, + NG_VALUE_ACCESSOR, + Validator +} from '@angular/forms'; +import { MatDialog } from '@angular/material/dialog'; +import { + RateLimitsDetailsDialogComponent, + RateLimitsDetailsDialogData +} from '@home/components/profile/tenant/rate-limits/rate-limits-details-dialog.component'; +import { + addRateLimitTranslationMap, + editRateLimitTranslationMap, + rateLimitLabelTranslationMap, + RateLimitsType, + stringToRateLimitsArray +} from '@shared/models/rate-limits.models'; + +@Component({ + selector: 'tb-rate-limits', + templateUrl: './rate-limits.component.html', + styleUrls: ['./rate-limits.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => RateLimitsComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => RateLimitsComponent), + multi: true, + } + ] +}) +export class RateLimitsComponent implements ControlValueAccessor, OnInit, Validator { + + @Input() + disabled: boolean; + + @Input() + type: RateLimitsType; + + label: string; + + rateLimitsFormGroup: FormGroup; + + private modelValue: string; + + private propagateChange = null; + + constructor(private dialog: MatDialog, + private fb: FormBuilder) { + } + + registerOnChange(fn: any): void { + this.propagateChange = fn; + } + + registerOnTouched(fn: any): void { + } + + ngOnInit() { + this.label = rateLimitLabelTranslationMap.get(this.type); + this.rateLimitsFormGroup = this.fb.group({ + rateLimits: [null, []] + }); + } + + setDisabledState(isDisabled: boolean) { + this.disabled = isDisabled; + if (this.disabled) { + this.rateLimitsFormGroup.disable({emitEvent: false}); + } else { + this.rateLimitsFormGroup.enable({emitEvent: false}); + } + } + + writeValue(value: string) { + this.modelValue = value; + this.updateRateLimitsInfo(); + } + + public validate(c: FormControl) { + return null; + } + + public onClick($event: Event, action: string) { + if ($event) { + $event.stopPropagation(); + } + const title = this.setTitle(action); + this.dialog.open(RateLimitsDetailsDialogComponent, { + disableClose: true, + panelClass: ['tb-dialog', 'tb-fullscreen-dialog'], + data: { + rateLimits: this.modelValue, + title, + readonly: this.disabled + } + }).afterClosed().subscribe((result) => { + if (result) { + this.modelValue = result; + this.updateModel(); + } + }); + } + + private setTitle(action: string): string { + switch (action) { + case 'add': + return addRateLimitTranslationMap.get(this.type); + case 'edit': + return editRateLimitTranslationMap.get(this.type); + } + } + + private updateRateLimitsInfo() { + this.rateLimitsFormGroup.patchValue( + { + rateLimits: stringToRateLimitsArray(this.modelValue) + } + ); + } + + private updateModel() { + this.updateRateLimitsInfo(); + this.propagateChange(this.modelValue); + } + +} diff --git a/ui-ngx/src/app/shared/models/rate-limits.models.ts b/ui-ngx/src/app/shared/models/rate-limits.models.ts new file mode 100644 index 0000000000..8b8eae794a --- /dev/null +++ b/ui-ngx/src/app/shared/models/rate-limits.models.ts @@ -0,0 +1,137 @@ +/// +/// Copyright © 2016-2022 The Thingsboard Authors +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +/// See the License for the specific language governing permissions and +/// limitations under the License. +/// + +import { TranslateService } from '@ngx-translate/core'; + +export interface RateLimits { + value: string; + time: string; +} + +export enum RateLimitsType { + DEVICE_MESSAGES = 'DEVICE_MESSAGES', + DEVICE_TELEMETRY_MESSAGES = 'DEVICE_TELEMETRY_MESSAGES', + DEVICE_TELEMETRY_DATA_POINTS = 'DEVICE_TELEMETRY_DATA_POINTS', + TENANT_MESSAGES = 'TENANT_MESSAGES', + TENANT_TELEMETRY_MESSAGES = 'TENANT_TELEMETRY_MESSAGES', + TENANT_TELEMETRY_DATA_POINTS = 'TENANT_TELEMETRY_DATA_POINTS', + TENANT_SERVER_REST_LIMITS_CONFIGURATION = 'TENANT_SERVER_REST_LIMITS_CONFIGURATION', + CUSTOMER_SERVER_REST_LIMITS_CONFIGURATION = 'CUSTOMER_SERVER_REST_LIMITS_CONFIGURATION', + WS_UPDATE_PER_SESSION_RATE_LIMIT = 'WS_UPDATE_PER_SESSION_RATE_LIMIT', + CASSANDRA_QUERY_TENANT_RATE_LIMITS_CONFIGURATION = 'CASSANDRA_QUERY_TENANT_RATE_LIMITS_CONFIGURATION', +} + +export const rateLimitLabelTranslationMap = new Map( + [ + [RateLimitsType.TENANT_MESSAGES, 'tenant-profile.rate-limits.transport-tenant-msg'], + [RateLimitsType.TENANT_TELEMETRY_MESSAGES, 'tenant-profile.rate-limits.transport-tenant-telemetry-msg'], + [RateLimitsType.TENANT_TELEMETRY_DATA_POINTS, 'tenant-profile.rate-limits.transport-tenant-telemetry-data-points'], + [RateLimitsType.DEVICE_MESSAGES, 'tenant-profile.rate-limits.transport-device-msg'], + [RateLimitsType.DEVICE_TELEMETRY_MESSAGES, 'tenant-profile.rate-limits.transport-device-telemetry-msg'], + [RateLimitsType.DEVICE_TELEMETRY_DATA_POINTS, 'tenant-profile.rate-limits.transport-device-telemetry-data-points'], + [RateLimitsType.TENANT_SERVER_REST_LIMITS_CONFIGURATION, 'tenant-profile.transport-tenant-msg-rate-limit'], + [RateLimitsType.CUSTOMER_SERVER_REST_LIMITS_CONFIGURATION, 'tenant-profile.customer-rest-limits'], + [RateLimitsType.WS_UPDATE_PER_SESSION_RATE_LIMIT, 'tenant-profile.ws-limit-updates-per-session'], + [RateLimitsType.CASSANDRA_QUERY_TENANT_RATE_LIMITS_CONFIGURATION, 'tenant-profile.cassandra-tenant-limits-configuration'], + ] +); + +export const editRateLimitTranslationMap = new Map( + [ + [RateLimitsType.TENANT_MESSAGES, 'tenant-profile.rate-limits.edit-transport-tenant-msg-title'], + [RateLimitsType.TENANT_TELEMETRY_MESSAGES, 'tenant-profile.rate-limits.edit-transport-tenant-telemetry-msg-title'], + [RateLimitsType.TENANT_TELEMETRY_DATA_POINTS, 'tenant-profile.rate-limits.edit-transport-tenant-telemetry-data-points-title'], + [RateLimitsType.DEVICE_MESSAGES, 'tenant-profile.rate-limits.edit-transport-device-msg-title'], + [RateLimitsType.DEVICE_TELEMETRY_MESSAGES, 'tenant-profile.rate-limits.edit-transport-device-telemetry-msg-title'], + [RateLimitsType.DEVICE_TELEMETRY_DATA_POINTS, 'tenant-profile.rate-limits.edit-transport-device-telemetry-data-points-title'], + [RateLimitsType.TENANT_SERVER_REST_LIMITS_CONFIGURATION, 'tenant-profile.rate-limits.edit-transport-device-telemetry-data-points-title'], + [RateLimitsType.CUSTOMER_SERVER_REST_LIMITS_CONFIGURATION, 'tenant-profile.rate-limits.edit-transport-device-telemetry-data-points-title'], + [RateLimitsType.WS_UPDATE_PER_SESSION_RATE_LIMIT, 'tenant-profile.rate-limits.edit-transport-device-telemetry-data-points-title'], + [RateLimitsType.CASSANDRA_QUERY_TENANT_RATE_LIMITS_CONFIGURATION, 'tenant-profile.rate-limits.edit-transport-device-telemetry-data-points-title'], + ] +); + +export const addRateLimitTranslationMap = new Map( + [ + [RateLimitsType.TENANT_MESSAGES, 'tenant-profile.rate-limits.add-transport-tenant-msg-title'], + [RateLimitsType.TENANT_TELEMETRY_MESSAGES, 'tenant-profile.rate-limits.add-transport-tenant-telemetry-msg-title'], + [RateLimitsType.TENANT_TELEMETRY_DATA_POINTS, 'tenant-profile.rate-limits.add-transport-tenant-telemetry-data-points-title'], + [RateLimitsType.DEVICE_MESSAGES, 'tenant-profile.rate-limits.add-transport-device-msg-title'], + [RateLimitsType.DEVICE_TELEMETRY_MESSAGES, 'tenant-profile.rate-limits.add-transport-device-telemetry-msg-title'], + [RateLimitsType.DEVICE_TELEMETRY_DATA_POINTS, 'tenant-profile.rate-limits.add-transport-device-telemetry-data-points-title'], + [RateLimitsType.TENANT_SERVER_REST_LIMITS_CONFIGURATION, 'tenant-profile.rate-limits.add-transport-device-telemetry-data-points-title'], + [RateLimitsType.CUSTOMER_SERVER_REST_LIMITS_CONFIGURATION, 'tenant-profile.rate-limits.add-transport-device-telemetry-data-points-title'], + [RateLimitsType.WS_UPDATE_PER_SESSION_RATE_LIMIT, 'tenant-profile.rate-limits.add-transport-device-telemetry-data-points-title'], + [RateLimitsType.CASSANDRA_QUERY_TENANT_RATE_LIMITS_CONFIGURATION, 'tenant-profile.rate-limits.add-transport-device-telemetry-data-points-title'], + ] +); + +export function stringToRateLimitsArray(rateLimits: string): Array { + const result: Array = []; + if (rateLimits?.length > 0) { + let rateLimitsArrays = rateLimits.split(','); + for (let i = 0; i < rateLimitsArrays.length; i++) { + let valueTime = rateLimitsArrays[i].split(':'); + let value = valueTime[0]; + let time = valueTime[1]; + const rateLimitControl = { + value, + time + } + result.push(rateLimitControl); + } + } + return result; +} + +export function rateLimitsArrayToString(rateLimits: Array): string { + let result = ''; + for (let i = 0; i < rateLimits.length; i++) { + result = result.concat(rateLimits[i].value, ':', rateLimits[i].time); + if ((rateLimits.length > 1) && (i !== rateLimits.length - 1)) { + result = result.concat(','); + } + } + return result; +} + +export function rateLimitsArrayToHtml(translate: TranslateService, rateLimitsArray: Array): string { + const rateLimitsHtml = rateLimitsArray.map((rateLimits, index) => { + const isLast: boolean = index === rateLimitsArray.length-1; + return rateLimitsToHtml(translate, rateLimits, isLast); + }); + let result: string; + if (rateLimitsHtml.length > 1) { + const butLessThanText = translate.instant('tenant-profile.rate-limits.but-less-than'); + result = rateLimitsHtml.join(' ' + butLessThanText + ' '); + } else { + result = rateLimitsHtml[0]; + } + return result; +} + +function rateLimitsToHtml(translate: TranslateService, rateLimit: RateLimits, isLast: boolean): string { + const value = rateLimit.value; + const time = rateLimit.time; + const operation = translate.instant('tenant-profile.rate-limits.messages-per'); + const seconds = translate.instant('tenant-profile.rate-limits.sec'); + const comma = isLast ? '' : ','; + const result = `${value} + ${operation} + ${time} + ${seconds}${comma}
`; + return result; +} diff --git a/ui-ngx/src/assets/locale/locale.constant-en_US.json b/ui-ngx/src/assets/locale/locale.constant-en_US.json index 6e76448847..4e83984480 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -3187,7 +3187,41 @@ "ws-limit-max-subscriptions-per-customer": "Subscriptions per customer maximum number", "ws-limit-max-subscriptions-per-regular-user": "Subscriptions per regular user maximum number", "ws-limit-max-subscriptions-per-public-user": "Subscriptions per public user maximum number", - "ws-limit-updates-per-session": "WS updates per session" + "ws-limit-updates-per-session": "WS updates per session", + "rate-limits": { + "add-limit": "Add limit", + "add-transport-tenant-msg-title": "Add transport tenant messages rate limit", + "add-transport-tenant-telemetry-msg-title": "Add transport tenant telemetry messages rate limit", + "add-transport-tenant-telemetry-data-points-title": "Add transport tenant telemetry data points rate limit", + "add-transport-device-msg-title": "Add transport device messages rate limit", + "add-transport-device-telemetry-msg-title": "Add transport device telemetry messages rate limit", + "add-transport-device-telemetry-data-points-title": "Add transport device telemetry data points rate limit", + "advanced-settings": "Advanced settings", + "edit-limit": "Edit limit", + "but-less-than": "but less than", + "edit-transport-tenant-msg-title": "Edit transport tenant messages rate limit", + "edit-transport-tenant-telemetry-msg-title": "Edit transport tenant telemetry messages rate limit", + "edit-transport-tenant-telemetry-data-points-title": "Edit transport tenant telemetry data points rate limit", + "edit-transport-device-msg-title": "Edit transport device messages rate limit", + "edit-transport-device-telemetry-msg-title": "Edit transport device telemetry messages rate limit", + "edit-transport-device-telemetry-data-points-title": "Edit transport device telemetry data points rate limit", + "messages-per": "messages per", + "not-set": "Not set", + "number-of-messages": "Number of messages", + "number-of-messages-required": "Number of messages is required.", + "preview": "Preview", + "per-seconds": "Per seconds", + "per-seconds-required": "Time rate is required.", + "rate-limits": "Rate limits", + "remove-limit": "Remove rate limit", + "transport-tenant-msg": "Transport tenant messages", + "transport-tenant-telemetry-msg": "Transport tenant telemetry messages", + "transport-tenant-telemetry-data-points": "Transport tenant telemetry data points", + "transport-device-msg": "Transport device messages", + "transport-device-telemetry-msg": "Transport device telemetry messages", + "transport-device-telemetry-data-points": "Transport device telemetry data points", + "sec": "sec" + } }, "timeinterval": { "seconds-interval": "{ seconds, plural, 1 {1 second} other {# seconds} }", From 97e46e18cbd1b14c315981e2d01ca353c21838a1 Mon Sep 17 00:00:00 2001 From: Artem Babak Date: Wed, 6 Jul 2022 14:47:31 +0300 Subject: [PATCH 002/108] Rate limits translations updated --- .../app/shared/models/rate-limits.models.ts | 16 ++++----- .../assets/locale/locale.constant-en_US.json | 34 ++++++++++++------- 2 files changed, 29 insertions(+), 21 deletions(-) diff --git a/ui-ngx/src/app/shared/models/rate-limits.models.ts b/ui-ngx/src/app/shared/models/rate-limits.models.ts index 8b8eae794a..e6b4218773 100644 --- a/ui-ngx/src/app/shared/models/rate-limits.models.ts +++ b/ui-ngx/src/app/shared/models/rate-limits.models.ts @@ -57,10 +57,10 @@ export const editRateLimitTranslationMap = new Map( [RateLimitsType.DEVICE_MESSAGES, 'tenant-profile.rate-limits.edit-transport-device-msg-title'], [RateLimitsType.DEVICE_TELEMETRY_MESSAGES, 'tenant-profile.rate-limits.edit-transport-device-telemetry-msg-title'], [RateLimitsType.DEVICE_TELEMETRY_DATA_POINTS, 'tenant-profile.rate-limits.edit-transport-device-telemetry-data-points-title'], - [RateLimitsType.TENANT_SERVER_REST_LIMITS_CONFIGURATION, 'tenant-profile.rate-limits.edit-transport-device-telemetry-data-points-title'], - [RateLimitsType.CUSTOMER_SERVER_REST_LIMITS_CONFIGURATION, 'tenant-profile.rate-limits.edit-transport-device-telemetry-data-points-title'], - [RateLimitsType.WS_UPDATE_PER_SESSION_RATE_LIMIT, 'tenant-profile.rate-limits.edit-transport-device-telemetry-data-points-title'], - [RateLimitsType.CASSANDRA_QUERY_TENANT_RATE_LIMITS_CONFIGURATION, 'tenant-profile.rate-limits.edit-transport-device-telemetry-data-points-title'], + [RateLimitsType.TENANT_SERVER_REST_LIMITS_CONFIGURATION, 'tenant-profile.rate-limits.edit-transport-tenant-msg-rate-limit-title'], + [RateLimitsType.CUSTOMER_SERVER_REST_LIMITS_CONFIGURATION, 'tenant-profile.rate-limits.edit-customer-rest-limits-title'], + [RateLimitsType.WS_UPDATE_PER_SESSION_RATE_LIMIT, 'tenant-profile.rate-limits.edit-ws-limit-updates-per-session-title'], + [RateLimitsType.CASSANDRA_QUERY_TENANT_RATE_LIMITS_CONFIGURATION, 'tenant-profile.rate-limits.edit-cassandra-tenant-limits-configuration-title'], ] ); @@ -72,10 +72,10 @@ export const addRateLimitTranslationMap = new Map( [RateLimitsType.DEVICE_MESSAGES, 'tenant-profile.rate-limits.add-transport-device-msg-title'], [RateLimitsType.DEVICE_TELEMETRY_MESSAGES, 'tenant-profile.rate-limits.add-transport-device-telemetry-msg-title'], [RateLimitsType.DEVICE_TELEMETRY_DATA_POINTS, 'tenant-profile.rate-limits.add-transport-device-telemetry-data-points-title'], - [RateLimitsType.TENANT_SERVER_REST_LIMITS_CONFIGURATION, 'tenant-profile.rate-limits.add-transport-device-telemetry-data-points-title'], - [RateLimitsType.CUSTOMER_SERVER_REST_LIMITS_CONFIGURATION, 'tenant-profile.rate-limits.add-transport-device-telemetry-data-points-title'], - [RateLimitsType.WS_UPDATE_PER_SESSION_RATE_LIMIT, 'tenant-profile.rate-limits.add-transport-device-telemetry-data-points-title'], - [RateLimitsType.CASSANDRA_QUERY_TENANT_RATE_LIMITS_CONFIGURATION, 'tenant-profile.rate-limits.add-transport-device-telemetry-data-points-title'], + [RateLimitsType.TENANT_SERVER_REST_LIMITS_CONFIGURATION, 'tenant-profile.rate-limits.add-transport-tenant-msg-rate-limit-title'], + [RateLimitsType.CUSTOMER_SERVER_REST_LIMITS_CONFIGURATION, 'tenant-profile.rate-limits.add-customer-rest-limits-title'], + [RateLimitsType.WS_UPDATE_PER_SESSION_RATE_LIMIT, 'tenant-profile.rate-limits.add-ws-limit-updates-per-session-title'], + [RateLimitsType.CASSANDRA_QUERY_TENANT_RATE_LIMITS_CONFIGURATION, 'tenant-profile.rate-limits.add-cassandra-tenant-limits-configuration-title'], ] ); diff --git a/ui-ngx/src/assets/locale/locale.constant-en_US.json b/ui-ngx/src/assets/locale/locale.constant-en_US.json index 4e83984480..8cd65a139e 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -3190,21 +3190,29 @@ "ws-limit-updates-per-session": "WS updates per session", "rate-limits": { "add-limit": "Add limit", - "add-transport-tenant-msg-title": "Add transport tenant messages rate limit", - "add-transport-tenant-telemetry-msg-title": "Add transport tenant telemetry messages rate limit", - "add-transport-tenant-telemetry-data-points-title": "Add transport tenant telemetry data points rate limit", - "add-transport-device-msg-title": "Add transport device messages rate limit", - "add-transport-device-telemetry-msg-title": "Add transport device telemetry messages rate limit", - "add-transport-device-telemetry-data-points-title": "Add transport device telemetry data points rate limit", + "add-transport-tenant-msg-title": "Add transport tenant messages rate limits", + "add-transport-tenant-telemetry-msg-title": "Add transport tenant telemetry messages rate limits", + "add-transport-tenant-telemetry-data-points-title": "Add transport tenant telemetry data points rate limits", + "add-transport-device-msg-title": "Add transport device messages rate limits", + "add-transport-device-telemetry-msg-title": "Add transport device telemetry messages rate limits", + "add-transport-device-telemetry-data-points-title": "Add transport device telemetry data points rate limits", + "add-transport-tenant-msg-rate-limit-title": "Add transport tenant messages rate limits", + "add-customer-rest-limits-title": "Add REST requests for customer rate limits", + "add-ws-limit-updates-per-session-title": "Add WS updates per session rate limits", + "add-cassandra-tenant-limits-configuration-title": "Add Cassandra query for tenant rate limits", "advanced-settings": "Advanced settings", "edit-limit": "Edit limit", "but-less-than": "but less than", - "edit-transport-tenant-msg-title": "Edit transport tenant messages rate limit", - "edit-transport-tenant-telemetry-msg-title": "Edit transport tenant telemetry messages rate limit", - "edit-transport-tenant-telemetry-data-points-title": "Edit transport tenant telemetry data points rate limit", - "edit-transport-device-msg-title": "Edit transport device messages rate limit", - "edit-transport-device-telemetry-msg-title": "Edit transport device telemetry messages rate limit", - "edit-transport-device-telemetry-data-points-title": "Edit transport device telemetry data points rate limit", + "edit-transport-tenant-msg-title": "Edit transport tenant messages rate limits", + "edit-transport-tenant-telemetry-msg-title": "Edit transport tenant telemetry messages rate limits", + "edit-transport-tenant-telemetry-data-points-title": "Edit transport tenant telemetry data points rate limits", + "edit-transport-device-msg-title": "Edit transport device messages rate limits", + "edit-transport-device-telemetry-msg-title": "Edit transport device telemetry messages rate limits", + "edit-transport-device-telemetry-data-points-title": "Edit transport device telemetry data points rate limits", + "edit-transport-tenant-msg-rate-limit-title": "Edit transport tenant messages rate limits", + "edit-customer-rest-limits-title": "Edit REST requests for customer rate limits", + "edit-ws-limit-updates-per-session-title": "Edit WS updates per session rate limits", + "edit-cassandra-tenant-limits-configuration-title": "Edit Cassandra query for tenant rate limits", "messages-per": "messages per", "not-set": "Not set", "number-of-messages": "Number of messages", @@ -3213,7 +3221,7 @@ "per-seconds": "Per seconds", "per-seconds-required": "Time rate is required.", "rate-limits": "Rate limits", - "remove-limit": "Remove rate limit", + "remove-limit": "Remove limit", "transport-tenant-msg": "Transport tenant messages", "transport-tenant-telemetry-msg": "Transport tenant telemetry messages", "transport-tenant-telemetry-data-points": "Transport tenant telemetry data points", From 5a43971fe8e43744b8cb521eb7635a0feb27bdd3 Mon Sep 17 00:00:00 2001 From: devaskim Date: Mon, 11 Jul 2022 17:09:46 +0500 Subject: [PATCH 003/108] Add 'Process no-data' option to widget's type parameters. --- .../widget/widget-component.service.ts | 3 +++ .../home/components/widget/widget.component.ts | 18 +++++++++--------- ui-ngx/src/app/shared/models/widget.models.ts | 1 + 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/widget/widget-component.service.ts b/ui-ngx/src/app/modules/home/components/widget/widget-component.service.ts index de88b73e3b..5b608d71ba 100644 --- a/ui-ngx/src/app/modules/home/components/widget/widget-component.service.ts +++ b/ui-ngx/src/app/modules/home/components/widget/widget-component.service.ts @@ -502,6 +502,9 @@ export class WidgetComponentService { if (isUndefined(result.typeParameters.stateData)) { result.typeParameters.stateData = false; } + if (isUndefined(result.typeParameters.processNoDataByWidget)) { + result.typeParameters.processNoDataByWidget = false; + } if (isFunction(widgetTypeInstance.actionSources)) { result.actionSources = widgetTypeInstance.actionSources(); } else { diff --git a/ui-ngx/src/app/modules/home/components/widget/widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/widget.component.ts index 0506feb02d..1552d1356b 100644 --- a/ui-ngx/src/app/modules/home/components/widget/widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/widget.component.ts @@ -399,17 +399,17 @@ export class WidgetComponent extends PageComponent implements OnInit, AfterViewI } private displayWidgetInstance(): boolean { - if (this.widget.type !== widgetType.static) { - for (const id of Object.keys(this.widgetContext.subscriptions)) { - const subscription = this.widgetContext.subscriptions[id]; - if (subscription.isDataResolved()) { - return true; - } - } - return false; - } else { + if (this.widget.type === widgetType.static || this.typeParameters?.processNoDataByWidget) { return true; } + + for (const id of Object.keys(this.widgetContext.subscriptions)) { + const subscription = this.widgetContext.subscriptions[id]; + if (subscription.isDataResolved()) { + return true; + } + } + return false; } private onDestroy() { diff --git a/ui-ngx/src/app/shared/models/widget.models.ts b/ui-ngx/src/app/shared/models/widget.models.ts index 703cffcaee..688e1b05cd 100644 --- a/ui-ngx/src/app/shared/models/widget.models.ts +++ b/ui-ngx/src/app/shared/models/widget.models.ts @@ -159,6 +159,7 @@ export interface WidgetTypeParameters { singleEntity?: boolean; warnOnPageDataOverflow?: boolean; ignoreDataUpdateOnIntervalTick?: boolean; + processNoDataByWidget?: boolean; } export interface WidgetControllerDescriptor { From c7daaa571e3d7f497ef6b84feb4bfd56153fee99 Mon Sep 17 00:00:00 2001 From: thingsboard Date: Mon, 11 Jul 2022 17:49:33 +0300 Subject: [PATCH 004/108] replace StringUtils usages with in-repository implementation --- .../actors/ruleChain/DefaultTbContext.java | 2 +- ...tomOAuth2AuthorizationRequestResolver.java | 2 +- .../config/RateLimitProcessingFilter.java | 2 +- .../controller/AbstractRpcController.java | 2 +- .../server/controller/AlarmController.java | 2 +- .../server/controller/AuditLogController.java | 2 +- .../server/controller/BaseController.java | 2 +- .../ComponentDescriptorController.java | 2 +- .../controller/DeviceProfileController.java | 2 +- .../controller/TelemetryController.java | 2 +- .../controller/plugin/TbWebSocketHandler.java | 2 +- .../service/action/EntityActionService.java | 8 +-- .../apiusage/DefaultRateLimitService.java | 2 +- .../DefaultTbApiUsageStateService.java | 2 +- .../device/ClaimDevicesServiceImpl.java | 2 +- .../device/DeviceBulkImportService.java | 2 +- .../device/DeviceProvisionServiceImpl.java | 2 +- .../fetch/AdminSettingsEdgeEventFetcher.java | 2 +- .../rpc/processor/DeviceEdgeProcessor.java | 2 +- .../DefaultTbEntityViewService.java | 2 +- .../service/install/DatabaseHelper.java | 2 +- .../service/install/InstallScripts.java | 2 +- .../install/SqlTsDatabaseUpgradeService.java | 2 +- .../TimescaleTsDatabaseUpgradeService.java | 2 +- .../CassandraTsLatestToSqlMigrateService.java | 2 +- .../update/DefaultDataUpdateService.java | 2 +- .../install/update/RateLimitsUpdater.java | 2 +- .../service/mail/DefaultMailService.java | 2 +- .../resource/DefaultTbResourceService.java | 2 +- .../script/RuleNodeJsScriptEngine.java | 2 +- .../jwt/RefreshTokenProcessingFilter.java | 2 +- .../extractor/JwtHeaderTokenExtractor.java | 2 +- .../jwt/extractor/JwtQueryTokenExtractor.java | 2 +- .../auth/mfa/DefaultTwoFactorAuthService.java | 2 +- .../oauth2/AbstractOAuth2ClientMapper.java | 2 +- .../auth/oauth2/AppleOAuth2ClientMapper.java | 2 +- .../auth/oauth2/BasicMapperUtils.java | 2 +- .../auth/oauth2/CustomOAuth2ClientMapper.java | 2 +- .../auth/rest/RestLoginProcessingFilter.java | 2 +- .../rest/RestPublicLoginProcessingFilter.java | 2 +- .../security/model/token/JwtTokenFactory.java | 2 +- .../model/token/OAuth2AppTokenFactory.java | 2 +- .../system/DefaultSystemSecurityService.java | 2 +- .../server/service/sms/aws/AwsSmsSender.java | 2 +- .../service/sms/smpp/SmppSmsSender.java | 2 +- .../service/sms/twilio/TwilioSmsSender.java | 2 +- .../state/DefaultDeviceStateService.java | 2 +- .../csv/AbstractBulkImportService.java | 2 +- .../DefaultTelemetryWebSocketService.java | 2 +- .../server/controller/AbstractWebTest.java | 2 +- .../server/controller/TwoFactorAuthTest.java | 2 +- .../service/sms/smpp/SmppSmsSenderTest.java | 2 +- ...tractCoapServerSideRpcIntegrationTest.java | 2 +- .../mqtt/AbstractMqttIntegrationTest.java | 2 +- ...tractMqttServerSideRpcIntegrationTest.java | 2 +- .../cache/TBRedisClusterConfiguration.java | 2 +- .../TbCoapDtlsCertificateVerifier.java | 2 +- .../dao/cassandra/CassandraDriverOptions.java | 2 +- common/data/pom.xml | 10 ++++ .../server/common/data/StringUtils.java | 50 +++++++++++++++++++ .../SnmpDeviceTransportConfiguration.java | 2 +- .../common/data/sync/vc/EntityLoadError.java | 2 +- .../data/transport/snmp/SnmpMapping.java | 2 +- .../thingsboard/server/common/msg/TbMsg.java | 2 +- .../DefaultTbServiceInfoProvider.java | 2 +- .../kafka/TbKafkaConsumerStatsService.java | 2 +- .../queue/kafka/TbKafkaProducerTemplate.java | 2 +- common/stats/pom.xml | 4 ++ .../common/stats/DefaultStatsFactory.java | 2 +- .../coap/adaptors/CoapAdaptorUtils.java | 2 +- .../coap/adaptors/JsonCoapAdaptor.java | 2 +- .../coap/adaptors/ProtoCoapAdaptor.java | 2 +- .../transport/http/DeviceApiController.java | 2 +- .../lwm2m/utils/LwM2MTransportUtil.java | 2 +- .../lwm2m/utils/LwM2mValueConverterImpl.java | 2 +- .../mqtt/MqttSslHandlerProvider.java | 2 +- .../transport/mqtt/MqttTransportHandler.java | 4 +- .../mqtt/adaptors/JsonMqttAdaptor.java | 2 +- .../mqtt/adaptors/ProtoMqttAdaptor.java | 2 +- .../mqtt/session/GatewaySessionHandler.java | 2 +- .../transport/adaptor/JsonConverter.java | 2 +- .../transport/adaptor/ProtoConverter.java | 2 +- .../DefaultTransportRateLimitService.java | 2 +- .../sync/vc/DefaultGitRepositoryService.java | 2 +- .../server/service/sync/vc/GitRepository.java | 2 +- .../server/dao/audit/AuditLogServiceImpl.java | 2 +- .../audit/sink/ElasticsearchAuditLogSink.java | 2 +- .../server/dao/event/BaseEventService.java | 2 +- .../dao/model/sql/AbstractAlarmEntity.java | 2 +- .../server/dao/model/sql/DashboardEntity.java | 2 +- .../dao/model/sql/DashboardInfoEntity.java | 2 +- .../model/sql/OAuth2RegistrationEntity.java | 2 +- .../timescale/ts/TimescaleTsKvEntity.java | 2 +- .../server/dao/oauth2/OAuth2ServiceImpl.java | 2 +- .../dao/relation/BaseRelationService.java | 2 +- .../server/dao/service/DataValidator.java | 2 +- .../validator/AdminSettingsDataValidator.java | 2 +- .../service/validator/AlarmDataValidator.java | 2 +- .../service/validator/AssetDataValidator.java | 2 +- ...ientRegistrationTemplateDataValidator.java | 2 +- .../ComponentDescriptorDataValidator.java | 2 +- .../validator/CustomerDataValidator.java | 2 +- .../validator/DashboardDataValidator.java | 2 +- .../validator/DeviceDataValidator.java | 2 +- .../service/validator/EdgeDataValidator.java | 2 +- .../validator/EntityViewDataValidator.java | 2 +- .../service/validator/EventDataValidator.java | 2 +- .../validator/ResourceDataValidator.java | 2 +- .../validator/RuleChainDataValidator.java | 2 +- .../validator/TenantDataValidator.java | 2 +- .../validator/TenantProfileDataValidator.java | 2 +- .../UserCredentialsDataValidator.java | 2 +- .../service/validator/UserDataValidator.java | 2 +- .../validator/WidgetTypeDataValidator.java | 2 +- .../validator/WidgetsBundleDataValidator.java | 2 +- .../server/dao/sql/device/JpaDeviceDao.java | 2 +- .../dao/sql/device/JpaDeviceProfileDao.java | 2 +- .../dao/sql/edge/JpaBaseEdgeEventDao.java | 2 +- .../server/dao/sql/event/JpaBaseEventDao.java | 2 +- .../dao/sql/query/AlarmDataAdapter.java | 2 +- .../query/DefaultAlarmQueryRepository.java | 2 +- .../query/DefaultEntityQueryRepository.java | 2 +- .../dao/sql/query/EntityKeyMapping.java | 2 +- .../AbstractCassandraBaseTimeseriesDao.java | 2 +- .../dao/timeseries/BaseTimeseriesService.java | 2 +- .../dao/service/BaseEntityServiceTest.java | 2 +- .../thingsboard/rest/client/RestClient.java | 2 +- .../rule/engine/api/util/TbNodeUtils.java | 2 +- .../rule/engine/aws/sqs/TbSqsNode.java | 2 +- .../credentials/CertPemCredentials.java | 2 +- .../rule/engine/debug/TbMsgGeneratorNode.java | 2 +- .../rule/engine/kafka/TbKafkaNode.java | 2 +- .../rule/engine/mail/TbMsgToEmailNode.java | 2 +- .../rule/engine/mail/TbSendEmailNode.java | 2 +- .../engine/metadata/TbGetTelemetryNode.java | 2 +- .../rule/engine/mqtt/TbMqttNode.java | 2 +- .../engine/mqtt/azure/TbAzureIotHubNode.java | 2 +- .../rule/engine/profile/AlarmState.java | 2 +- .../rule/engine/profile/DeviceState.java | 2 +- .../rule/engine/rabbitmq/TbRabbitMqNode.java | 2 +- .../rule/engine/rest/TbHttpClient.java | 2 +- .../rule/engine/rpc/TbSendRPCReplyNode.java | 2 +- .../rule/engine/rpc/TbSendRPCRequestNode.java | 2 +- .../rpc/TbSendRpcReplyNodeConfiguration.java | 2 +- .../engine/telemetry/TbMsgAttributesNode.java | 2 +- .../engine/telemetry/TbMsgTimeseriesNode.java | 2 +- .../tools/migrator/DictionaryParser.java | 2 +- .../client/tools/migrator/PgCaMigrator.java | 2 +- .../tools/migrator/RelatedEntitiesParser.java | 2 +- 149 files changed, 212 insertions(+), 152 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/actors/ruleChain/DefaultTbContext.java b/application/src/main/java/org/thingsboard/server/actors/ruleChain/DefaultTbContext.java index 3538800d38..b4a7fef8ed 100644 --- a/application/src/main/java/org/thingsboard/server/actors/ruleChain/DefaultTbContext.java +++ b/application/src/main/java/org/thingsboard/server/actors/ruleChain/DefaultTbContext.java @@ -19,7 +19,7 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import io.netty.channel.EventLoopGroup; import lombok.extern.slf4j.Slf4j; -import org.springframework.util.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.common.util.ListeningExecutor; import org.thingsboard.rule.engine.api.MailService; import org.thingsboard.rule.engine.api.RuleEngineAlarmService; diff --git a/application/src/main/java/org/thingsboard/server/config/CustomOAuth2AuthorizationRequestResolver.java b/application/src/main/java/org/thingsboard/server/config/CustomOAuth2AuthorizationRequestResolver.java index bbeed33449..bc91eb9908 100644 --- a/application/src/main/java/org/thingsboard/server/config/CustomOAuth2AuthorizationRequestResolver.java +++ b/application/src/main/java/org/thingsboard/server/config/CustomOAuth2AuthorizationRequestResolver.java @@ -33,7 +33,7 @@ import org.springframework.security.web.util.UrlUtils; import org.springframework.security.web.util.matcher.AntPathRequestMatcher; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; -import org.springframework.util.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.springframework.web.util.UriComponents; import org.springframework.web.util.UriComponentsBuilder; import org.thingsboard.server.dao.oauth2.OAuth2Configuration; diff --git a/application/src/main/java/org/thingsboard/server/config/RateLimitProcessingFilter.java b/application/src/main/java/org/thingsboard/server/config/RateLimitProcessingFilter.java index 86675a79a8..232419a57e 100644 --- a/application/src/main/java/org/thingsboard/server/config/RateLimitProcessingFilter.java +++ b/application/src/main/java/org/thingsboard/server/config/RateLimitProcessingFilter.java @@ -16,7 +16,7 @@ package org.thingsboard.server.config; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Lazy; import org.springframework.security.authentication.BadCredentialsException; diff --git a/application/src/main/java/org/thingsboard/server/controller/AbstractRpcController.java b/application/src/main/java/org/thingsboard/server/controller/AbstractRpcController.java index 965975c0ee..e5a217893e 100644 --- a/application/src/main/java/org/thingsboard/server/controller/AbstractRpcController.java +++ b/application/src/main/java/org/thingsboard/server/controller/AbstractRpcController.java @@ -22,10 +22,10 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; -import org.springframework.util.StringUtils; import org.springframework.web.context.request.async.DeferredResult; import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.server.common.data.DataConstants; +import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.data.audit.ActionType; import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; import org.thingsboard.server.common.data.exception.ThingsboardException; diff --git a/application/src/main/java/org/thingsboard/server/controller/AlarmController.java b/application/src/main/java/org/thingsboard/server/controller/AlarmController.java index 5003aac526..50a69c5b17 100644 --- a/application/src/main/java/org/thingsboard/server/controller/AlarmController.java +++ b/application/src/main/java/org/thingsboard/server/controller/AlarmController.java @@ -18,7 +18,7 @@ package org.thingsboard.server.controller; import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiParam; import lombok.RequiredArgsConstructor; -import org.apache.commons.lang3.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.security.access.prepost.PreAuthorize; diff --git a/application/src/main/java/org/thingsboard/server/controller/AuditLogController.java b/application/src/main/java/org/thingsboard/server/controller/AuditLogController.java index db78b87f70..dbe948c26c 100644 --- a/application/src/main/java/org/thingsboard/server/controller/AuditLogController.java +++ b/application/src/main/java/org/thingsboard/server/controller/AuditLogController.java @@ -17,7 +17,7 @@ package org.thingsboard.server.controller; import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiParam; -import org.apache.commons.lang3.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.springframework.http.MediaType; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.PathVariable; diff --git a/application/src/main/java/org/thingsboard/server/controller/BaseController.java b/application/src/main/java/org/thingsboard/server/controller/BaseController.java index 7d2d2cd255..5e1bc74992 100644 --- a/application/src/main/java/org/thingsboard/server/controller/BaseController.java +++ b/application/src/main/java/org/thingsboard/server/controller/BaseController.java @@ -23,7 +23,7 @@ import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.MoreExecutors; import lombok.Getter; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.support.DefaultMessageSourceResolvable; diff --git a/application/src/main/java/org/thingsboard/server/controller/ComponentDescriptorController.java b/application/src/main/java/org/thingsboard/server/controller/ComponentDescriptorController.java index b8e5da25de..069e8eb9eb 100644 --- a/application/src/main/java/org/thingsboard/server/controller/ComponentDescriptorController.java +++ b/application/src/main/java/org/thingsboard/server/controller/ComponentDescriptorController.java @@ -17,7 +17,7 @@ package org.thingsboard.server.controller; import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiParam; -import org.apache.commons.lang3.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; diff --git a/application/src/main/java/org/thingsboard/server/controller/DeviceProfileController.java b/application/src/main/java/org/thingsboard/server/controller/DeviceProfileController.java index 08568a28ce..150e013f6d 100644 --- a/application/src/main/java/org/thingsboard/server/controller/DeviceProfileController.java +++ b/application/src/main/java/org/thingsboard/server/controller/DeviceProfileController.java @@ -19,7 +19,7 @@ import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiParam; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.security.access.prepost.PreAuthorize; diff --git a/application/src/main/java/org/thingsboard/server/controller/TelemetryController.java b/application/src/main/java/org/thingsboard/server/controller/TelemetryController.java index b9c929f909..aa9717dd39 100644 --- a/application/src/main/java/org/thingsboard/server/controller/TelemetryController.java +++ b/application/src/main/java/org/thingsboard/server/controller/TelemetryController.java @@ -35,7 +35,7 @@ import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.util.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; diff --git a/application/src/main/java/org/thingsboard/server/controller/plugin/TbWebSocketHandler.java b/application/src/main/java/org/thingsboard/server/controller/plugin/TbWebSocketHandler.java index 578bfa5662..09fab07faa 100644 --- a/application/src/main/java/org/thingsboard/server/controller/plugin/TbWebSocketHandler.java +++ b/application/src/main/java/org/thingsboard/server/controller/plugin/TbWebSocketHandler.java @@ -16,7 +16,7 @@ package org.thingsboard.server.controller.plugin; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.springframework.beans.factory.BeanCreationNotAllowedException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; diff --git a/application/src/main/java/org/thingsboard/server/service/action/EntityActionService.java b/application/src/main/java/org/thingsboard/server/service/action/EntityActionService.java index 39064c210c..2f18fb56c8 100644 --- a/application/src/main/java/org/thingsboard/server/service/action/EntityActionService.java +++ b/application/src/main/java/org/thingsboard/server/service/action/EntityActionService.java @@ -20,14 +20,10 @@ import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; + import org.springframework.stereotype.Service; import org.thingsboard.server.cluster.TbClusterService; -import org.thingsboard.server.common.data.DataConstants; -import org.thingsboard.server.common.data.EntityType; -import org.thingsboard.server.common.data.HasName; -import org.thingsboard.server.common.data.HasTenantId; -import org.thingsboard.server.common.data.User; +import org.thingsboard.server.common.data.*; import org.thingsboard.server.common.data.audit.ActionType; import org.thingsboard.server.common.data.edge.EdgeEventActionType; import org.thingsboard.server.common.data.id.CustomerId; diff --git a/application/src/main/java/org/thingsboard/server/service/apiusage/DefaultRateLimitService.java b/application/src/main/java/org/thingsboard/server/service/apiusage/DefaultRateLimitService.java index 55b23a99cc..01dade4d71 100644 --- a/application/src/main/java/org/thingsboard/server/service/apiusage/DefaultRateLimitService.java +++ b/application/src/main/java/org/thingsboard/server/service/apiusage/DefaultRateLimitService.java @@ -16,7 +16,7 @@ package org.thingsboard.server.service.apiusage; import lombok.RequiredArgsConstructor; -import org.apache.commons.lang3.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.springframework.stereotype.Service; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.tenant.profile.DefaultTenantProfileConfiguration; diff --git a/application/src/main/java/org/thingsboard/server/service/apiusage/DefaultTbApiUsageStateService.java b/application/src/main/java/org/thingsboard/server/service/apiusage/DefaultTbApiUsageStateService.java index 7ccfd6fe4d..4971331047 100644 --- a/application/src/main/java/org/thingsboard/server/service/apiusage/DefaultTbApiUsageStateService.java +++ b/application/src/main/java/org/thingsboard/server/service/apiusage/DefaultTbApiUsageStateService.java @@ -19,7 +19,7 @@ import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.checkerframework.checker.nullness.qual.Nullable; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; diff --git a/application/src/main/java/org/thingsboard/server/service/device/ClaimDevicesServiceImpl.java b/application/src/main/java/org/thingsboard/server/service/device/ClaimDevicesServiceImpl.java index 68c9e3117e..a397a4d0e9 100644 --- a/application/src/main/java/org/thingsboard/server/service/device/ClaimDevicesServiceImpl.java +++ b/application/src/main/java/org/thingsboard/server/service/device/ClaimDevicesServiceImpl.java @@ -27,13 +27,13 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.cache.Cache; import org.springframework.cache.CacheManager; import org.springframework.stereotype.Service; -import org.springframework.util.StringUtils; import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.rule.engine.api.RuleEngineTelemetryService; import org.thingsboard.server.cluster.TbClusterService; import org.thingsboard.server.common.data.Customer; import org.thingsboard.server.common.data.DataConstants; import org.thingsboard.server.common.data.Device; +import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.DeviceId; import org.thingsboard.server.common.data.id.TenantId; diff --git a/application/src/main/java/org/thingsboard/server/service/device/DeviceBulkImportService.java b/application/src/main/java/org/thingsboard/server/service/device/DeviceBulkImportService.java index 8b2126905f..92ae09fa3f 100644 --- a/application/src/main/java/org/thingsboard/server/service/device/DeviceBulkImportService.java +++ b/application/src/main/java/org/thingsboard/server/service/device/DeviceBulkImportService.java @@ -22,7 +22,7 @@ import lombok.RequiredArgsConstructor; import lombok.SneakyThrows; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.RandomStringUtils; -import org.apache.commons.lang3.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.springframework.stereotype.Service; import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.server.common.data.Device; diff --git a/application/src/main/java/org/thingsboard/server/service/device/DeviceProvisionServiceImpl.java b/application/src/main/java/org/thingsboard/server/service/device/DeviceProvisionServiceImpl.java index 7fd42740c4..201b0341fd 100644 --- a/application/src/main/java/org/thingsboard/server/service/device/DeviceProvisionServiceImpl.java +++ b/application/src/main/java/org/thingsboard/server/service/device/DeviceProvisionServiceImpl.java @@ -23,7 +23,7 @@ import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.RandomStringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import org.springframework.util.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.cluster.TbClusterService; import org.thingsboard.server.common.data.DataConstants; import org.thingsboard.server.common.data.Device; diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/fetch/AdminSettingsEdgeEventFetcher.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/fetch/AdminSettingsEdgeEventFetcher.java index ee10c7859b..e7be46e2d6 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/fetch/AdminSettingsEdgeEventFetcher.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/fetch/AdminSettingsEdgeEventFetcher.java @@ -23,7 +23,7 @@ import freemarker.template.Configuration; import freemarker.template.Template; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.apache.commons.lang3.text.WordUtils; import org.thingsboard.server.common.data.AdminSettings; import org.thingsboard.server.common.data.EdgeUtils; diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/DeviceEdgeProcessor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/DeviceEdgeProcessor.java index 0e1dee7132..b0e3536e92 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/DeviceEdgeProcessor.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/DeviceEdgeProcessor.java @@ -23,7 +23,7 @@ import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.SettableFuture; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.RandomStringUtils; -import org.apache.commons.lang3.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.springframework.stereotype.Component; import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.server.common.data.Customer; diff --git a/application/src/main/java/org/thingsboard/server/service/entitiy/entityview/DefaultTbEntityViewService.java b/application/src/main/java/org/thingsboard/server/service/entitiy/entityview/DefaultTbEntityViewService.java index e098d6b605..8de6ec9aac 100644 --- a/application/src/main/java/org/thingsboard/server/service/entitiy/entityview/DefaultTbEntityViewService.java +++ b/application/src/main/java/org/thingsboard/server/service/entitiy/entityview/DefaultTbEntityViewService.java @@ -59,7 +59,7 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutionException; import java.util.stream.Collectors; -import static org.apache.commons.lang3.StringUtils.isBlank; +import static org.thingsboard.server.common.data.StringUtils.isBlank; @Service @AllArgsConstructor diff --git a/application/src/main/java/org/thingsboard/server/service/install/DatabaseHelper.java b/application/src/main/java/org/thingsboard/server/service/install/DatabaseHelper.java index 2cff9841da..fa702cc2c6 100644 --- a/application/src/main/java/org/thingsboard/server/service/install/DatabaseHelper.java +++ b/application/src/main/java/org/thingsboard/server/service/install/DatabaseHelper.java @@ -20,7 +20,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import lombok.extern.slf4j.Slf4j; import org.apache.commons.csv.CSVFormat; import org.apache.commons.csv.CSVParser; -import org.apache.commons.lang3.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.data.ShortCustomerInfo; import org.thingsboard.server.common.data.UUIDConverter; import org.thingsboard.server.common.data.id.CustomerId; diff --git a/application/src/main/java/org/thingsboard/server/service/install/InstallScripts.java b/application/src/main/java/org/thingsboard/server/service/install/InstallScripts.java index f193b10a62..b12dc2243d 100644 --- a/application/src/main/java/org/thingsboard/server/service/install/InstallScripts.java +++ b/application/src/main/java/org/thingsboard/server/service/install/InstallScripts.java @@ -20,7 +20,7 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; -import org.springframework.util.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.data.Dashboard; import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.EntityId; diff --git a/application/src/main/java/org/thingsboard/server/service/install/SqlTsDatabaseUpgradeService.java b/application/src/main/java/org/thingsboard/server/service/install/SqlTsDatabaseUpgradeService.java index c1d41a6f6e..1ac003db61 100644 --- a/application/src/main/java/org/thingsboard/server/service/install/SqlTsDatabaseUpgradeService.java +++ b/application/src/main/java/org/thingsboard/server/service/install/SqlTsDatabaseUpgradeService.java @@ -16,7 +16,7 @@ package org.thingsboard.server.service.install; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.apache.commons.lang3.SystemUtils; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Profile; diff --git a/application/src/main/java/org/thingsboard/server/service/install/TimescaleTsDatabaseUpgradeService.java b/application/src/main/java/org/thingsboard/server/service/install/TimescaleTsDatabaseUpgradeService.java index 245dc4503d..4cfa23f278 100644 --- a/application/src/main/java/org/thingsboard/server/service/install/TimescaleTsDatabaseUpgradeService.java +++ b/application/src/main/java/org/thingsboard/server/service/install/TimescaleTsDatabaseUpgradeService.java @@ -16,7 +16,7 @@ package org.thingsboard.server.service.install; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.apache.commons.lang3.SystemUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; diff --git a/application/src/main/java/org/thingsboard/server/service/install/migrate/CassandraTsLatestToSqlMigrateService.java b/application/src/main/java/org/thingsboard/server/service/install/migrate/CassandraTsLatestToSqlMigrateService.java index 142bacd7ff..84e9458c78 100644 --- a/application/src/main/java/org/thingsboard/server/service/install/migrate/CassandraTsLatestToSqlMigrateService.java +++ b/application/src/main/java/org/thingsboard/server/service/install/migrate/CassandraTsLatestToSqlMigrateService.java @@ -16,7 +16,7 @@ package org.thingsboard.server.service.install.migrate; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.hibernate.exception.ConstraintViolationException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; diff --git a/application/src/main/java/org/thingsboard/server/service/install/update/DefaultDataUpdateService.java b/application/src/main/java/org/thingsboard/server/service/install/update/DefaultDataUpdateService.java index 9bfa86b3ba..19ed7da65e 100644 --- a/application/src/main/java/org/thingsboard/server/service/install/update/DefaultDataUpdateService.java +++ b/application/src/main/java/org/thingsboard/server/service/install/update/DefaultDataUpdateService.java @@ -78,7 +78,7 @@ import java.util.concurrent.ExecutionException; import java.util.concurrent.atomic.AtomicLong; import java.util.stream.Collectors; -import static org.apache.commons.lang3.StringUtils.isBlank; +import static org.thingsboard.server.common.data.StringUtils.isBlank; @Service @Profile("install") diff --git a/application/src/main/java/org/thingsboard/server/service/install/update/RateLimitsUpdater.java b/application/src/main/java/org/thingsboard/server/service/install/update/RateLimitsUpdater.java index c136f97b52..52031b252b 100644 --- a/application/src/main/java/org/thingsboard/server/service/install/update/RateLimitsUpdater.java +++ b/application/src/main/java/org/thingsboard/server/service/install/update/RateLimitsUpdater.java @@ -15,7 +15,7 @@ */ package org.thingsboard.server.service.install.update; -import org.apache.commons.lang3.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; diff --git a/application/src/main/java/org/thingsboard/server/service/mail/DefaultMailService.java b/application/src/main/java/org/thingsboard/server/service/mail/DefaultMailService.java index aa8e019317..6db4d741d2 100644 --- a/application/src/main/java/org/thingsboard/server/service/mail/DefaultMailService.java +++ b/application/src/main/java/org/thingsboard/server/service/mail/DefaultMailService.java @@ -19,7 +19,7 @@ import com.fasterxml.jackson.databind.JsonNode; import freemarker.template.Configuration; import freemarker.template.Template; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.apache.commons.lang3.exception.ExceptionUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; diff --git a/application/src/main/java/org/thingsboard/server/service/resource/DefaultTbResourceService.java b/application/src/main/java/org/thingsboard/server/service/resource/DefaultTbResourceService.java index d83508220b..e9b4e849b4 100644 --- a/application/src/main/java/org/thingsboard/server/service/resource/DefaultTbResourceService.java +++ b/application/src/main/java/org/thingsboard/server/service/resource/DefaultTbResourceService.java @@ -16,7 +16,7 @@ package org.thingsboard.server.service.resource; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.eclipse.leshan.core.model.DDFFileParser; import org.eclipse.leshan.core.model.DefaultDDFFileValidator; import org.eclipse.leshan.core.model.InvalidDDFFileException; diff --git a/application/src/main/java/org/thingsboard/server/service/script/RuleNodeJsScriptEngine.java b/application/src/main/java/org/thingsboard/server/service/script/RuleNodeJsScriptEngine.java index 4b2bcb99da..c90e104ff4 100644 --- a/application/src/main/java/org/thingsboard/server/service/script/RuleNodeJsScriptEngine.java +++ b/application/src/main/java/org/thingsboard/server/service/script/RuleNodeJsScriptEngine.java @@ -22,7 +22,7 @@ import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.MoreExecutors; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.TenantId; diff --git a/application/src/main/java/org/thingsboard/server/service/security/auth/jwt/RefreshTokenProcessingFilter.java b/application/src/main/java/org/thingsboard/server/service/security/auth/jwt/RefreshTokenProcessingFilter.java index 28794fc77e..2128ab0fa3 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/auth/jwt/RefreshTokenProcessingFilter.java +++ b/application/src/main/java/org/thingsboard/server/service/security/auth/jwt/RefreshTokenProcessingFilter.java @@ -17,7 +17,7 @@ package org.thingsboard.server.service.security.auth.jwt; import com.fasterxml.jackson.databind.ObjectMapper; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.springframework.http.HttpMethod; import org.springframework.security.authentication.AuthenticationServiceException; import org.springframework.security.core.Authentication; diff --git a/application/src/main/java/org/thingsboard/server/service/security/auth/jwt/extractor/JwtHeaderTokenExtractor.java b/application/src/main/java/org/thingsboard/server/service/security/auth/jwt/extractor/JwtHeaderTokenExtractor.java index b29164fb6b..4f8d9425a6 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/auth/jwt/extractor/JwtHeaderTokenExtractor.java +++ b/application/src/main/java/org/thingsboard/server/service/security/auth/jwt/extractor/JwtHeaderTokenExtractor.java @@ -15,7 +15,7 @@ */ package org.thingsboard.server.service.security.auth.jwt.extractor; -import org.apache.commons.lang3.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.springframework.security.authentication.AuthenticationServiceException; import org.springframework.stereotype.Component; import org.thingsboard.server.config.ThingsboardSecurityConfiguration; diff --git a/application/src/main/java/org/thingsboard/server/service/security/auth/jwt/extractor/JwtQueryTokenExtractor.java b/application/src/main/java/org/thingsboard/server/service/security/auth/jwt/extractor/JwtQueryTokenExtractor.java index 17ed090807..129e865631 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/auth/jwt/extractor/JwtQueryTokenExtractor.java +++ b/application/src/main/java/org/thingsboard/server/service/security/auth/jwt/extractor/JwtQueryTokenExtractor.java @@ -15,7 +15,7 @@ */ package org.thingsboard.server.service.security.auth.jwt.extractor; -import org.apache.commons.lang3.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.springframework.security.authentication.AuthenticationServiceException; import org.springframework.stereotype.Component; import org.thingsboard.server.config.ThingsboardSecurityConfiguration; diff --git a/application/src/main/java/org/thingsboard/server/service/security/auth/mfa/DefaultTwoFactorAuthService.java b/application/src/main/java/org/thingsboard/server/service/security/auth/mfa/DefaultTwoFactorAuthService.java index 0972b378eb..7657a81e66 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/auth/mfa/DefaultTwoFactorAuthService.java +++ b/application/src/main/java/org/thingsboard/server/service/security/auth/mfa/DefaultTwoFactorAuthService.java @@ -16,7 +16,7 @@ package org.thingsboard.server.service.security.auth.mfa; import lombok.RequiredArgsConstructor; -import org.apache.commons.lang3.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.authentication.LockedException; import org.springframework.stereotype.Service; diff --git a/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/AbstractOAuth2ClientMapper.java b/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/AbstractOAuth2ClientMapper.java index ede9f8746a..9b7912c6a7 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/AbstractOAuth2ClientMapper.java +++ b/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/AbstractOAuth2ClientMapper.java @@ -24,7 +24,7 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; -import org.springframework.util.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.data.Customer; import org.thingsboard.server.common.data.DashboardInfo; import org.thingsboard.server.common.data.Tenant; diff --git a/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/AppleOAuth2ClientMapper.java b/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/AppleOAuth2ClientMapper.java index 77b9a94aaa..5021f72f68 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/AppleOAuth2ClientMapper.java +++ b/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/AppleOAuth2ClientMapper.java @@ -21,7 +21,7 @@ import org.springframework.security.oauth2.client.authentication.OAuth2Authentic import org.springframework.stereotype.Service; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; -import org.springframework.util.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.server.common.data.oauth2.OAuth2MapperConfig; import org.thingsboard.server.common.data.oauth2.OAuth2Registration; diff --git a/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/BasicMapperUtils.java b/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/BasicMapperUtils.java index 2185387520..e8e1011a47 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/BasicMapperUtils.java +++ b/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/BasicMapperUtils.java @@ -17,7 +17,7 @@ package org.thingsboard.server.service.security.auth.oauth2; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.text.StrSubstitutor; -import org.springframework.util.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.data.oauth2.OAuth2MapperConfig; import org.thingsboard.server.dao.oauth2.OAuth2User; diff --git a/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/CustomOAuth2ClientMapper.java b/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/CustomOAuth2ClientMapper.java index 39438b997d..377a761b43 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/CustomOAuth2ClientMapper.java +++ b/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/CustomOAuth2ClientMapper.java @@ -22,7 +22,7 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.boot.web.client.RestTemplateBuilder; import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken; import org.springframework.stereotype.Service; -import org.springframework.util.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.springframework.web.client.RestTemplate; import org.thingsboard.server.common.data.oauth2.OAuth2CustomMapperConfig; import org.thingsboard.server.common.data.oauth2.OAuth2MapperConfig; diff --git a/application/src/main/java/org/thingsboard/server/service/security/auth/rest/RestLoginProcessingFilter.java b/application/src/main/java/org/thingsboard/server/service/security/auth/rest/RestLoginProcessingFilter.java index 2fcb2516df..8b42a0d140 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/auth/rest/RestLoginProcessingFilter.java +++ b/application/src/main/java/org/thingsboard/server/service/security/auth/rest/RestLoginProcessingFilter.java @@ -17,7 +17,7 @@ package org.thingsboard.server.service.security.auth.rest; import com.fasterxml.jackson.databind.ObjectMapper; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.springframework.http.HttpMethod; import org.springframework.security.authentication.AuthenticationDetailsSource; import org.springframework.security.authentication.AuthenticationServiceException; diff --git a/application/src/main/java/org/thingsboard/server/service/security/auth/rest/RestPublicLoginProcessingFilter.java b/application/src/main/java/org/thingsboard/server/service/security/auth/rest/RestPublicLoginProcessingFilter.java index 8c5fb15aee..83b5f78868 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/auth/rest/RestPublicLoginProcessingFilter.java +++ b/application/src/main/java/org/thingsboard/server/service/security/auth/rest/RestPublicLoginProcessingFilter.java @@ -17,7 +17,7 @@ package org.thingsboard.server.service.security.auth.rest; import com.fasterxml.jackson.databind.ObjectMapper; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.springframework.http.HttpMethod; import org.springframework.security.authentication.AuthenticationServiceException; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; diff --git a/application/src/main/java/org/thingsboard/server/service/security/model/token/JwtTokenFactory.java b/application/src/main/java/org/thingsboard/server/service/security/model/token/JwtTokenFactory.java index a8e6f9cb5c..182bf58609 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/model/token/JwtTokenFactory.java +++ b/application/src/main/java/org/thingsboard/server/service/security/model/token/JwtTokenFactory.java @@ -25,7 +25,7 @@ import io.jsonwebtoken.SignatureAlgorithm; import io.jsonwebtoken.SignatureException; import io.jsonwebtoken.UnsupportedJwtException; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.core.GrantedAuthority; diff --git a/application/src/main/java/org/thingsboard/server/service/security/model/token/OAuth2AppTokenFactory.java b/application/src/main/java/org/thingsboard/server/service/security/model/token/OAuth2AppTokenFactory.java index 1b25ea9d87..485cfa5c97 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/model/token/OAuth2AppTokenFactory.java +++ b/application/src/main/java/org/thingsboard/server/service/security/model/token/OAuth2AppTokenFactory.java @@ -22,7 +22,7 @@ import io.jsonwebtoken.Jwts; import io.jsonwebtoken.MalformedJwtException; import io.jsonwebtoken.SignatureException; import io.jsonwebtoken.UnsupportedJwtException; -import io.micrometer.core.instrument.util.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; diff --git a/application/src/main/java/org/thingsboard/server/service/security/system/DefaultSystemSecurityService.java b/application/src/main/java/org/thingsboard/server/service/security/system/DefaultSystemSecurityService.java index e399c14d04..887b4d346e 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/system/DefaultSystemSecurityService.java +++ b/application/src/main/java/org/thingsboard/server/service/security/system/DefaultSystemSecurityService.java @@ -19,7 +19,7 @@ import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ObjectNode; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.passay.CharacterRule; import org.passay.EnglishCharacterData; import org.passay.LengthRule; diff --git a/application/src/main/java/org/thingsboard/server/service/sms/aws/AwsSmsSender.java b/application/src/main/java/org/thingsboard/server/service/sms/aws/AwsSmsSender.java index 41601d9f1c..3221c56a85 100644 --- a/application/src/main/java/org/thingsboard/server/service/sms/aws/AwsSmsSender.java +++ b/application/src/main/java/org/thingsboard/server/service/sms/aws/AwsSmsSender.java @@ -23,7 +23,7 @@ import com.amazonaws.services.sns.AmazonSNSClient; import com.amazonaws.services.sns.model.MessageAttributeValue; import com.amazonaws.services.sns.model.PublishRequest; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.data.sms.config.AwsSnsSmsProviderConfiguration; import org.thingsboard.rule.engine.api.sms.exception.SmsException; import org.thingsboard.rule.engine.api.sms.exception.SmsSendException; diff --git a/application/src/main/java/org/thingsboard/server/service/sms/smpp/SmppSmsSender.java b/application/src/main/java/org/thingsboard/server/service/sms/smpp/SmppSmsSender.java index 57c5c5d25c..88c73490ba 100644 --- a/application/src/main/java/org/thingsboard/server/service/sms/smpp/SmppSmsSender.java +++ b/application/src/main/java/org/thingsboard/server/service/sms/smpp/SmppSmsSender.java @@ -16,7 +16,7 @@ package org.thingsboard.server.service.sms.smpp; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.apache.commons.lang3.exception.ExceptionUtils; import org.smpp.Connection; import org.smpp.Data; diff --git a/application/src/main/java/org/thingsboard/server/service/sms/twilio/TwilioSmsSender.java b/application/src/main/java/org/thingsboard/server/service/sms/twilio/TwilioSmsSender.java index fb2fd0376b..eb187f2f31 100644 --- a/application/src/main/java/org/thingsboard/server/service/sms/twilio/TwilioSmsSender.java +++ b/application/src/main/java/org/thingsboard/server/service/sms/twilio/TwilioSmsSender.java @@ -18,7 +18,7 @@ package org.thingsboard.server.service.sms.twilio; import com.twilio.http.TwilioRestClient; import com.twilio.rest.api.v2010.account.Message; import com.twilio.type.PhoneNumber; -import org.apache.commons.lang3.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.rule.engine.api.sms.exception.SmsParseException; import org.thingsboard.server.common.data.sms.config.TwilioSmsProviderConfiguration; import org.thingsboard.rule.engine.api.sms.exception.SmsException; diff --git a/application/src/main/java/org/thingsboard/server/service/state/DefaultDeviceStateService.java b/application/src/main/java/org/thingsboard/server/service/state/DefaultDeviceStateService.java index d74b0fca87..b62e8a6c11 100644 --- a/application/src/main/java/org/thingsboard/server/service/state/DefaultDeviceStateService.java +++ b/application/src/main/java/org/thingsboard/server/service/state/DefaultDeviceStateService.java @@ -25,7 +25,7 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; -import org.springframework.util.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.common.util.ThingsBoardThreadFactory; import org.thingsboard.server.cluster.TbClusterService; diff --git a/application/src/main/java/org/thingsboard/server/service/sync/ie/importing/csv/AbstractBulkImportService.java b/application/src/main/java/org/thingsboard/server/service/sync/ie/importing/csv/AbstractBulkImportService.java index becf92771f..43bf002d6c 100644 --- a/application/src/main/java/org/thingsboard/server/service/sync/ie/importing/csv/AbstractBulkImportService.java +++ b/application/src/main/java/org/thingsboard/server/service/sync/ie/importing/csv/AbstractBulkImportService.java @@ -20,7 +20,7 @@ import com.google.gson.JsonObject; import com.google.gson.JsonPrimitive; import lombok.Data; import lombok.SneakyThrows; -import org.apache.commons.lang3.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.apache.commons.lang3.exception.ExceptionUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.core.context.SecurityContext; diff --git a/application/src/main/java/org/thingsboard/server/service/telemetry/DefaultTelemetryWebSocketService.java b/application/src/main/java/org/thingsboard/server/service/telemetry/DefaultTelemetryWebSocketService.java index 0551d7e114..acfed379f4 100644 --- a/application/src/main/java/org/thingsboard/server/service/telemetry/DefaultTelemetryWebSocketService.java +++ b/application/src/main/java/org/thingsboard/server/service/telemetry/DefaultTelemetryWebSocketService.java @@ -26,7 +26,7 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; -import org.springframework.util.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.springframework.web.socket.CloseStatus; import org.thingsboard.common.util.ThingsBoardExecutors; import org.thingsboard.common.util.ThingsBoardThreadFactory; diff --git a/application/src/test/java/org/thingsboard/server/controller/AbstractWebTest.java b/application/src/test/java/org/thingsboard/server/controller/AbstractWebTest.java index 677303cc15..19e78626f7 100644 --- a/application/src/test/java/org/thingsboard/server/controller/AbstractWebTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/AbstractWebTest.java @@ -27,7 +27,7 @@ import io.jsonwebtoken.Jwt; import io.jsonwebtoken.Jwts; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.RandomStringUtils; -import org.apache.commons.lang3.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.hamcrest.Matcher; import org.junit.After; import org.junit.Assert; diff --git a/application/src/test/java/org/thingsboard/server/controller/TwoFactorAuthTest.java b/application/src/test/java/org/thingsboard/server/controller/TwoFactorAuthTest.java index 9c30ebbbd0..6e99d15c8f 100644 --- a/application/src/test/java/org/thingsboard/server/controller/TwoFactorAuthTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/TwoFactorAuthTest.java @@ -18,7 +18,7 @@ package org.thingsboard.server.controller; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.JsonNode; import org.apache.commons.lang3.RandomStringUtils; -import org.apache.commons.lang3.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.jboss.aerogear.security.otp.Totp; import org.junit.After; import org.junit.Before; diff --git a/application/src/test/java/org/thingsboard/server/service/sms/smpp/SmppSmsSenderTest.java b/application/src/test/java/org/thingsboard/server/service/sms/smpp/SmppSmsSenderTest.java index 7cbc8c03d2..f7cc80d02d 100644 --- a/application/src/test/java/org/thingsboard/server/service/sms/smpp/SmppSmsSenderTest.java +++ b/application/src/test/java/org/thingsboard/server/service/sms/smpp/SmppSmsSenderTest.java @@ -15,7 +15,7 @@ */ package org.thingsboard.server.service.sms.smpp; -import org.apache.commons.lang3.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.assertj.core.api.Assertions; import org.junit.Before; import org.junit.Ignore; diff --git a/application/src/test/java/org/thingsboard/server/transport/coap/rpc/AbstractCoapServerSideRpcIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/coap/rpc/AbstractCoapServerSideRpcIntegrationTest.java index beb4d3747c..96eb92757c 100644 --- a/application/src/test/java/org/thingsboard/server/transport/coap/rpc/AbstractCoapServerSideRpcIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/coap/rpc/AbstractCoapServerSideRpcIntegrationTest.java @@ -22,7 +22,7 @@ import com.google.protobuf.DynamicMessage; import com.google.protobuf.InvalidProtocolBufferException; import com.squareup.wire.schema.internal.parser.ProtoFileElement; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.eclipse.californium.core.CoapHandler; import org.eclipse.californium.core.CoapObserveRelation; import org.eclipse.californium.core.CoapResponse; diff --git a/application/src/test/java/org/thingsboard/server/transport/mqtt/AbstractMqttIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/mqtt/AbstractMqttIntegrationTest.java index 9fbdff3fa5..4c07cec3d4 100644 --- a/application/src/test/java/org/thingsboard/server/transport/mqtt/AbstractMqttIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/mqtt/AbstractMqttIntegrationTest.java @@ -23,7 +23,7 @@ import org.eclipse.paho.client.mqttv3.MqttException; import org.eclipse.paho.client.mqttv3.MqttMessage; import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence; import org.springframework.test.context.TestPropertySource; -import org.springframework.util.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.DeviceProfile; import org.thingsboard.server.common.data.DeviceProfileInfo; diff --git a/application/src/test/java/org/thingsboard/server/transport/mqtt/rpc/AbstractMqttServerSideRpcIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/mqtt/rpc/AbstractMqttServerSideRpcIntegrationTest.java index 0abd0f1d6c..78c63b6fd2 100644 --- a/application/src/test/java/org/thingsboard/server/transport/mqtt/rpc/AbstractMqttServerSideRpcIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/mqtt/rpc/AbstractMqttServerSideRpcIntegrationTest.java @@ -25,7 +25,7 @@ import com.nimbusds.jose.util.StandardCharset; import com.squareup.wire.schema.internal.parser.ProtoFileElement; import io.netty.handler.codec.mqtt.MqttQoS; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.eclipse.paho.client.mqttv3.MqttException; import org.eclipse.paho.client.mqttv3.MqttMessage; import org.thingsboard.common.util.JacksonUtil; diff --git a/common/cache/src/main/java/org/thingsboard/server/cache/TBRedisClusterConfiguration.java b/common/cache/src/main/java/org/thingsboard/server/cache/TBRedisClusterConfiguration.java index 2cf67e35aa..f68dabf9eb 100644 --- a/common/cache/src/main/java/org/thingsboard/server/cache/TBRedisClusterConfiguration.java +++ b/common/cache/src/main/java/org/thingsboard/server/cache/TBRedisClusterConfiguration.java @@ -15,7 +15,7 @@ */ package org.thingsboard.server.cache; -import org.apache.commons.lang3.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; diff --git a/common/coap-server/src/main/java/org/thingsboard/server/coapserver/TbCoapDtlsCertificateVerifier.java b/common/coap-server/src/main/java/org/thingsboard/server/coapserver/TbCoapDtlsCertificateVerifier.java index ce8b093b4d..15807c4154 100644 --- a/common/coap-server/src/main/java/org/thingsboard/server/coapserver/TbCoapDtlsCertificateVerifier.java +++ b/common/coap-server/src/main/java/org/thingsboard/server/coapserver/TbCoapDtlsCertificateVerifier.java @@ -27,7 +27,7 @@ import org.eclipse.californium.scandium.dtls.HandshakeException; import org.eclipse.californium.scandium.dtls.HandshakeResultHandler; import org.eclipse.californium.scandium.dtls.x509.NewAdvancedCertificateVerifier; import org.eclipse.californium.scandium.util.ServerNames; -import org.springframework.util.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.data.DeviceProfile; import org.thingsboard.server.common.data.DeviceTransportType; import org.thingsboard.server.common.msg.EncryptionUtil; diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/cassandra/CassandraDriverOptions.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/cassandra/CassandraDriverOptions.java index 986be6d515..3c6d8ce1dd 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/cassandra/CassandraDriverOptions.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/cassandra/CassandraDriverOptions.java @@ -23,7 +23,7 @@ import com.datastax.oss.driver.api.core.config.ProgrammaticDriverConfigLoaderBui import com.datastax.oss.driver.api.core.metrics.DefaultSessionMetric; import com.datastax.oss.driver.api.core.metrics.DefaultNodeMetric; import lombok.Data; -import org.apache.commons.lang3.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Configuration; import org.springframework.stereotype.Component; diff --git a/common/data/pom.xml b/common/data/pom.xml index 539dd0d9e3..50755115a0 100644 --- a/common/data/pom.xml +++ b/common/data/pom.xml @@ -108,6 +108,16 @@ de.ruedigermoeller fst + + org.eclipse.leshan + leshan-core + + + com.amazonaws + aws-java-sdk-core + 1.11.747 + compile + diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/StringUtils.java b/common/data/src/main/java/org/thingsboard/server/common/data/StringUtils.java index f76757f522..4b916df30e 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/StringUtils.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/StringUtils.java @@ -17,9 +17,12 @@ package org.thingsboard.server.common.data; import com.google.common.base.Splitter; +import java.nio.charset.Charset; + import static org.apache.commons.lang3.StringUtils.repeat; public class StringUtils { + public static Charset UTF8 = com.amazonaws.util.StringUtils.UTF8; public static final String EMPTY = ""; @@ -98,4 +101,51 @@ public class StringUtils { return Splitter.fixedLength(maxPartSize).split(value); } + public static boolean equalsIgnoreCase(String value, String aTrue) { + return org.eclipse.leshan.core.util.StringUtils.equalsIgnoreCase(value, aTrue); + } + + public static String join(String[] keyArray, String lwm2mSeparatorPath) { + return org.apache.commons.lang3.StringUtils.join(keyArray, lwm2mSeparatorPath); + } + + public static String trimToNull(String toString) { + return org.apache.commons.lang3.StringUtils.trimToNull(toString); + } + + public static boolean isNoneEmpty(String str) { + return org.apache.commons.lang3.StringUtils.isNoneEmpty(str); + } + + public static boolean endsWith(String str, String suffix) { + return org.apache.commons.lang3.StringUtils.endsWith(str, suffix); + } + + public static boolean hasLength(String str) { + return org.springframework.util.StringUtils.hasLength(str); + } + + public static boolean isNoneBlank(String str) { + return org.apache.commons.lang3.StringUtils.isNoneBlank(str); + } + + public static boolean hasText(String str) { + return org.springframework.util.StringUtils.hasText(str); + } + + public static String defaultString(String s, String defaultValue) { + return org.apache.commons.lang3.StringUtils.defaultString(s, defaultValue); + } + + public static boolean isNumeric(String str) { + return org.apache.commons.lang3.StringUtils.isNumeric(str); + } + + public static boolean equals(String str1, String str2) { + return org.apache.commons.lang3.StringUtils.equals(str1, str2); + } + + public static String substringAfterLast(String str, String sep) { + return org.apache.commons.lang3.StringUtils.substringAfterLast(str, sep); + } } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/device/data/SnmpDeviceTransportConfiguration.java b/common/data/src/main/java/org/thingsboard/server/common/data/device/data/SnmpDeviceTransportConfiguration.java index 041fe4752c..0893157ef6 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/device/data/SnmpDeviceTransportConfiguration.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/device/data/SnmpDeviceTransportConfiguration.java @@ -19,7 +19,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import lombok.Data; import lombok.ToString; import org.apache.commons.lang3.ObjectUtils; -import org.apache.commons.lang3.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.data.DeviceTransportType; import org.thingsboard.server.common.data.transport.snmp.AuthenticationProtocol; import org.thingsboard.server.common.data.transport.snmp.PrivacyProtocol; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/sync/vc/EntityLoadError.java b/common/data/src/main/java/org/thingsboard/server/common/data/sync/vc/EntityLoadError.java index cbfe9f6457..1f54a7c262 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/sync/vc/EntityLoadError.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/sync/vc/EntityLoadError.java @@ -19,7 +19,7 @@ import com.fasterxml.jackson.annotation.JsonInclude; import lombok.Builder; import lombok.Data; import org.apache.commons.lang3.ClassUtils; -import org.apache.commons.lang3.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.data.id.EntityId; import java.io.Serializable; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/transport/snmp/SnmpMapping.java b/common/data/src/main/java/org/thingsboard/server/common/data/transport/snmp/SnmpMapping.java index 44fe42512b..376311f75b 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/transport/snmp/SnmpMapping.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/transport/snmp/SnmpMapping.java @@ -19,7 +19,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; -import org.apache.commons.lang3.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.data.kv.DataType; import java.util.regex.Pattern; diff --git a/common/message/src/main/java/org/thingsboard/server/common/msg/TbMsg.java b/common/message/src/main/java/org/thingsboard/server/common/msg/TbMsg.java index bb3be80629..ba7c957d58 100644 --- a/common/message/src/main/java/org/thingsboard/server/common/msg/TbMsg.java +++ b/common/message/src/main/java/org/thingsboard/server/common/msg/TbMsg.java @@ -22,7 +22,7 @@ import lombok.AccessLevel; import lombok.Data; import lombok.Getter; import lombok.extern.slf4j.Slf4j; -import org.springframework.util.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.EntityId; diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/discovery/DefaultTbServiceInfoProvider.java b/common/queue/src/main/java/org/thingsboard/server/queue/discovery/DefaultTbServiceInfoProvider.java index a3744c3946..ba8f103658 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/discovery/DefaultTbServiceInfoProvider.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/discovery/DefaultTbServiceInfoProvider.java @@ -21,7 +21,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.ApplicationContext; import org.springframework.stereotype.Component; -import org.springframework.util.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.data.TbTransportService; import org.thingsboard.server.common.msg.queue.ServiceType; import org.thingsboard.server.gen.transport.TransportProtos.ServiceInfo; diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/kafka/TbKafkaConsumerStatsService.java b/common/queue/src/main/java/org/thingsboard/server/queue/kafka/TbKafkaConsumerStatsService.java index e62ee850fa..9c867fb5be 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/kafka/TbKafkaConsumerStatsService.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/kafka/TbKafkaConsumerStatsService.java @@ -29,7 +29,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Component; -import org.springframework.util.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.common.util.ThingsBoardThreadFactory; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.msg.queue.ServiceType; diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/kafka/TbKafkaProducerTemplate.java b/common/queue/src/main/java/org/thingsboard/server/queue/kafka/TbKafkaProducerTemplate.java index d4946581e6..29aadcafd6 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/kafka/TbKafkaProducerTemplate.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/kafka/TbKafkaProducerTemplate.java @@ -23,7 +23,7 @@ import org.apache.kafka.clients.producer.ProducerConfig; import org.apache.kafka.clients.producer.ProducerRecord; import org.apache.kafka.common.header.Header; import org.apache.kafka.common.header.internals.RecordHeader; -import org.springframework.util.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.msg.queue.TopicPartitionInfo; import org.thingsboard.server.queue.TbQueueAdmin; import org.thingsboard.server.queue.TbQueueCallback; diff --git a/common/stats/pom.xml b/common/stats/pom.xml index 7802793d64..b5bb3c39b7 100644 --- a/common/stats/pom.xml +++ b/common/stats/pom.xml @@ -86,6 +86,10 @@ awaitility test + + org.thingsboard.common + data + diff --git a/common/stats/src/main/java/org/thingsboard/server/common/stats/DefaultStatsFactory.java b/common/stats/src/main/java/org/thingsboard/server/common/stats/DefaultStatsFactory.java index e71ac22d00..dff0212e99 100644 --- a/common/stats/src/main/java/org/thingsboard/server/common/stats/DefaultStatsFactory.java +++ b/common/stats/src/main/java/org/thingsboard/server/common/stats/DefaultStatsFactory.java @@ -19,7 +19,7 @@ import io.micrometer.core.instrument.*; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; -import org.springframework.util.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import javax.annotation.PostConstruct; import java.util.concurrent.atomic.AtomicInteger; diff --git a/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/adaptors/CoapAdaptorUtils.java b/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/adaptors/CoapAdaptorUtils.java index a23ca82234..1043cecc41 100644 --- a/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/adaptors/CoapAdaptorUtils.java +++ b/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/adaptors/CoapAdaptorUtils.java @@ -16,7 +16,7 @@ package org.thingsboard.server.transport.coap.adaptors; import org.eclipse.californium.core.coap.Request; -import org.springframework.util.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.transport.adaptor.AdaptorException; import org.thingsboard.server.gen.transport.TransportProtos; diff --git a/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/adaptors/JsonCoapAdaptor.java b/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/adaptors/JsonCoapAdaptor.java index 3d4a4ee053..3568624289 100644 --- a/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/adaptors/JsonCoapAdaptor.java +++ b/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/adaptors/JsonCoapAdaptor.java @@ -27,7 +27,7 @@ import org.eclipse.californium.core.coap.MediaTypeRegistry; import org.eclipse.californium.core.coap.Request; import org.eclipse.californium.core.coap.Response; import org.springframework.stereotype.Component; -import org.springframework.util.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.data.id.DeviceId; import org.thingsboard.server.common.transport.adaptor.AdaptorException; import org.thingsboard.server.common.transport.adaptor.JsonConverter; diff --git a/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/adaptors/ProtoCoapAdaptor.java b/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/adaptors/ProtoCoapAdaptor.java index 1bd1ffb827..13c783675e 100644 --- a/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/adaptors/ProtoCoapAdaptor.java +++ b/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/adaptors/ProtoCoapAdaptor.java @@ -26,7 +26,7 @@ import org.eclipse.californium.core.coap.MediaTypeRegistry; import org.eclipse.californium.core.coap.Request; import org.eclipse.californium.core.coap.Response; import org.springframework.stereotype.Component; -import org.springframework.util.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.data.id.DeviceId; import org.thingsboard.server.common.transport.adaptor.AdaptorException; import org.thingsboard.server.common.transport.adaptor.JsonConverter; diff --git a/common/transport/http/src/main/java/org/thingsboard/server/transport/http/DeviceApiController.java b/common/transport/http/src/main/java/org/thingsboard/server/transport/http/DeviceApiController.java index de9619cb9f..17bc257ccb 100644 --- a/common/transport/http/src/main/java/org/thingsboard/server/transport/http/DeviceApiController.java +++ b/common/transport/http/src/main/java/org/thingsboard/server/transport/http/DeviceApiController.java @@ -28,7 +28,7 @@ import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; -import org.springframework.util.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/utils/LwM2MTransportUtil.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/utils/LwM2MTransportUtil.java index ca001e3b83..43c40280a8 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/utils/LwM2MTransportUtil.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/utils/LwM2MTransportUtil.java @@ -18,7 +18,7 @@ package org.thingsboard.server.transport.lwm2m.utils; import com.fasterxml.jackson.core.type.TypeReference; import com.google.gson.JsonElement; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.eclipse.leshan.core.attributes.Attribute; import org.eclipse.leshan.core.attributes.AttributeSet; import org.eclipse.leshan.core.model.LwM2mModel; diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/utils/LwM2mValueConverterImpl.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/utils/LwM2mValueConverterImpl.java index c4057be1fe..cd2bb87fc4 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/utils/LwM2mValueConverterImpl.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/utils/LwM2mValueConverterImpl.java @@ -23,7 +23,7 @@ import org.eclipse.leshan.core.node.ObjectLink; import org.eclipse.leshan.core.node.codec.CodecException; import org.eclipse.leshan.core.node.codec.LwM2mValueConverter; import org.eclipse.leshan.core.util.Hex; -import org.eclipse.leshan.core.util.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import java.math.BigInteger; import java.text.DateFormat; diff --git a/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttSslHandlerProvider.java b/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttSslHandlerProvider.java index 8408c76a16..98aaca7f06 100644 --- a/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttSslHandlerProvider.java +++ b/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttSslHandlerProvider.java @@ -24,7 +24,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.stereotype.Component; -import org.springframework.util.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.data.DeviceTransportType; import org.thingsboard.server.common.msg.EncryptionUtil; import org.thingsboard.server.common.transport.TransportService; diff --git a/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttTransportHandler.java b/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttTransportHandler.java index f37715efc8..b83cb4aa44 100644 --- a/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttTransportHandler.java +++ b/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttTransportHandler.java @@ -41,7 +41,7 @@ import io.netty.util.ReferenceCountUtil; import io.netty.util.concurrent.Future; import io.netty.util.concurrent.GenericFutureListener; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.data.DataConstants; import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.DeviceProfile; @@ -89,7 +89,7 @@ import java.util.concurrent.TimeUnit; import java.util.regex.Matcher; import java.util.regex.Pattern; -import static com.amazonaws.util.StringUtils.UTF8; +import static org.thingsboard.server.common.data.StringUtils.UTF8; import static io.netty.handler.codec.mqtt.MqttConnectReturnCode.CONNECTION_ACCEPTED; import static io.netty.handler.codec.mqtt.MqttConnectReturnCode.CONNECTION_REFUSED_NOT_AUTHORIZED; import static io.netty.handler.codec.mqtt.MqttMessageType.CONNACK; diff --git a/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/adaptors/JsonMqttAdaptor.java b/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/adaptors/JsonMqttAdaptor.java index 75c76c0cdb..b8e120f301 100644 --- a/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/adaptors/JsonMqttAdaptor.java +++ b/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/adaptors/JsonMqttAdaptor.java @@ -27,7 +27,7 @@ import io.netty.handler.codec.mqtt.MqttPublishMessage; import io.netty.handler.codec.mqtt.MqttPublishVariableHeader; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; -import org.springframework.util.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.data.device.profile.MqttTopics; import org.thingsboard.server.common.data.ota.OtaPackageType; import org.thingsboard.server.common.transport.adaptor.AdaptorException; diff --git a/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/adaptors/ProtoMqttAdaptor.java b/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/adaptors/ProtoMqttAdaptor.java index 175bf17c02..17ae0d75b5 100644 --- a/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/adaptors/ProtoMqttAdaptor.java +++ b/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/adaptors/ProtoMqttAdaptor.java @@ -25,7 +25,7 @@ import io.netty.handler.codec.mqtt.MqttMessage; import io.netty.handler.codec.mqtt.MqttPublishMessage; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; -import org.springframework.util.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.data.device.profile.MqttTopics; import org.thingsboard.server.common.data.ota.OtaPackageType; import org.thingsboard.server.common.transport.adaptor.AdaptorException; diff --git a/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/session/GatewaySessionHandler.java b/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/session/GatewaySessionHandler.java index d91935086b..fad67470ba 100644 --- a/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/session/GatewaySessionHandler.java +++ b/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/session/GatewaySessionHandler.java @@ -35,7 +35,7 @@ import io.netty.handler.codec.mqtt.MqttPublishMessage; import lombok.extern.slf4j.Slf4j; import org.springframework.util.CollectionUtils; import org.springframework.util.ConcurrentReferenceHashMap; -import org.springframework.util.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.data.id.DeviceId; import org.thingsboard.server.common.transport.TransportService; import org.thingsboard.server.common.transport.TransportServiceCallback; diff --git a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/adaptor/JsonConverter.java b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/adaptor/JsonConverter.java index 636b9554a5..3ba33d58da 100644 --- a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/adaptor/JsonConverter.java +++ b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/adaptor/JsonConverter.java @@ -23,7 +23,7 @@ import com.google.gson.JsonParser; import com.google.gson.JsonPrimitive; import com.google.gson.JsonSyntaxException; import org.apache.commons.lang3.math.NumberUtils; -import org.springframework.util.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.data.DataConstants; import org.thingsboard.server.common.data.id.DeviceId; import org.thingsboard.server.common.data.kv.AttributeKvEntry; diff --git a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/adaptor/ProtoConverter.java b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/adaptor/ProtoConverter.java index 137ceff337..6fe0f29cfc 100644 --- a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/adaptor/ProtoConverter.java +++ b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/adaptor/ProtoConverter.java @@ -25,7 +25,7 @@ import com.google.protobuf.InvalidProtocolBufferException; import com.google.protobuf.util.JsonFormat; import lombok.extern.slf4j.Slf4j; import org.springframework.util.CollectionUtils; -import org.springframework.util.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.data.DataConstants; import org.thingsboard.server.common.data.id.DeviceId; import org.thingsboard.server.gen.transport.TransportApiProtos; diff --git a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/limits/DefaultTransportRateLimitService.java b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/limits/DefaultTransportRateLimitService.java index e3170797bd..92084db5af 100644 --- a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/limits/DefaultTransportRateLimitService.java +++ b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/limits/DefaultTransportRateLimitService.java @@ -18,7 +18,7 @@ package org.thingsboard.server.common.transport.limits; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; -import org.springframework.util.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.TenantProfile; import org.thingsboard.server.common.data.id.DeviceId; diff --git a/common/version-control/src/main/java/org/thingsboard/server/service/sync/vc/DefaultGitRepositoryService.java b/common/version-control/src/main/java/org/thingsboard/server/service/sync/vc/DefaultGitRepositoryService.java index d3615f7228..64f4e90cb8 100644 --- a/common/version-control/src/main/java/org/thingsboard/server/service/sync/vc/DefaultGitRepositoryService.java +++ b/common/version-control/src/main/java/org/thingsboard/server/service/sync/vc/DefaultGitRepositoryService.java @@ -18,7 +18,7 @@ package org.thingsboard.server.service.sync.vc; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import org.apache.commons.io.FileUtils; -import org.apache.commons.lang3.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.eclipse.jgit.api.errors.GitAPIException; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; diff --git a/common/version-control/src/main/java/org/thingsboard/server/service/sync/vc/GitRepository.java b/common/version-control/src/main/java/org/thingsboard/server/service/sync/vc/GitRepository.java index 7d1710a87b..d820659e77 100644 --- a/common/version-control/src/main/java/org/thingsboard/server/service/sync/vc/GitRepository.java +++ b/common/version-control/src/main/java/org/thingsboard/server/service/sync/vc/GitRepository.java @@ -20,7 +20,7 @@ import com.google.common.collect.Ordering; import com.google.common.collect.Streams; import lombok.Data; import lombok.Getter; -import org.apache.commons.lang3.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.apache.sshd.common.util.security.SecurityUtils; import org.eclipse.jgit.api.CloneCommand; import org.eclipse.jgit.api.Git; diff --git a/dao/src/main/java/org/thingsboard/server/dao/audit/AuditLogServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/audit/AuditLogServiceImpl.java index e88c37d213..693a1c413c 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/audit/AuditLogServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/audit/AuditLogServiceImpl.java @@ -27,7 +27,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.annotation.Bean; import org.springframework.stereotype.Service; -import org.springframework.util.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.HasName; diff --git a/dao/src/main/java/org/thingsboard/server/dao/audit/sink/ElasticsearchAuditLogSink.java b/dao/src/main/java/org/thingsboard/server/dao/audit/sink/ElasticsearchAuditLogSink.java index 4d8bc9d6ac..7ef0204565 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/audit/sink/ElasticsearchAuditLogSink.java +++ b/dao/src/main/java/org/thingsboard/server/dao/audit/sink/ElasticsearchAuditLogSink.java @@ -18,7 +18,7 @@ package org.thingsboard.server.dao.audit.sink; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ObjectNode; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.apache.http.HttpEntity; import org.apache.http.HttpHost; import org.apache.http.auth.AuthScope; diff --git a/dao/src/main/java/org/thingsboard/server/dao/event/BaseEventService.java b/dao/src/main/java/org/thingsboard/server/dao/event/BaseEventService.java index 3937bbd9c3..671f063640 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/event/BaseEventService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/event/BaseEventService.java @@ -18,7 +18,7 @@ package org.thingsboard.server.dao.event; import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.common.util.concurrent.ListenableFuture; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/AbstractAlarmEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/AbstractAlarmEntity.java index e958b8422f..a10969eb22 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/AbstractAlarmEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/AbstractAlarmEntity.java @@ -21,7 +21,7 @@ import lombok.EqualsAndHashCode; import org.hibernate.annotations.Type; import org.hibernate.annotations.TypeDef; import org.springframework.util.CollectionUtils; -import org.springframework.util.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.alarm.Alarm; import org.thingsboard.server.common.data.alarm.AlarmSeverity; diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/DashboardEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/DashboardEntity.java index ccaea5524e..cf167a8b61 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/DashboardEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/DashboardEntity.java @@ -24,7 +24,7 @@ import lombok.EqualsAndHashCode; import lombok.extern.slf4j.Slf4j; import org.hibernate.annotations.Type; import org.hibernate.annotations.TypeDef; -import org.springframework.util.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.data.Dashboard; import org.thingsboard.server.common.data.ShortCustomerInfo; import org.thingsboard.server.common.data.id.DashboardId; diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/DashboardInfoEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/DashboardInfoEntity.java index de5dd6a22c..3aef6e0fb9 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/DashboardInfoEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/DashboardInfoEntity.java @@ -21,7 +21,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.extern.slf4j.Slf4j; -import org.springframework.util.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.data.DashboardInfo; import org.thingsboard.server.common.data.ShortCustomerInfo; import org.thingsboard.server.common.data.id.DashboardId; diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/OAuth2RegistrationEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/OAuth2RegistrationEntity.java index 68b5baa9bf..59701a3ac8 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/OAuth2RegistrationEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/OAuth2RegistrationEntity.java @@ -16,7 +16,7 @@ package org.thingsboard.server.dao.model.sql; import com.fasterxml.jackson.databind.JsonNode; -import io.micrometer.core.instrument.util.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import lombok.Data; import lombok.EqualsAndHashCode; import org.hibernate.annotations.Type; diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sqlts/timescale/ts/TimescaleTsKvEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sqlts/timescale/ts/TimescaleTsKvEntity.java index 05c264a48b..88c1693e10 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sqlts/timescale/ts/TimescaleTsKvEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sqlts/timescale/ts/TimescaleTsKvEntity.java @@ -17,7 +17,7 @@ package org.thingsboard.server.dao.model.sqlts.timescale.ts; import lombok.Data; import lombok.EqualsAndHashCode; -import org.springframework.util.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.dao.model.sql.AbstractTsKvEntity; import javax.persistence.ColumnResult; diff --git a/dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2ServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2ServiceImpl.java index fd4b29817b..015f2e1101 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2ServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2ServiceImpl.java @@ -19,7 +19,7 @@ import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections.CollectionUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import org.springframework.util.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.data.BaseData; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.oauth2.MapperType; diff --git a/dao/src/main/java/org/thingsboard/server/dao/relation/BaseRelationService.java b/dao/src/main/java/org/thingsboard/server/dao/relation/BaseRelationService.java index f60920a31d..90b3c290b9 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/relation/BaseRelationService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/relation/BaseRelationService.java @@ -28,7 +28,7 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.event.TransactionalEventListener; import org.springframework.transaction.support.TransactionSynchronizationManager; -import org.springframework.util.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.cache.TbTransactionalCache; import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.TenantId; diff --git a/dao/src/main/java/org/thingsboard/server/dao/service/DataValidator.java b/dao/src/main/java/org/thingsboard/server/dao/service/DataValidator.java index 81297b3594..ecdcf9b398 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/service/DataValidator.java +++ b/dao/src/main/java/org/thingsboard/server/dao/service/DataValidator.java @@ -17,7 +17,7 @@ package org.thingsboard.server.dao.service; import com.fasterxml.jackson.databind.JsonNode; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.data.BaseData; import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.id.TenantId; diff --git a/dao/src/main/java/org/thingsboard/server/dao/service/validator/AdminSettingsDataValidator.java b/dao/src/main/java/org/thingsboard/server/dao/service/validator/AdminSettingsDataValidator.java index 8033688787..6c10a59917 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/service/validator/AdminSettingsDataValidator.java +++ b/dao/src/main/java/org/thingsboard/server/dao/service/validator/AdminSettingsDataValidator.java @@ -16,7 +16,7 @@ package org.thingsboard.server.dao.service.validator; import lombok.AllArgsConstructor; -import org.apache.commons.lang3.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.springframework.stereotype.Component; import org.thingsboard.server.common.data.AdminSettings; import org.thingsboard.server.common.data.id.TenantId; diff --git a/dao/src/main/java/org/thingsboard/server/dao/service/validator/AlarmDataValidator.java b/dao/src/main/java/org/thingsboard/server/dao/service/validator/AlarmDataValidator.java index a95f7a43aa..f9097cfcc0 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/service/validator/AlarmDataValidator.java +++ b/dao/src/main/java/org/thingsboard/server/dao/service/validator/AlarmDataValidator.java @@ -17,7 +17,7 @@ package org.thingsboard.server.dao.service.validator; import lombok.AllArgsConstructor; import org.springframework.stereotype.Component; -import org.springframework.util.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.data.alarm.Alarm; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.dao.exception.DataValidationException; diff --git a/dao/src/main/java/org/thingsboard/server/dao/service/validator/AssetDataValidator.java b/dao/src/main/java/org/thingsboard/server/dao/service/validator/AssetDataValidator.java index 1f303cc79d..68525b871f 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/service/validator/AssetDataValidator.java +++ b/dao/src/main/java/org/thingsboard/server/dao/service/validator/AssetDataValidator.java @@ -18,7 +18,7 @@ package org.thingsboard.server.dao.service.validator; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Component; -import org.springframework.util.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.data.Customer; import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.asset.Asset; diff --git a/dao/src/main/java/org/thingsboard/server/dao/service/validator/ClientRegistrationTemplateDataValidator.java b/dao/src/main/java/org/thingsboard/server/dao/service/validator/ClientRegistrationTemplateDataValidator.java index b5d0247e28..2023ec353f 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/service/validator/ClientRegistrationTemplateDataValidator.java +++ b/dao/src/main/java/org/thingsboard/server/dao/service/validator/ClientRegistrationTemplateDataValidator.java @@ -16,7 +16,7 @@ package org.thingsboard.server.dao.service.validator; import org.springframework.stereotype.Component; -import org.springframework.util.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.oauth2.OAuth2ClientRegistrationTemplate; import org.thingsboard.server.dao.exception.DataValidationException; diff --git a/dao/src/main/java/org/thingsboard/server/dao/service/validator/ComponentDescriptorDataValidator.java b/dao/src/main/java/org/thingsboard/server/dao/service/validator/ComponentDescriptorDataValidator.java index f7eceec4d5..6071d7e9be 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/service/validator/ComponentDescriptorDataValidator.java +++ b/dao/src/main/java/org/thingsboard/server/dao/service/validator/ComponentDescriptorDataValidator.java @@ -15,7 +15,7 @@ */ package org.thingsboard.server.dao.service.validator; -import org.apache.commons.lang3.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.springframework.stereotype.Component; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.plugin.ComponentDescriptor; diff --git a/dao/src/main/java/org/thingsboard/server/dao/service/validator/CustomerDataValidator.java b/dao/src/main/java/org/thingsboard/server/dao/service/validator/CustomerDataValidator.java index 9cc8d6a0de..9d356e7484 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/service/validator/CustomerDataValidator.java +++ b/dao/src/main/java/org/thingsboard/server/dao/service/validator/CustomerDataValidator.java @@ -15,7 +15,7 @@ */ package org.thingsboard.server.dao.service.validator; -import org.apache.commons.lang3.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Component; diff --git a/dao/src/main/java/org/thingsboard/server/dao/service/validator/DashboardDataValidator.java b/dao/src/main/java/org/thingsboard/server/dao/service/validator/DashboardDataValidator.java index 23b960253c..b1453c870e 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/service/validator/DashboardDataValidator.java +++ b/dao/src/main/java/org/thingsboard/server/dao/service/validator/DashboardDataValidator.java @@ -15,7 +15,7 @@ */ package org.thingsboard.server.dao.service.validator; -import org.apache.commons.lang3.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Component; diff --git a/dao/src/main/java/org/thingsboard/server/dao/service/validator/DeviceDataValidator.java b/dao/src/main/java/org/thingsboard/server/dao/service/validator/DeviceDataValidator.java index d30180a892..80c5c98862 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/service/validator/DeviceDataValidator.java +++ b/dao/src/main/java/org/thingsboard/server/dao/service/validator/DeviceDataValidator.java @@ -18,7 +18,7 @@ package org.thingsboard.server.dao.service.validator; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Component; -import org.springframework.util.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.data.Customer; import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.EntityType; diff --git a/dao/src/main/java/org/thingsboard/server/dao/service/validator/EdgeDataValidator.java b/dao/src/main/java/org/thingsboard/server/dao/service/validator/EdgeDataValidator.java index b88724f7af..e64ff15409 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/service/validator/EdgeDataValidator.java +++ b/dao/src/main/java/org/thingsboard/server/dao/service/validator/EdgeDataValidator.java @@ -17,7 +17,7 @@ package org.thingsboard.server.dao.service.validator; import lombok.AllArgsConstructor; import org.springframework.stereotype.Component; -import org.springframework.util.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.data.Customer; import org.thingsboard.server.common.data.edge.Edge; import org.thingsboard.server.common.data.id.CustomerId; diff --git a/dao/src/main/java/org/thingsboard/server/dao/service/validator/EntityViewDataValidator.java b/dao/src/main/java/org/thingsboard/server/dao/service/validator/EntityViewDataValidator.java index 7532dda195..7d47df55be 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/service/validator/EntityViewDataValidator.java +++ b/dao/src/main/java/org/thingsboard/server/dao/service/validator/EntityViewDataValidator.java @@ -16,7 +16,7 @@ package org.thingsboard.server.dao.service.validator; import lombok.AllArgsConstructor; -import org.apache.commons.lang3.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.springframework.stereotype.Component; import org.thingsboard.server.common.data.Customer; import org.thingsboard.server.common.data.EntityView; diff --git a/dao/src/main/java/org/thingsboard/server/dao/service/validator/EventDataValidator.java b/dao/src/main/java/org/thingsboard/server/dao/service/validator/EventDataValidator.java index ae7b7542a4..e43cdcc9de 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/service/validator/EventDataValidator.java +++ b/dao/src/main/java/org/thingsboard/server/dao/service/validator/EventDataValidator.java @@ -15,7 +15,7 @@ */ package org.thingsboard.server.dao.service.validator; -import org.apache.commons.lang3.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.springframework.stereotype.Component; import org.thingsboard.server.common.data.Event; import org.thingsboard.server.common.data.id.TenantId; diff --git a/dao/src/main/java/org/thingsboard/server/dao/service/validator/ResourceDataValidator.java b/dao/src/main/java/org/thingsboard/server/dao/service/validator/ResourceDataValidator.java index 49de43dba3..512fa9275b 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/service/validator/ResourceDataValidator.java +++ b/dao/src/main/java/org/thingsboard/server/dao/service/validator/ResourceDataValidator.java @@ -15,7 +15,7 @@ */ package org.thingsboard.server.dao.service.validator; -import org.apache.commons.lang3.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Component; diff --git a/dao/src/main/java/org/thingsboard/server/dao/service/validator/RuleChainDataValidator.java b/dao/src/main/java/org/thingsboard/server/dao/service/validator/RuleChainDataValidator.java index 1581a61b80..0778d039e0 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/service/validator/RuleChainDataValidator.java +++ b/dao/src/main/java/org/thingsboard/server/dao/service/validator/RuleChainDataValidator.java @@ -15,7 +15,7 @@ */ package org.thingsboard.server.dao.service.validator; -import org.apache.commons.lang3.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Component; diff --git a/dao/src/main/java/org/thingsboard/server/dao/service/validator/TenantDataValidator.java b/dao/src/main/java/org/thingsboard/server/dao/service/validator/TenantDataValidator.java index 65770aefdb..bd07c6b597 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/service/validator/TenantDataValidator.java +++ b/dao/src/main/java/org/thingsboard/server/dao/service/validator/TenantDataValidator.java @@ -15,7 +15,7 @@ */ package org.thingsboard.server.dao.service.validator; -import org.apache.commons.lang3.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.thingsboard.server.common.data.Tenant; diff --git a/dao/src/main/java/org/thingsboard/server/dao/service/validator/TenantProfileDataValidator.java b/dao/src/main/java/org/thingsboard/server/dao/service/validator/TenantProfileDataValidator.java index feab5078e6..68af5fee48 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/service/validator/TenantProfileDataValidator.java +++ b/dao/src/main/java/org/thingsboard/server/dao/service/validator/TenantProfileDataValidator.java @@ -15,7 +15,7 @@ */ package org.thingsboard.server.dao.service.validator; -import org.apache.commons.lang3.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Component; diff --git a/dao/src/main/java/org/thingsboard/server/dao/service/validator/UserCredentialsDataValidator.java b/dao/src/main/java/org/thingsboard/server/dao/service/validator/UserCredentialsDataValidator.java index 5920ad552f..111e8af55c 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/service/validator/UserCredentialsDataValidator.java +++ b/dao/src/main/java/org/thingsboard/server/dao/service/validator/UserCredentialsDataValidator.java @@ -15,7 +15,7 @@ */ package org.thingsboard.server.dao.service.validator; -import org.apache.commons.lang3.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Component; diff --git a/dao/src/main/java/org/thingsboard/server/dao/service/validator/UserDataValidator.java b/dao/src/main/java/org/thingsboard/server/dao/service/validator/UserDataValidator.java index 21e2143f1a..3e6e4900f7 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/service/validator/UserDataValidator.java +++ b/dao/src/main/java/org/thingsboard/server/dao/service/validator/UserDataValidator.java @@ -15,7 +15,7 @@ */ package org.thingsboard.server.dao.service.validator; -import org.apache.commons.lang3.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Component; diff --git a/dao/src/main/java/org/thingsboard/server/dao/service/validator/WidgetTypeDataValidator.java b/dao/src/main/java/org/thingsboard/server/dao/service/validator/WidgetTypeDataValidator.java index 25c6b5db86..3e83518941 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/service/validator/WidgetTypeDataValidator.java +++ b/dao/src/main/java/org/thingsboard/server/dao/service/validator/WidgetTypeDataValidator.java @@ -16,7 +16,7 @@ package org.thingsboard.server.dao.service.validator; import lombok.AllArgsConstructor; -import org.apache.commons.lang3.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.springframework.stereotype.Component; import org.thingsboard.server.common.data.Tenant; import org.thingsboard.server.common.data.id.TenantId; diff --git a/dao/src/main/java/org/thingsboard/server/dao/service/validator/WidgetsBundleDataValidator.java b/dao/src/main/java/org/thingsboard/server/dao/service/validator/WidgetsBundleDataValidator.java index b950a12826..1b77c63f1f 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/service/validator/WidgetsBundleDataValidator.java +++ b/dao/src/main/java/org/thingsboard/server/dao/service/validator/WidgetsBundleDataValidator.java @@ -16,7 +16,7 @@ package org.thingsboard.server.dao.service.validator; import lombok.AllArgsConstructor; -import org.apache.commons.lang3.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.springframework.stereotype.Component; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.widget.WidgetsBundle; diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/device/JpaDeviceDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/device/JpaDeviceDao.java index 8513e440b7..0430f3811f 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/device/JpaDeviceDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/device/JpaDeviceDao.java @@ -23,7 +23,7 @@ import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Transactional; -import org.springframework.util.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.DeviceInfo; import org.thingsboard.server.common.data.DeviceTransportType; diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/device/JpaDeviceProfileDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/device/JpaDeviceProfileDao.java index 07a680493f..8b3aff42e4 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/device/JpaDeviceProfileDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/device/JpaDeviceProfileDao.java @@ -15,7 +15,7 @@ */ package org.thingsboard.server.dao.sql.device; -import org.apache.commons.lang3.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Component; diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/edge/JpaBaseEdgeEventDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/edge/JpaBaseEdgeEventDao.java index 36f834b8bc..6d90ac4d2d 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/edge/JpaBaseEdgeEventDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/edge/JpaBaseEdgeEventDao.java @@ -18,7 +18,7 @@ package org.thingsboard.server.dao.sql.edge; import com.datastax.oss.driver.api.core.uuid.Uuids; import com.google.common.util.concurrent.ListenableFuture; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.data.jpa.repository.JpaRepository; diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/event/JpaBaseEventDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/event/JpaBaseEventDao.java index 2b409006d2..30019202ff 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/event/JpaBaseEventDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/event/JpaBaseEventDao.java @@ -18,7 +18,7 @@ package org.thingsboard.server.dao.sql.event; import com.datastax.oss.driver.api.core.uuid.Uuids; import com.google.common.util.concurrent.ListenableFuture; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.data.domain.PageRequest; diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/query/AlarmDataAdapter.java b/dao/src/main/java/org/thingsboard/server/dao/sql/query/AlarmDataAdapter.java index 7d660519eb..733ce25d6c 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/query/AlarmDataAdapter.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/query/AlarmDataAdapter.java @@ -18,7 +18,7 @@ package org.thingsboard.server.dao.sql.query; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import lombok.extern.slf4j.Slf4j; -import org.springframework.util.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.alarm.Alarm; import org.thingsboard.server.common.data.alarm.AlarmSeverity; diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/query/DefaultAlarmQueryRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/query/DefaultAlarmQueryRepository.java index a1be8884ff..07b597e5a2 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/query/DefaultAlarmQueryRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/query/DefaultAlarmQueryRepository.java @@ -16,7 +16,7 @@ package org.thingsboard.server.dao.sql.query; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; import org.springframework.stereotype.Repository; import org.springframework.transaction.support.TransactionTemplate; diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/query/DefaultEntityQueryRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/query/DefaultEntityQueryRepository.java index 8d6af88c59..fa8745164d 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/query/DefaultEntityQueryRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/query/DefaultEntityQueryRepository.java @@ -17,7 +17,7 @@ package org.thingsboard.server.dao.sql.query; import lombok.Getter; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.springframework.beans.factory.annotation.Value; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; import org.springframework.stereotype.Repository; diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/query/EntityKeyMapping.java b/dao/src/main/java/org/thingsboard/server/dao/sql/query/EntityKeyMapping.java index 1499b7150f..78e90b3311 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/query/EntityKeyMapping.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/query/EntityKeyMapping.java @@ -16,7 +16,7 @@ package org.thingsboard.server.dao.sql.query; import lombok.Data; -import org.apache.commons.lang3.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.data.DataConstants; import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.query.BooleanFilterPredicate; diff --git a/dao/src/main/java/org/thingsboard/server/dao/timeseries/AbstractCassandraBaseTimeseriesDao.java b/dao/src/main/java/org/thingsboard/server/dao/timeseries/AbstractCassandraBaseTimeseriesDao.java index 0b97a2874f..be960f4af8 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/timeseries/AbstractCassandraBaseTimeseriesDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/timeseries/AbstractCassandraBaseTimeseriesDao.java @@ -17,7 +17,7 @@ package org.thingsboard.server.dao.timeseries; import com.datastax.oss.driver.api.core.cql.Row; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.data.kv.BasicTsKvEntry; import org.thingsboard.server.common.data.kv.BooleanDataEntry; import org.thingsboard.server.common.data.kv.DoubleDataEntry; diff --git a/dao/src/main/java/org/thingsboard/server/dao/timeseries/BaseTimeseriesService.java b/dao/src/main/java/org/thingsboard/server/dao/timeseries/BaseTimeseriesService.java index a74f51ce9e..8254b2bee0 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/timeseries/BaseTimeseriesService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/timeseries/BaseTimeseriesService.java @@ -47,7 +47,7 @@ import java.util.Collections; import java.util.List; import java.util.stream.Collectors; -import static org.apache.commons.lang3.StringUtils.isBlank; +import static org.thingsboard.server.common.data.StringUtils.isBlank; /** * @author Andrew Shvayka diff --git a/dao/src/test/java/org/thingsboard/server/dao/service/BaseEntityServiceTest.java b/dao/src/test/java/org/thingsboard/server/dao/service/BaseEntityServiceTest.java index 808e499239..5c86799442 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/service/BaseEntityServiceTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/service/BaseEntityServiceTest.java @@ -21,7 +21,7 @@ import com.google.common.util.concurrent.ListenableFuture; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.RandomStringUtils; import org.apache.commons.lang3.RandomUtils; -import org.apache.commons.lang3.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.hamcrest.Matchers; import org.junit.After; import org.junit.Assert; diff --git a/rest-client/src/main/java/org/thingsboard/rest/client/RestClient.java b/rest-client/src/main/java/org/thingsboard/rest/client/RestClient.java index a0f1d5dfa1..67ee202331 100644 --- a/rest-client/src/main/java/org/thingsboard/rest/client/RestClient.java +++ b/rest-client/src/main/java/org/thingsboard/rest/client/RestClient.java @@ -34,7 +34,7 @@ import org.springframework.http.client.ClientHttpResponse; import org.springframework.http.client.support.HttpRequestWrapper; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; -import org.springframework.util.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.springframework.web.client.HttpClientErrorException; import org.springframework.web.client.RestTemplate; import org.thingsboard.common.util.ThingsBoardExecutors; diff --git a/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/util/TbNodeUtils.java b/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/util/TbNodeUtils.java index bc38db7fd6..940a5453b6 100644 --- a/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/util/TbNodeUtils.java +++ b/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/util/TbNodeUtils.java @@ -19,9 +19,9 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.util.CollectionUtils; -import org.springframework.util.StringUtils; import org.thingsboard.rule.engine.api.TbNodeConfiguration; import org.thingsboard.rule.engine.api.TbNodeException; +import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.msg.TbMsg; import org.thingsboard.server.common.msg.TbMsgMetaData; diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/aws/sqs/TbSqsNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/aws/sqs/TbSqsNode.java index a03d853c09..06889bd6de 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/aws/sqs/TbSqsNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/aws/sqs/TbSqsNode.java @@ -25,7 +25,7 @@ import com.amazonaws.services.sqs.model.SendMessageRequest; import com.amazonaws.services.sqs.model.SendMessageResult; import com.google.common.util.concurrent.ListenableFuture; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.rule.engine.api.RuleNode; import org.thingsboard.rule.engine.api.TbContext; import org.thingsboard.rule.engine.api.TbNode; diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/credentials/CertPemCredentials.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/credentials/CertPemCredentials.java index 3a38a286f2..528840d972 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/credentials/CertPemCredentials.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/credentials/CertPemCredentials.java @@ -28,7 +28,7 @@ import org.bouncycastle.openssl.PEMKeyPair; import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter; import org.bouncycastle.openssl.jcajce.JcePEMDecryptorProviderBuilder; import org.bouncycastle.util.encoders.Hex; -import org.springframework.util.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import javax.crypto.Cipher; import javax.crypto.EncryptedPrivateKeyInfo; diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/debug/TbMsgGeneratorNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/debug/TbMsgGeneratorNode.java index 80b319e087..32ec34ef39 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/debug/TbMsgGeneratorNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/debug/TbMsgGeneratorNode.java @@ -19,7 +19,7 @@ import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.MoreExecutors; import lombok.extern.slf4j.Slf4j; -import org.springframework.util.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.common.util.TbStopWatch; import org.thingsboard.rule.engine.api.RuleNode; import org.thingsboard.rule.engine.api.ScriptEngine; diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/kafka/TbKafkaNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/kafka/TbKafkaNode.java index 836497cced..b9c7d53b1d 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/kafka/TbKafkaNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/kafka/TbKafkaNode.java @@ -17,7 +17,7 @@ package org.thingsboard.rule.engine.kafka; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.BooleanUtils; -import org.apache.commons.lang3.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.apache.kafka.clients.producer.KafkaProducer; import org.apache.kafka.clients.producer.Producer; import org.apache.kafka.clients.producer.ProducerConfig; diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mail/TbMsgToEmailNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mail/TbMsgToEmailNode.java index 28732c53e9..fbdbb84cad 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mail/TbMsgToEmailNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mail/TbMsgToEmailNode.java @@ -19,7 +19,7 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import lombok.extern.slf4j.Slf4j; -import org.springframework.util.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.rule.engine.api.RuleNode; import org.thingsboard.rule.engine.api.TbContext; import org.thingsboard.rule.engine.api.TbEmail; diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mail/TbSendEmailNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mail/TbSendEmailNode.java index bf65dc1fc3..10281be468 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mail/TbSendEmailNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mail/TbSendEmailNode.java @@ -17,7 +17,7 @@ package org.thingsboard.rule.engine.mail; import com.fasterxml.jackson.databind.ObjectMapper; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.springframework.mail.javamail.JavaMailSenderImpl; import org.thingsboard.rule.engine.api.RuleNode; import org.thingsboard.rule.engine.api.TbContext; diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTelemetryNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTelemetryNode.java index 320502005b..4d867562d8 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTelemetryNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTelemetryNode.java @@ -25,7 +25,7 @@ import com.google.gson.JsonParseException; import lombok.Data; import lombok.NoArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.apache.commons.lang3.math.NumberUtils; import org.thingsboard.common.util.DonAsynchron; import org.thingsboard.rule.engine.api.RuleNode; diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mqtt/TbMqttNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mqtt/TbMqttNode.java index 1600f2271c..6dd632aa97 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mqtt/TbMqttNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mqtt/TbMqttNode.java @@ -20,7 +20,7 @@ import io.netty.handler.codec.mqtt.MqttQoS; import io.netty.handler.ssl.SslContext; import io.netty.util.concurrent.Future; import lombok.extern.slf4j.Slf4j; -import org.springframework.util.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.mqtt.MqttClient; import org.thingsboard.mqtt.MqttClientConfig; import org.thingsboard.mqtt.MqttConnectResult; diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mqtt/azure/TbAzureIotHubNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mqtt/azure/TbAzureIotHubNode.java index 1218518a12..80c75e08ba 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mqtt/azure/TbAzureIotHubNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mqtt/azure/TbAzureIotHubNode.java @@ -18,7 +18,7 @@ package org.thingsboard.rule.engine.mqtt.azure; import io.netty.handler.codec.mqtt.MqttVersion; import io.netty.handler.ssl.SslContext; import lombok.extern.slf4j.Slf4j; -import org.springframework.util.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.common.util.AzureIotHubUtil; import org.thingsboard.mqtt.MqttClientConfig; import org.thingsboard.rule.engine.api.RuleNode; diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/profile/AlarmState.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/profile/AlarmState.java index db41c0f6d5..81b5282aff 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/profile/AlarmState.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/profile/AlarmState.java @@ -20,7 +20,7 @@ import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.common.util.concurrent.ListenableFuture; import lombok.Data; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.common.util.DonAsynchron; import org.thingsboard.rule.engine.action.TbAlarmResult; diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/profile/DeviceState.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/profile/DeviceState.java index f0bbdfb66b..5ab5adc7fc 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/profile/DeviceState.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/profile/DeviceState.java @@ -17,7 +17,7 @@ package org.thingsboard.rule.engine.profile; import com.google.gson.JsonParser; import lombok.extern.slf4j.Slf4j; -import org.springframework.util.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.rule.engine.api.TbContext; import org.thingsboard.rule.engine.profile.state.PersistedAlarmState; import org.thingsboard.rule.engine.profile.state.PersistedDeviceState; diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rabbitmq/TbRabbitMqNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rabbitmq/TbRabbitMqNode.java index 0b3822352e..5ba55fe2d5 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rabbitmq/TbRabbitMqNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rabbitmq/TbRabbitMqNode.java @@ -22,7 +22,7 @@ import com.rabbitmq.client.Connection; import com.rabbitmq.client.ConnectionFactory; import com.rabbitmq.client.MessageProperties; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.rule.engine.api.RuleNode; import org.thingsboard.rule.engine.api.TbContext; import org.thingsboard.rule.engine.api.TbNode; diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbHttpClient.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbHttpClient.java index e035d415ed..28c937c9ce 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbHttpClient.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbHttpClient.java @@ -35,7 +35,7 @@ import org.springframework.http.HttpMethod; import org.springframework.http.ResponseEntity; import org.springframework.http.client.HttpComponentsAsyncClientHttpRequestFactory; import org.springframework.http.client.Netty4ClientHttpRequestFactory; -import org.springframework.util.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.springframework.util.concurrent.ListenableFuture; import org.springframework.util.concurrent.ListenableFutureCallback; import org.springframework.web.client.AsyncRestTemplate; diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rpc/TbSendRPCReplyNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rpc/TbSendRPCReplyNode.java index 36497df564..cdc3095443 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rpc/TbSendRPCReplyNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rpc/TbSendRPCReplyNode.java @@ -16,7 +16,7 @@ package org.thingsboard.rule.engine.rpc; import lombok.extern.slf4j.Slf4j; -import org.springframework.util.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.rule.engine.api.RuleNode; import org.thingsboard.rule.engine.api.TbContext; import org.thingsboard.rule.engine.api.TbNode; diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rpc/TbSendRPCRequestNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rpc/TbSendRPCRequestNode.java index 265475c0d9..7a1436a385 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rpc/TbSendRPCRequestNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rpc/TbSendRPCRequestNode.java @@ -21,7 +21,7 @@ import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParser; import lombok.extern.slf4j.Slf4j; -import org.springframework.util.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.rule.engine.api.RuleEngineDeviceRpcRequest; import org.thingsboard.rule.engine.api.RuleNode; import org.thingsboard.rule.engine.api.TbContext; diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rpc/TbSendRpcReplyNodeConfiguration.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rpc/TbSendRpcReplyNodeConfiguration.java index a736759f1a..1a014eb323 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rpc/TbSendRpcReplyNodeConfiguration.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rpc/TbSendRpcReplyNodeConfiguration.java @@ -16,7 +16,7 @@ package org.thingsboard.rule.engine.rpc; import lombok.Data; -import org.springframework.util.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.rule.engine.api.NodeConfiguration; import org.thingsboard.server.common.data.DataConstants; diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/TbMsgAttributesNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/TbMsgAttributesNode.java index 56e1ca8577..fb819aed90 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/TbMsgAttributesNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/TbMsgAttributesNode.java @@ -17,7 +17,7 @@ package org.thingsboard.rule.engine.telemetry; import com.google.gson.JsonParser; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.rule.engine.api.RuleNode; import org.thingsboard.rule.engine.api.TbContext; import org.thingsboard.rule.engine.api.TbNode; diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/TbMsgTimeseriesNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/TbMsgTimeseriesNode.java index 22d9d1ac07..4a44d9f7b1 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/TbMsgTimeseriesNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/TbMsgTimeseriesNode.java @@ -17,7 +17,7 @@ package org.thingsboard.rule.engine.telemetry; import com.google.gson.JsonParser; import lombok.extern.slf4j.Slf4j; -import org.springframework.util.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.rule.engine.api.RuleNode; import org.thingsboard.rule.engine.api.TbContext; import org.thingsboard.rule.engine.api.TbNode; diff --git a/tools/src/main/java/org/thingsboard/client/tools/migrator/DictionaryParser.java b/tools/src/main/java/org/thingsboard/client/tools/migrator/DictionaryParser.java index b6a1be84b1..2feaf7cd77 100644 --- a/tools/src/main/java/org/thingsboard/client/tools/migrator/DictionaryParser.java +++ b/tools/src/main/java/org/thingsboard/client/tools/migrator/DictionaryParser.java @@ -17,7 +17,7 @@ package org.thingsboard.client.tools.migrator; import org.apache.commons.io.FileUtils; import org.apache.commons.io.LineIterator; -import org.apache.commons.lang3.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import java.io.File; import java.io.IOException; diff --git a/tools/src/main/java/org/thingsboard/client/tools/migrator/PgCaMigrator.java b/tools/src/main/java/org/thingsboard/client/tools/migrator/PgCaMigrator.java index 695356ed2d..77fc0837ed 100644 --- a/tools/src/main/java/org/thingsboard/client/tools/migrator/PgCaMigrator.java +++ b/tools/src/main/java/org/thingsboard/client/tools/migrator/PgCaMigrator.java @@ -19,7 +19,7 @@ import com.google.common.collect.Lists; import org.apache.cassandra.io.sstable.CQLSSTableWriter; import org.apache.commons.io.FileUtils; import org.apache.commons.io.LineIterator; -import org.apache.commons.lang3.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.apache.commons.lang3.math.NumberUtils; import java.io.File; diff --git a/tools/src/main/java/org/thingsboard/client/tools/migrator/RelatedEntitiesParser.java b/tools/src/main/java/org/thingsboard/client/tools/migrator/RelatedEntitiesParser.java index b0f786a2d3..c84020b6b5 100644 --- a/tools/src/main/java/org/thingsboard/client/tools/migrator/RelatedEntitiesParser.java +++ b/tools/src/main/java/org/thingsboard/client/tools/migrator/RelatedEntitiesParser.java @@ -17,7 +17,7 @@ package org.thingsboard.client.tools.migrator; import org.apache.commons.io.FileUtils; import org.apache.commons.io.LineIterator; -import org.apache.commons.lang3.StringUtils; +import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.data.EntityType; import java.io.File; From bc88babd1120db4a43e41212cf8cfa65d8edb7e1 Mon Sep 17 00:00:00 2001 From: thingsboard Date: Tue, 12 Jul 2022 12:29:27 +0300 Subject: [PATCH 005/108] fix pr comments --- .../server/service/action/EntityActionService.java | 7 ++++++- common/data/pom.xml | 10 ---------- .../thingsboard/server/common/data/StringUtils.java | 8 ++------ .../server/transport/mqtt/MqttTransportHandler.java | 2 +- 4 files changed, 9 insertions(+), 18 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/action/EntityActionService.java b/application/src/main/java/org/thingsboard/server/service/action/EntityActionService.java index 2f18fb56c8..e1e7ffbb55 100644 --- a/application/src/main/java/org/thingsboard/server/service/action/EntityActionService.java +++ b/application/src/main/java/org/thingsboard/server/service/action/EntityActionService.java @@ -23,7 +23,12 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.thingsboard.server.cluster.TbClusterService; -import org.thingsboard.server.common.data.*; +import org.thingsboard.server.common.data.DataConstants; +import org.thingsboard.server.common.data.EntityType; +import org.thingsboard.server.common.data.HasName; +import org.thingsboard.server.common.data.HasTenantId; +import org.thingsboard.server.common.data.User; +import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.data.audit.ActionType; import org.thingsboard.server.common.data.edge.EdgeEventActionType; import org.thingsboard.server.common.data.id.CustomerId; diff --git a/common/data/pom.xml b/common/data/pom.xml index 50755115a0..539dd0d9e3 100644 --- a/common/data/pom.xml +++ b/common/data/pom.xml @@ -108,16 +108,6 @@ de.ruedigermoeller fst - - org.eclipse.leshan - leshan-core - - - com.amazonaws - aws-java-sdk-core - 1.11.747 - compile - diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/StringUtils.java b/common/data/src/main/java/org/thingsboard/server/common/data/StringUtils.java index 4b916df30e..77e4e7656c 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/StringUtils.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/StringUtils.java @@ -17,13 +17,9 @@ package org.thingsboard.server.common.data; import com.google.common.base.Splitter; -import java.nio.charset.Charset; - import static org.apache.commons.lang3.StringUtils.repeat; public class StringUtils { - public static Charset UTF8 = com.amazonaws.util.StringUtils.UTF8; - public static final String EMPTY = ""; public static final int INDEX_NOT_FOUND = -1; @@ -101,8 +97,8 @@ public class StringUtils { return Splitter.fixedLength(maxPartSize).split(value); } - public static boolean equalsIgnoreCase(String value, String aTrue) { - return org.eclipse.leshan.core.util.StringUtils.equalsIgnoreCase(value, aTrue); + public static boolean equalsIgnoreCase(String str1, String str2) { + return str1 == null ? str2 == null : str1.equalsIgnoreCase(str2); } public static String join(String[] keyArray, String lwm2mSeparatorPath) { diff --git a/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttTransportHandler.java b/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttTransportHandler.java index b83cb4aa44..ad07c9f9a4 100644 --- a/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttTransportHandler.java +++ b/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttTransportHandler.java @@ -89,7 +89,7 @@ import java.util.concurrent.TimeUnit; import java.util.regex.Matcher; import java.util.regex.Pattern; -import static org.thingsboard.server.common.data.StringUtils.UTF8; +import static com.amazonaws.util.StringUtils.UTF8; import static io.netty.handler.codec.mqtt.MqttConnectReturnCode.CONNECTION_ACCEPTED; import static io.netty.handler.codec.mqtt.MqttConnectReturnCode.CONNECTION_REFUSED_NOT_AUTHORIZED; import static io.netty.handler.codec.mqtt.MqttMessageType.CONNACK; From 95faab9c2e78df45c9a6b233d1bb78a44886f03c Mon Sep 17 00:00:00 2001 From: thingsboard Date: Fri, 15 Jul 2022 12:54:41 +0300 Subject: [PATCH 006/108] fix pr comments --- .../java/org/thingsboard/server/common/data/StringUtils.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/StringUtils.java b/common/data/src/main/java/org/thingsboard/server/common/data/StringUtils.java index 77e4e7656c..e0b42d68a5 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/StringUtils.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/StringUtils.java @@ -121,7 +121,7 @@ public class StringUtils { return org.springframework.util.StringUtils.hasLength(str); } - public static boolean isNoneBlank(String str) { + public static boolean isNoneBlank(String... str) { return org.apache.commons.lang3.StringUtils.isNoneBlank(str); } From b08fd39bdc050774577e8d2139d9e1ff1c530518 Mon Sep 17 00:00:00 2001 From: Yuriy Lytvynchuk Date: Mon, 18 Jul 2022 15:05:47 +0300 Subject: [PATCH 007/108] fix_convertValue in EntityDataAdapter --- .../thingsboard/server/dao/sql/query/EntityDataAdapter.java | 5 ++++- .../server/dao/sql/query/EntityDataAdapterTest.java | 3 ++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/query/EntityDataAdapter.java b/dao/src/main/java/org/thingsboard/server/dao/sql/query/EntityDataAdapter.java index 49640c1640..c30ecdd9a2 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/query/EntityDataAdapter.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/query/EntityDataAdapter.java @@ -81,7 +81,10 @@ public class EntityDataAdapter { if (value != null) { String strVal = value.toString(); // check number - if (strVal.length() > 0 && NumberUtils.isParsable(strVal)) { + if (NumberUtils.isParsable(strVal)) { + if (strVal.startsWith("0") && !strVal.startsWith("0.")) { + return strVal; + } try { long longVal = Long.parseLong(strVal); return Long.toString(longVal); diff --git a/dao/src/test/java/org/thingsboard/server/dao/sql/query/EntityDataAdapterTest.java b/dao/src/test/java/org/thingsboard/server/dao/sql/query/EntityDataAdapterTest.java index 8965358e63..f140d66c83 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/sql/query/EntityDataAdapterTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/sql/query/EntityDataAdapterTest.java @@ -25,5 +25,6 @@ public class EntityDataAdapterTest { public void testConvertValue() { assertThat(EntityDataAdapter.convertValue("500")).isEqualTo("500"); assertThat(EntityDataAdapter.convertValue("500D")).isEqualTo("500D"); //do not convert to Double !!! + assertThat(EntityDataAdapter.convertValue("0101010521130565")).isEqualTo("0101010521130565"); } -} +} \ No newline at end of file From ee95dc20df958a67d3f60b8e72d48f01f853d721 Mon Sep 17 00:00:00 2001 From: Yuriy Lytvynchuk Date: Mon, 18 Jul 2022 15:13:21 +0300 Subject: [PATCH 008/108] fix_convertValue in EntityDataAdapter --- .../thingsboard/server/dao/sql/query/EntityDataAdapterTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dao/src/test/java/org/thingsboard/server/dao/sql/query/EntityDataAdapterTest.java b/dao/src/test/java/org/thingsboard/server/dao/sql/query/EntityDataAdapterTest.java index f140d66c83..6d052db1d1 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/sql/query/EntityDataAdapterTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/sql/query/EntityDataAdapterTest.java @@ -27,4 +27,4 @@ public class EntityDataAdapterTest { assertThat(EntityDataAdapter.convertValue("500D")).isEqualTo("500D"); //do not convert to Double !!! assertThat(EntityDataAdapter.convertValue("0101010521130565")).isEqualTo("0101010521130565"); } -} \ No newline at end of file +} From c6be0aeba298322be729953988bc81d474b3dc9b Mon Sep 17 00:00:00 2001 From: Vladyslav_Prykhodko Date: Wed, 20 Jul 2022 17:12:39 +0300 Subject: [PATCH 009/108] UI: Improvement of mobile view in widgets setting --- ...larms-table-widget-settings.component.html | 4 +-- ...ities-table-widget-settings.component.html | 8 +++--- .../cards/label-widget-label.component.html | 2 +- ...eries-table-widget-settings.component.html | 4 +-- ...ghnut-chart-widget-settings.component.html | 2 +- .../chart/flot-key-settings.component.html | 10 +++---- .../flot-latest-key-settings.component.html | 2 +- .../flot-pie-widget-settings.component.html | 4 +-- .../chart/flot-threshold.component.html | 2 +- .../chart/flot-widget-settings.component.html | 12 +++++---- .../chart/label-data-key.component.html | 2 +- .../common/value-source.component.html | 3 ++- .../common/widget-font.component.html | 6 ++--- ...nob-control-widget-settings.component.html | 2 +- ...stent-table-widget-settings.component.html | 4 +-- .../control/rpc-button-style.component.html | 2 +- ...lide-toggle-widget-settings.component.html | 2 +- ...gue-compass-widget-settings.component.html | 6 ++--- ...logue-gauge-widget-settings.component.html | 22 ++++++++-------- ...gital-gauge-widget-settings.component.html | 4 +-- .../gauge/gauge-highlight.component.html | 2 +- .../settings/gpio/gpio-item.component.html | 4 +-- .../datakey-select-option.component.html | 2 +- ...amera-input-widget-settings.component.html | 4 +-- ...-attribute-general-settings.component.html | 12 ++++----- ...n-attribute-widget-settings.component.html | 2 +- ...e-attribute-widget-settings.component.html | 2 +- ...r-attribute-widget-settings.component.html | 2 +- ...n-attribute-widget-settings.component.html | 8 +++--- ...n-attribute-widget-settings.component.html | 6 ++--- ...ple-attributes-key-settings.component.html | 9 ++++--- ...-attributes-widget-settings.component.html | 6 ++--- ...g-attribute-widget-settings.component.html | 2 +- .../map/circle-settings.component.html | 4 +-- .../map/common-map-settings.component.html | 6 ++--- ...image-map-provider-settings.component.html | 2 +- .../map/map-editor-settings.component.html | 4 +-- .../marker-clustering-settings.component.html | 14 +++++----- .../map/markers-settings.component.html | 4 +-- .../map/polygon-settings.component.html | 4 +-- ...p-animation-common-settings.component.html | 4 +-- ...rip-animation-path-settings.component.html | 8 +++--- ...ip-animation-point-settings.component.html | 2 +- .../widget/lib/settings/widget-settings.scss | 26 ++++++++++++++++++- 44 files changed, 135 insertions(+), 107 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/alarm/alarms-table-widget-settings.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/alarm/alarms-table-widget-settings.component.html index 3b5516c26c..5fc8104a80 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/alarm/alarms-table-widget-settings.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/alarm/alarms-table-widget-settings.component.html @@ -22,7 +22,7 @@ widgets.table.alarms-table-title -
+
{{ 'widgets.table.enable-alarms-selection' | translate }} @@ -67,7 +67,7 @@ {{ 'widgets.table.allow-alarms-clear' | translate }} -
+
{{ 'widgets.table.display-pagination' | translate }} diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/entities-table-widget-settings.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/entities-table-widget-settings.component.html index e58f083bea..c84a87deac 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/entities-table-widget-settings.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/entities-table-widget-settings.component.html @@ -22,7 +22,7 @@ widgets.table.entities-table-title -
+
{{ 'widgets.table.enable-search' | translate }} @@ -52,7 +52,7 @@
-
+
{{ 'widgets.table.display-entity-name' | translate }} @@ -61,7 +61,7 @@
-
+
{{ 'widgets.table.display-entity-label' | translate }} @@ -73,7 +73,7 @@ {{ 'widgets.table.display-entity-type' | translate }} -
+
{{ 'widgets.table.display-pagination' | translate }} diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/label-widget-label.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/label-widget-label.component.html index 9aa9fcc68c..bbc3e1c090 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/label-widget-label.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/label-widget-label.component.html @@ -47,7 +47,7 @@
widgets.label-widget.label-position -
+
widgets.label-widget.x-pos diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/timeseries-table-widget-settings.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/timeseries-table-widget-settings.component.html index c151a97402..a1ba27ce27 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/timeseries-table-widget-settings.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/timeseries-table-widget-settings.component.html @@ -18,7 +18,7 @@
widgets.table.common-table-settings -
+
{{ 'widgets.table.enable-search' | translate }} @@ -51,7 +51,7 @@ {{ 'widgets.table.display-milliseconds' | translate }} -
+
{{ 'widgets.table.display-pagination' | translate }} diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/doughnut-chart-widget-settings.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/doughnut-chart-widget-settings.component.html index 8a25d692c5..c3a20ce8f0 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/doughnut-chart-widget-settings.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/doughnut-chart-widget-settings.component.html @@ -24,7 +24,7 @@
widgets.chart.border-settings -
+
widgets.chart.border-width diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-key-settings.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-key-settings.component.html index 9aec9b535f..05879cb124 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-key-settings.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-key-settings.component.html @@ -46,7 +46,7 @@ -
+
widgets.chart.line-width @@ -74,7 +74,7 @@
-
+
widgets.chart.points-line-width @@ -137,7 +137,7 @@ widgets.chart.axis-title -
+
widgets.chart.min-scale-value @@ -160,7 +160,7 @@
widgets.chart.yaxis-tick-labels-settings -
+
widgets.chart.tick-step-size @@ -222,7 +222,7 @@ -
+
widgets.chart.comparison-values-label diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-latest-key-settings.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-latest-key-settings.component.html index b5b9009bd6..d2589515ca 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-latest-key-settings.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-latest-key-settings.component.html @@ -31,7 +31,7 @@ -
+
widgets.chart.threshold-line-width diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-pie-widget-settings.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-pie-widget-settings.component.html index 00f9573020..f03125303a 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-pie-widget-settings.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-pie-widget-settings.component.html @@ -18,7 +18,7 @@
widgets.chart.common-pie-settings -
+
widgets.chart.radius @@ -41,7 +41,7 @@
widgets.chart.stroke-settings -
+
widgets.chart.width-pixels diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-threshold.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-threshold.component.html index 46278cc45e..24d98d9619 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-threshold.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-threshold.component.html @@ -41,7 +41,7 @@
-
+
widgets.chart.line-width diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-widget-settings.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-widget-settings.component.html index 3ecc56b602..beebf38268 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-widget-settings.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-widget-settings.component.html @@ -21,7 +21,8 @@ {{ 'widgets.chart.enable-stacking-mode' | translate }} -
+
widgets.chart.line-shadow-size @@ -30,7 +31,8 @@ {{ 'widgets.chart.display-smooth-lines' | translate }}
-
+
widgets.chart.default-bar-width @@ -50,7 +52,7 @@
-
+
widgets.chart.default-font-size @@ -166,7 +168,7 @@ widgets.chart.axis-title -
+
widgets.chart.min-scale-value @@ -196,7 +198,7 @@ icon="format_color_fill" label="{{ 'widgets.chart.ticks-color' | translate }}" openOnInput colorClearButton> -
+
widgets.chart.tick-step-size diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/label-data-key.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/label-data-key.component.html index 50dc16d6fb..759f18ba6b 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/label-data-key.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/label-data-key.component.html @@ -37,7 +37,7 @@
-
+
widgets.chart.key-name diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/value-source.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/value-source.component.html index d4e1e669f6..bc590c3ce2 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/value-source.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/value-source.component.html @@ -31,7 +31,8 @@ widgets.value-source.value -
+
{{ 'widgets.value-source.source-entity-alias' | translate }}
-
+
widgets.widget-font.font-family @@ -26,7 +26,7 @@
-
+
widgets.widget-font.font-style @@ -68,7 +68,7 @@
-
+
widgets.rpc.initial-value -
+
widgets.rpc.min-value diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/persistent-table-widget-settings.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/persistent-table-widget-settings.component.html index 7961dddf1f..47b3ef545d 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/persistent-table-widget-settings.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/persistent-table-widget-settings.component.html @@ -18,7 +18,7 @@
widgets.persistent-table.general-settings -
+
{{ 'widgets.persistent-table.enable-filter' | translate }} @@ -43,7 +43,7 @@ {{ 'widgets.persistent-table.allow-delete-request' | translate }} -
+
{{ 'widgets.table.display-pagination' | translate }} diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/rpc-button-style.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/rpc-button-style.component.html index 1f027eb8b2..a8153c68fe 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/rpc-button-style.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/rpc-button-style.component.html @@ -24,7 +24,7 @@ {{ 'widgets.rpc.button-primary' | translate }} -
+
widgets.rpc.slide-toggle-label -
+
widgets.rpc.label-position diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/gauge/analogue-compass-widget-settings.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/gauge/analogue-compass-widget-settings.component.html index 3311c4d4e7..d2f53cbaa7 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/gauge/analogue-compass-widget-settings.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/gauge/analogue-compass-widget-settings.component.html @@ -42,7 +42,7 @@ icon="format_color_fill" label="{{ 'widgets.gauge.major-ticks-color' | translate }}" openOnInput colorClearButton> -
+
widgets.gauge.minor-ticks-count @@ -71,7 +71,7 @@ {{ 'widgets.gauge.show-plate-border' | translate }} -
+
widgets.gauge.needle-circle-size -
+
widgets.gauge.ticks-settings -
+
widgets.gauge.min-value @@ -41,7 +41,7 @@
-
+
widgets.gauge.major-ticks-count @@ -52,7 +52,7 @@ label="{{ 'widgets.gauge.major-ticks-color' | translate }}" openOnInput colorClearButton>
-
+
widgets.gauge.minor-ticks-count @@ -127,7 +127,7 @@ widgets.gauge.value-font
-
+
-
+
widgets.gauge.needle-settings -
+
-
+
widgets.gauge.radial-gauge-settings -
+
widgets.gauge.start-ticks-angle @@ -314,7 +314,7 @@
widgets.gauge.linear-gauge-settings -
+
widgets.gauge.bar-stroke-width @@ -325,7 +325,7 @@ label="{{ 'widgets.gauge.bar-stroke-color' | translate }}" openOnInput colorClearButton>
-
+
-
+
widgets.gauge.common-settings -
+
widgets.gauge.min-value @@ -65,7 +65,7 @@ widgets.gauge.neon-glow-brightness -
+
widgets.gauge.stripes-thickness diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/gauge/gauge-highlight.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/gauge/gauge-highlight.component.html index 13c6f6f7ef..a1ca29c6cf 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/gauge/gauge-highlight.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/gauge/gauge-highlight.component.html @@ -40,7 +40,7 @@
-
+
widgets.gauge.highlight-from diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/gpio/gpio-item.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/gpio/gpio-item.component.html index 9ebbdeefd9..f46ba5cb57 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/gpio/gpio-item.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/gpio/gpio-item.component.html @@ -40,7 +40,7 @@
-
+
widgets.gpio.pin @@ -50,7 +50,7 @@
-
+
widgets.gpio.row diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/datakey-select-option.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/datakey-select-option.component.html index 68a1a6c5dc..aa440982ab 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/datakey-select-option.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/datakey-select-option.component.html @@ -37,7 +37,7 @@
-
+
widgets.input-widgets.option-value diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/photo-camera-input-widget-settings.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/photo-camera-input-widget-settings.component.html index d838c59bf7..7377746bf0 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/photo-camera-input-widget-settings.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/photo-camera-input-widget-settings.component.html @@ -25,7 +25,7 @@
widgets.input-widgets.image-settings -
+
widgets.input-widgets.image-format @@ -45,7 +45,7 @@
-
+
widgets.input-widgets.max-image-width diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/update-attribute-general-settings.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/update-attribute-general-settings.component.html index 14b63d2f14..7b2c9bdcd1 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/update-attribute-general-settings.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/update-attribute-general-settings.component.html @@ -22,20 +22,20 @@ widgets.input-widgets.widget-title -
- +
+ {{ 'widgets.input-widgets.show-label' | translate }} - + widgets.input-widgets.label
-
- +
+ {{ 'widgets.input-widgets.required' | translate }} - + widgets.input-widgets.required-error-message diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/update-boolean-attribute-widget-settings.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/update-boolean-attribute-widget-settings.component.html index d47e0a0d73..b9e7a208dd 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/update-boolean-attribute-widget-settings.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/update-boolean-attribute-widget-settings.component.html @@ -28,7 +28,7 @@
widgets.input-widgets.checkbox-settings -
+
widgets.input-widgets.true-label diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/update-double-attribute-widget-settings.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/update-double-attribute-widget-settings.component.html index 8f5b543e41..be0c4a2b3b 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/update-double-attribute-widget-settings.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/update-double-attribute-widget-settings.component.html @@ -22,7 +22,7 @@
widgets.input-widgets.double-field-settings -
+
widgets.input-widgets.min-value diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/update-integer-attribute-widget-settings.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/update-integer-attribute-widget-settings.component.html index 0e5c1deccd..f28f055995 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/update-integer-attribute-widget-settings.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/update-integer-attribute-widget-settings.component.html @@ -22,7 +22,7 @@
widgets.input-widgets.integer-field-settings -
+
widgets.input-widgets.min-value diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/update-json-attribute-widget-settings.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/update-json-attribute-widget-settings.component.html index cd967cff33..fd76c980ac 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/update-json-attribute-widget-settings.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/update-json-attribute-widget-settings.component.html @@ -22,11 +22,11 @@ widgets.input-widgets.widget-title -
- +
+ {{ 'widgets.input-widgets.show-label' | translate }} - + widgets.input-widgets.label @@ -37,7 +37,7 @@
widgets.input-widgets.attribute-settings -
+
widgets.input-widgets.widget-mode diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/update-location-attribute-widget-settings.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/update-location-attribute-widget-settings.component.html index 5afb4cfc9d..22270a861f 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/update-location-attribute-widget-settings.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/update-location-attribute-widget-settings.component.html @@ -25,7 +25,7 @@ {{ 'widgets.input-widgets.show-result-message' | translate }} -
+
widgets.input-widgets.latitude-key-name @@ -47,7 +47,7 @@ {{ 'widgets.input-widgets.show-label' | translate }} -
+
widgets.input-widgets.latitude-label @@ -68,7 +68,7 @@ -
+
{{ 'widgets.input-widgets.latitude-field-required' | translate }} diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/update-multiple-attributes-key-settings.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/update-multiple-attributes-key-settings.component.html index 2f47998fba..22823ba778 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/update-multiple-attributes-key-settings.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/update-multiple-attributes-key-settings.component.html @@ -21,7 +21,7 @@
widgets.input-widgets.general-settings -
+
widgets.input-widgets.datakey-type @@ -72,7 +72,7 @@ {{ 'widgets.input-widgets.value-is-required' | translate }} -
+
widgets.input-widgets.ability-to-edit-attribute @@ -140,7 +140,7 @@ (updateMultipleAttributesKeySettingsForm.get('dataKeyValueType').value === 'integer' || updateMultipleAttributesKeySettingsForm.get('dataKeyValueType').value === 'double')" class="fields-group"> widgets.input-widgets.numeric-field-settings -
+
widgets.input-widgets.step-interval @@ -162,7 +162,8 @@
+ updateMultipleAttributesKeySettingsForm.get('dataKeyValueType').value === 'double'" + class="row-fill" fxLayout="row" fxLayoutGap="8px"> widgets.input-widgets.min-value-error-message diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/update-multiple-attributes-widget-settings.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/update-multiple-attributes-widget-settings.component.html index 327879ed03..188a392718 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/update-multiple-attributes-widget-settings.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/update-multiple-attributes-widget-settings.component.html @@ -45,7 +45,7 @@ {{ 'widgets.input-widgets.update-all-values' | translate }} -
+
widgets.input-widgets.save-button-label @@ -61,7 +61,7 @@
widgets.input-widgets.group-settings -
+
{{ 'widgets.input-widgets.show-group-title' | translate }} @@ -73,7 +73,7 @@
widgets.input-widgets.fields-alignment -
+
widgets.input-widgets.fields-alignment diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/update-string-attribute-widget-settings.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/update-string-attribute-widget-settings.component.html index f80d319dab..a282117cab 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/update-string-attribute-widget-settings.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/input/update-string-attribute-widget-settings.component.html @@ -22,7 +22,7 @@
widgets.input-widgets.text-field-settings -
+
widgets.input-widgets.min-length diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/circle-settings.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/circle-settings.component.html index 3f480cc347..827fb44129 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/circle-settings.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/circle-settings.component.html @@ -119,7 +119,7 @@
widgets.maps.circle-fill-color -
+
widgets.maps.circle-stroke -
+
widgets.maps.common-map-settings -
+
- + widget-config.advanced-settings @@ -65,7 +65,7 @@
-
+
{{ 'widgets.maps.disable-scroll-zooming' | translate }} diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/image-map-provider-settings.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/image-map-provider-settings.component.html index a8c5318142..3c30bba518 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/image-map-provider-settings.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/image-map-provider-settings.component.html @@ -21,7 +21,7 @@
widgets.maps.image-map-background-from-entity-attribute -
+
widgets.maps.image-url-source-entity-alias
widgets.maps.editor-settings - + {{ 'widgets.maps.enable-snapping' | translate }} - + {{ 'widgets.maps.init-draggable-mode' | translate }} diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/marker-clustering-settings.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/marker-clustering-settings.component.html index 9ceb172090..f0dd8e50c5 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/marker-clustering-settings.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/marker-clustering-settings.component.html @@ -34,7 +34,7 @@ {{ 'widgets.maps.zoom-on-cluster-click' | translate }} -
+
widgets.maps.max-cluster-zoom @@ -44,23 +44,23 @@
-
- +
+ {{ 'widgets.maps.cluster-zoom-animation' | translate }} - + {{ 'widgets.maps.show-markers-bounds-on-cluster-mouse-over' | translate }}
- + {{ 'widgets.maps.spiderfy-max-zoom-level' | translate }}
widgets.maps.load-optimization - + {{ 'widgets.maps.cluster-chunked-loading' | translate }} - + {{ 'widgets.maps.cluster-markers-lazy-load' | translate }}
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/markers-settings.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/markers-settings.component.html index ea955f5f7f..ed6c29d9cb 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/markers-settings.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/markers-settings.component.html @@ -18,7 +18,7 @@
widgets.maps.markers-settings -
+
widgets.maps.marker-offset-x @@ -113,7 +113,7 @@ functionTitle="{{ 'widgets.maps.tooltip-function' | translate }}" helpId="widget/lib/map/tooltip_fn"> -
+
widgets.maps.tooltip-offset-x diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/polygon-settings.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/polygon-settings.component.html index 8f3f74b1ff..e1553b2615 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/polygon-settings.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/polygon-settings.component.html @@ -119,7 +119,7 @@
widgets.maps.polygon-color -
+
widgets.maps.polygon-stroke -
+
widgets.maps.normalization-step -
+
-
+
widgets.maps.path-settings -
+
-
+
widgets.maps.decorator-symbol @@ -84,7 +84,7 @@
-
+
{{ 'widgets.maps.use-path-decorator-custom-color' | translate }} @@ -95,7 +95,7 @@ label="{{ 'widgets.maps.decorator-custom-color' | translate }}" openOnInput colorClearButton>
-
+
widgets.maps.decorator-offset diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/trip-animation-point-settings.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/trip-animation-point-settings.component.html index e48c690823..efae78727b 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/trip-animation-point-settings.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/trip-animation-point-settings.component.html @@ -31,7 +31,7 @@ -
+
Date: Thu, 21 Jul 2022 13:07:15 +0300 Subject: [PATCH 010/108] Rate limits added tenant entity version/load --- ...enant-profile-configuration.component.html | 20 ++++++------------- ...-tenant-profile-configuration.component.ts | 4 ++-- .../rate-limits-details-dialog.component.html | 4 ++-- .../rate-limits-list.component.html | 7 +++++++ .../rate-limits-list.component.scss | 12 +++++------ .../rate-limits/rate-limits.component.html | 13 ++++++------ .../rate-limits/rate-limits.component.scss | 4 ++++ .../app/shared/models/rate-limits.models.ts | 8 ++++++++ .../assets/locale/locale.constant-en_US.json | 6 ++++++ 9 files changed, 47 insertions(+), 31 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/profile/tenant/default-tenant-profile-configuration.component.html b/ui-ngx/src/app/modules/home/components/profile/tenant/default-tenant-profile-configuration.component.html index 5484aaed28..34015f71ad 100644 --- a/ui-ngx/src/app/modules/home/components/profile/tenant/default-tenant-profile-configuration.component.html +++ b/ui-ngx/src/app/modules/home/components/profile/tenant/default-tenant-profile-configuration.component.html @@ -469,20 +469,12 @@
- - tenant-profile.tenant-entity-export-rate-limit - - - - tenant-profile.tenant-entity-import-rate-limit - - - + + + +
diff --git a/ui-ngx/src/app/modules/home/components/profile/tenant/default-tenant-profile-configuration.component.ts b/ui-ngx/src/app/modules/home/components/profile/tenant/default-tenant-profile-configuration.component.ts index ac2702ca43..5652f7dd71 100644 --- a/ui-ngx/src/app/modules/home/components/profile/tenant/default-tenant-profile-configuration.component.ts +++ b/ui-ngx/src/app/modules/home/components/profile/tenant/default-tenant-profile-configuration.component.ts @@ -71,8 +71,8 @@ export class DefaultTenantProfileConfigurationComponent implements ControlValueA transportDeviceMsgRateLimit: [null, [Validators.pattern(this.rateLimitsPattern)]], transportDeviceTelemetryMsgRateLimit: [null, [Validators.pattern(this.rateLimitsPattern)]], transportDeviceTelemetryDataPointsRateLimit: [null, [Validators.pattern(this.rateLimitsPattern)]], - tenantEntityExportRateLimit: [null, []], - tenantEntityImportRateLimit: [null, []], + tenantEntityExportRateLimit: [null, [Validators.pattern(this.rateLimitsPattern)]], + tenantEntityImportRateLimit: [null, [Validators.pattern(this.rateLimitsPattern)]], maxTransportMessages: [null, [Validators.required, Validators.min(0)]], maxTransportDataPoints: [null, [Validators.required, Validators.min(0)]], maxREExecutions: [null, [Validators.required, Validators.min(0)]], diff --git a/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-details-dialog.component.html b/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-details-dialog.component.html index 911b44ecd8..751ffe0e2c 100644 --- a/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-details-dialog.component.html +++ b/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-details-dialog.component.html @@ -15,9 +15,9 @@ limitations under the License. --> -
+ -

{{ title }}

+

{{ title | translate }}

-
- -
+ diff --git a/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits.component.scss b/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits.component.scss index 6d45b33b73..1d7e817839 100644 --- a/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits.component.scss +++ b/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits.component.scss @@ -28,4 +28,8 @@ font-size: 12px; } } + + .tb-rate-limits-button { + margin-top: 0.5em; + } } diff --git a/ui-ngx/src/app/shared/models/rate-limits.models.ts b/ui-ngx/src/app/shared/models/rate-limits.models.ts index e6b4218773..ffde8a3c87 100644 --- a/ui-ngx/src/app/shared/models/rate-limits.models.ts +++ b/ui-ngx/src/app/shared/models/rate-limits.models.ts @@ -32,6 +32,8 @@ export enum RateLimitsType { CUSTOMER_SERVER_REST_LIMITS_CONFIGURATION = 'CUSTOMER_SERVER_REST_LIMITS_CONFIGURATION', WS_UPDATE_PER_SESSION_RATE_LIMIT = 'WS_UPDATE_PER_SESSION_RATE_LIMIT', CASSANDRA_QUERY_TENANT_RATE_LIMITS_CONFIGURATION = 'CASSANDRA_QUERY_TENANT_RATE_LIMITS_CONFIGURATION', + TENANT_ENTITY_EXPORT_RATE_LIMIT = 'TENANT_ENTITY_EXPORT_RATE_LIMIT', + TENANT_ENTITY_IMPORT_RATE_LIMIT = 'TENANT_ENTITY_IMPORT_RATE_LIMIT' } export const rateLimitLabelTranslationMap = new Map( @@ -46,6 +48,8 @@ export const rateLimitLabelTranslationMap = new Map( [RateLimitsType.CUSTOMER_SERVER_REST_LIMITS_CONFIGURATION, 'tenant-profile.customer-rest-limits'], [RateLimitsType.WS_UPDATE_PER_SESSION_RATE_LIMIT, 'tenant-profile.ws-limit-updates-per-session'], [RateLimitsType.CASSANDRA_QUERY_TENANT_RATE_LIMITS_CONFIGURATION, 'tenant-profile.cassandra-tenant-limits-configuration'], + [RateLimitsType.TENANT_ENTITY_EXPORT_RATE_LIMIT, 'tenant-profile.tenant-entity-export-rate-limit'], + [RateLimitsType.TENANT_ENTITY_IMPORT_RATE_LIMIT, 'tenant-profile.tenant-entity-import-rate-limit'], ] ); @@ -61,6 +65,8 @@ export const editRateLimitTranslationMap = new Map( [RateLimitsType.CUSTOMER_SERVER_REST_LIMITS_CONFIGURATION, 'tenant-profile.rate-limits.edit-customer-rest-limits-title'], [RateLimitsType.WS_UPDATE_PER_SESSION_RATE_LIMIT, 'tenant-profile.rate-limits.edit-ws-limit-updates-per-session-title'], [RateLimitsType.CASSANDRA_QUERY_TENANT_RATE_LIMITS_CONFIGURATION, 'tenant-profile.rate-limits.edit-cassandra-tenant-limits-configuration-title'], + [RateLimitsType.TENANT_ENTITY_EXPORT_RATE_LIMIT, 'tenant-profile.rate-limits.edit-tenant-entity-export-rate-limit-title'], + [RateLimitsType.TENANT_ENTITY_IMPORT_RATE_LIMIT, 'tenant-profile.rate-limits.edit-tenant-entity-import-rate-limit-title'], ] ); @@ -76,6 +82,8 @@ export const addRateLimitTranslationMap = new Map( [RateLimitsType.CUSTOMER_SERVER_REST_LIMITS_CONFIGURATION, 'tenant-profile.rate-limits.add-customer-rest-limits-title'], [RateLimitsType.WS_UPDATE_PER_SESSION_RATE_LIMIT, 'tenant-profile.rate-limits.add-ws-limit-updates-per-session-title'], [RateLimitsType.CASSANDRA_QUERY_TENANT_RATE_LIMITS_CONFIGURATION, 'tenant-profile.rate-limits.add-cassandra-tenant-limits-configuration-title'], + [RateLimitsType.TENANT_ENTITY_EXPORT_RATE_LIMIT, 'tenant-profile.rate-limits.add-tenant-entity-export-rate-limit-title'], + [RateLimitsType.TENANT_ENTITY_IMPORT_RATE_LIMIT, 'tenant-profile.rate-limits.add-tenant-entity-import-rate-limit-title'], ] ); diff --git a/ui-ngx/src/assets/locale/locale.constant-en_US.json b/ui-ngx/src/assets/locale/locale.constant-en_US.json index 8cd65a139e..371ade779c 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -3200,6 +3200,8 @@ "add-customer-rest-limits-title": "Add REST requests for customer rate limits", "add-ws-limit-updates-per-session-title": "Add WS updates per session rate limits", "add-cassandra-tenant-limits-configuration-title": "Add Cassandra query for tenant rate limits", + "add-tenant-entity-export-rate-limit-title": "Add entity version creation rate limits", + "add-tenant-entity-import-rate-limit-title": "Add entity version load rate limits", "advanced-settings": "Advanced settings", "edit-limit": "Edit limit", "but-less-than": "but less than", @@ -3213,13 +3215,17 @@ "edit-customer-rest-limits-title": "Edit REST requests for customer rate limits", "edit-ws-limit-updates-per-session-title": "Edit WS updates per session rate limits", "edit-cassandra-tenant-limits-configuration-title": "Edit Cassandra query for tenant rate limits", + "edit-tenant-entity-export-rate-limit-title": "Edit entity version creation rate limits", + "edit-tenant-entity-import-rate-limit-title": "Edit entity version load rate limits", "messages-per": "messages per", "not-set": "Not set", "number-of-messages": "Number of messages", "number-of-messages-required": "Number of messages is required.", + "number-of-messages-min": "Minimum value is 1.", "preview": "Preview", "per-seconds": "Per seconds", "per-seconds-required": "Time rate is required.", + "per-seconds-min": "Minimum value is 1.", "rate-limits": "Rate limits", "remove-limit": "Remove limit", "transport-tenant-msg": "Transport tenant messages", From e74eeed6a8b3c6a3f5e05a1e9acd4f8f5d061a8e Mon Sep 17 00:00:00 2001 From: Artem Babak Date: Thu, 21 Jul 2022 13:09:55 +0300 Subject: [PATCH 011/108] Removed Add rate limit titles --- .../rate-limits/rate-limits.component.html | 4 ++-- .../tenant/rate-limits/rate-limits.component.ts | 14 ++------------ .../src/app/shared/models/rate-limits.models.ts | 17 ----------------- .../assets/locale/locale.constant-en_US.json | 12 ------------ 4 files changed, 4 insertions(+), 43 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits.component.html b/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits.component.html index 2c4b82e4ab..3a6591790f 100644 --- a/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits.component.html +++ b/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits.component.html @@ -19,14 +19,14 @@
{{ label | translate }}
diff --git a/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits.component.ts b/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits.component.ts index 34cbadb755..75318c41cb 100644 --- a/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits.component.ts +++ b/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits.component.ts @@ -30,7 +30,6 @@ import { RateLimitsDetailsDialogData } from '@home/components/profile/tenant/rate-limits/rate-limits-details-dialog.component'; import { - addRateLimitTranslationMap, editRateLimitTranslationMap, rateLimitLabelTranslationMap, RateLimitsType, @@ -106,11 +105,11 @@ export class RateLimitsComponent implements ControlValueAccessor, OnInit, Valida return null; } - public onClick($event: Event, action: string) { + public onClick($event: Event) { if ($event) { $event.stopPropagation(); } - const title = this.setTitle(action); + const title = editRateLimitTranslationMap.get(this.type); this.dialog.open(RateLimitsDetailsDialogComponent, { disableClose: true, @@ -128,15 +127,6 @@ export class RateLimitsComponent implements ControlValueAccessor, OnInit, Valida }); } - private setTitle(action: string): string { - switch (action) { - case 'add': - return addRateLimitTranslationMap.get(this.type); - case 'edit': - return editRateLimitTranslationMap.get(this.type); - } - } - private updateRateLimitsInfo() { this.rateLimitsFormGroup.patchValue( { diff --git a/ui-ngx/src/app/shared/models/rate-limits.models.ts b/ui-ngx/src/app/shared/models/rate-limits.models.ts index ffde8a3c87..f035d9f67c 100644 --- a/ui-ngx/src/app/shared/models/rate-limits.models.ts +++ b/ui-ngx/src/app/shared/models/rate-limits.models.ts @@ -70,23 +70,6 @@ export const editRateLimitTranslationMap = new Map( ] ); -export const addRateLimitTranslationMap = new Map( - [ - [RateLimitsType.TENANT_MESSAGES, 'tenant-profile.rate-limits.add-transport-tenant-msg-title'], - [RateLimitsType.TENANT_TELEMETRY_MESSAGES, 'tenant-profile.rate-limits.add-transport-tenant-telemetry-msg-title'], - [RateLimitsType.TENANT_TELEMETRY_DATA_POINTS, 'tenant-profile.rate-limits.add-transport-tenant-telemetry-data-points-title'], - [RateLimitsType.DEVICE_MESSAGES, 'tenant-profile.rate-limits.add-transport-device-msg-title'], - [RateLimitsType.DEVICE_TELEMETRY_MESSAGES, 'tenant-profile.rate-limits.add-transport-device-telemetry-msg-title'], - [RateLimitsType.DEVICE_TELEMETRY_DATA_POINTS, 'tenant-profile.rate-limits.add-transport-device-telemetry-data-points-title'], - [RateLimitsType.TENANT_SERVER_REST_LIMITS_CONFIGURATION, 'tenant-profile.rate-limits.add-transport-tenant-msg-rate-limit-title'], - [RateLimitsType.CUSTOMER_SERVER_REST_LIMITS_CONFIGURATION, 'tenant-profile.rate-limits.add-customer-rest-limits-title'], - [RateLimitsType.WS_UPDATE_PER_SESSION_RATE_LIMIT, 'tenant-profile.rate-limits.add-ws-limit-updates-per-session-title'], - [RateLimitsType.CASSANDRA_QUERY_TENANT_RATE_LIMITS_CONFIGURATION, 'tenant-profile.rate-limits.add-cassandra-tenant-limits-configuration-title'], - [RateLimitsType.TENANT_ENTITY_EXPORT_RATE_LIMIT, 'tenant-profile.rate-limits.add-tenant-entity-export-rate-limit-title'], - [RateLimitsType.TENANT_ENTITY_IMPORT_RATE_LIMIT, 'tenant-profile.rate-limits.add-tenant-entity-import-rate-limit-title'], - ] -); - export function stringToRateLimitsArray(rateLimits: string): Array { const result: Array = []; if (rateLimits?.length > 0) { diff --git a/ui-ngx/src/assets/locale/locale.constant-en_US.json b/ui-ngx/src/assets/locale/locale.constant-en_US.json index 371ade779c..612823b803 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -3190,18 +3190,6 @@ "ws-limit-updates-per-session": "WS updates per session", "rate-limits": { "add-limit": "Add limit", - "add-transport-tenant-msg-title": "Add transport tenant messages rate limits", - "add-transport-tenant-telemetry-msg-title": "Add transport tenant telemetry messages rate limits", - "add-transport-tenant-telemetry-data-points-title": "Add transport tenant telemetry data points rate limits", - "add-transport-device-msg-title": "Add transport device messages rate limits", - "add-transport-device-telemetry-msg-title": "Add transport device telemetry messages rate limits", - "add-transport-device-telemetry-data-points-title": "Add transport device telemetry data points rate limits", - "add-transport-tenant-msg-rate-limit-title": "Add transport tenant messages rate limits", - "add-customer-rest-limits-title": "Add REST requests for customer rate limits", - "add-ws-limit-updates-per-session-title": "Add WS updates per session rate limits", - "add-cassandra-tenant-limits-configuration-title": "Add Cassandra query for tenant rate limits", - "add-tenant-entity-export-rate-limit-title": "Add entity version creation rate limits", - "add-tenant-entity-import-rate-limit-title": "Add entity version load rate limits", "advanced-settings": "Advanced settings", "edit-limit": "Edit limit", "but-less-than": "but less than", From 9ada3562d56788298036317460cd88a53dd3659c Mon Sep 17 00:00:00 2001 From: Artem Babak Date: Thu, 21 Jul 2022 13:11:40 +0300 Subject: [PATCH 012/108] Rate limit dialog minor title refactor --- .../profile/tenant/rate-limits/rate-limits.component.ts | 4 ++-- ui-ngx/src/app/shared/models/rate-limits.models.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits.component.ts b/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits.component.ts index 75318c41cb..2c320bcbe2 100644 --- a/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits.component.ts +++ b/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits.component.ts @@ -30,7 +30,7 @@ import { RateLimitsDetailsDialogData } from '@home/components/profile/tenant/rate-limits/rate-limits-details-dialog.component'; import { - editRateLimitTranslationMap, + rateLimitDialogTitleTranslationMap, rateLimitLabelTranslationMap, RateLimitsType, stringToRateLimitsArray @@ -109,7 +109,7 @@ export class RateLimitsComponent implements ControlValueAccessor, OnInit, Valida if ($event) { $event.stopPropagation(); } - const title = editRateLimitTranslationMap.get(this.type); + const title = rateLimitDialogTitleTranslationMap.get(this.type); this.dialog.open(RateLimitsDetailsDialogComponent, { disableClose: true, diff --git a/ui-ngx/src/app/shared/models/rate-limits.models.ts b/ui-ngx/src/app/shared/models/rate-limits.models.ts index f035d9f67c..272728c647 100644 --- a/ui-ngx/src/app/shared/models/rate-limits.models.ts +++ b/ui-ngx/src/app/shared/models/rate-limits.models.ts @@ -53,7 +53,7 @@ export const rateLimitLabelTranslationMap = new Map( ] ); -export const editRateLimitTranslationMap = new Map( +export const rateLimitDialogTitleTranslationMap = new Map( [ [RateLimitsType.TENANT_MESSAGES, 'tenant-profile.rate-limits.edit-transport-tenant-msg-title'], [RateLimitsType.TENANT_TELEMETRY_MESSAGES, 'tenant-profile.rate-limits.edit-transport-tenant-telemetry-msg-title'], From acadd0f8278a19eef4b5053ee5fbbcc54891885e Mon Sep 17 00:00:00 2001 From: Artem Babak Date: Thu, 21 Jul 2022 13:31:00 +0300 Subject: [PATCH 013/108] Rate limits fix close null bug --- .../rate-limits-details-dialog.component.ts | 2 +- .../tenant/rate-limits/rate-limits.component.ts | 11 ++++++----- ui-ngx/src/app/shared/models/rate-limits.models.ts | 4 ++-- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-details-dialog.component.ts b/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-details-dialog.component.ts index 69bf5cda4f..790ca57838 100644 --- a/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-details-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-details-dialog.component.ts @@ -72,7 +72,7 @@ export class RateLimitsDetailsDialogComponent extends DialogComponent(RateLimitsDetailsDialogComponent, { disableClose: true, @@ -120,7 +121,7 @@ export class RateLimitsComponent implements ControlValueAccessor, OnInit, Valida readonly: this.disabled } }).afterClosed().subscribe((result) => { - if (result) { + if (result || result === null) { this.modelValue = result; this.updateModel(); } diff --git a/ui-ngx/src/app/shared/models/rate-limits.models.ts b/ui-ngx/src/app/shared/models/rate-limits.models.ts index 272728c647..7185dbdd44 100644 --- a/ui-ngx/src/app/shared/models/rate-limits.models.ts +++ b/ui-ngx/src/app/shared/models/rate-limits.models.ts @@ -36,7 +36,7 @@ export enum RateLimitsType { TENANT_ENTITY_IMPORT_RATE_LIMIT = 'TENANT_ENTITY_IMPORT_RATE_LIMIT' } -export const rateLimitLabelTranslationMap = new Map( +export const rateLimitsLabelTranslationMap = new Map( [ [RateLimitsType.TENANT_MESSAGES, 'tenant-profile.rate-limits.transport-tenant-msg'], [RateLimitsType.TENANT_TELEMETRY_MESSAGES, 'tenant-profile.rate-limits.transport-tenant-telemetry-msg'], @@ -53,7 +53,7 @@ export const rateLimitLabelTranslationMap = new Map( ] ); -export const rateLimitDialogTitleTranslationMap = new Map( +export const rateLimitsDialogTitleTranslationMap = new Map( [ [RateLimitsType.TENANT_MESSAGES, 'tenant-profile.rate-limits.edit-transport-tenant-msg-title'], [RateLimitsType.TENANT_TELEMETRY_MESSAGES, 'tenant-profile.rate-limits.edit-transport-tenant-telemetry-msg-title'], From b331bbbb2491373a52096590cf02f331c2dcb955 Mon Sep 17 00:00:00 2001 From: Artem Babak Date: Thu, 21 Jul 2022 13:50:17 +0300 Subject: [PATCH 014/108] Rate limits: changed order --- ...t-tenant-profile-configuration.component.html | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/profile/tenant/default-tenant-profile-configuration.component.html b/ui-ngx/src/app/modules/home/components/profile/tenant/default-tenant-profile-configuration.component.html index 34015f71ad..847aae7bf1 100644 --- a/ui-ngx/src/app/modules/home/components/profile/tenant/default-tenant-profile-configuration.component.html +++ b/ui-ngx/src/app/modules/home/components/profile/tenant/default-tenant-profile-configuration.component.html @@ -460,14 +460,6 @@ [type]="rateLimitsType.CUSTOMER_SERVER_REST_LIMITS_CONFIGURATION"> -
- - - - -
@@ -476,6 +468,14 @@ [type]="rateLimitsType.TENANT_ENTITY_IMPORT_RATE_LIMIT">
+
+ + + + +
From 913db7a0d329f132218beaecdc55a2b0098c8d5b Mon Sep 17 00:00:00 2001 From: Artem Babak Date: Thu, 21 Jul 2022 15:45:00 +0300 Subject: [PATCH 015/108] - Fixed diabled button in the edit rate limits; - Removed validation by the pattern for the rate limits --- ...-tenant-profile-configuration.component.ts | 25 +++++++++---------- .../rate-limits-list.component.html | 2 ++ 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/profile/tenant/default-tenant-profile-configuration.component.ts b/ui-ngx/src/app/modules/home/components/profile/tenant/default-tenant-profile-configuration.component.ts index 5652f7dd71..d44715cc63 100644 --- a/ui-ngx/src/app/modules/home/components/profile/tenant/default-tenant-profile-configuration.component.ts +++ b/ui-ngx/src/app/modules/home/components/profile/tenant/default-tenant-profile-configuration.component.ts @@ -36,7 +36,6 @@ import { RateLimitsType } from '@shared/models/rate-limits.models'; export class DefaultTenantProfileConfigurationComponent implements ControlValueAccessor, OnInit { defaultTenantProfileConfigurationFormGroup: FormGroup; - rateLimitsPattern = '([1-9]\\d*:[1-9]\\d*)(,[1-9]\\d*:[1-9]\\d*)*'; private requiredValue: boolean; get required(): boolean { @@ -65,14 +64,14 @@ export class DefaultTenantProfileConfigurationComponent implements ControlValueA maxRuleChains: [null, [Validators.required, Validators.min(0)]], maxResourcesInBytes: [null, [Validators.required, Validators.min(0)]], maxOtaPackagesInBytes: [null, [Validators.required, Validators.min(0)]], - transportTenantMsgRateLimit: [null, [Validators.pattern(this.rateLimitsPattern)]], - transportTenantTelemetryMsgRateLimit: [null, [Validators.pattern(this.rateLimitsPattern)]], - transportTenantTelemetryDataPointsRateLimit: [null, [Validators.pattern(this.rateLimitsPattern)]], - transportDeviceMsgRateLimit: [null, [Validators.pattern(this.rateLimitsPattern)]], - transportDeviceTelemetryMsgRateLimit: [null, [Validators.pattern(this.rateLimitsPattern)]], - transportDeviceTelemetryDataPointsRateLimit: [null, [Validators.pattern(this.rateLimitsPattern)]], - tenantEntityExportRateLimit: [null, [Validators.pattern(this.rateLimitsPattern)]], - tenantEntityImportRateLimit: [null, [Validators.pattern(this.rateLimitsPattern)]], + transportTenantMsgRateLimit: [null, []], + transportTenantTelemetryMsgRateLimit: [null, []], + transportTenantTelemetryDataPointsRateLimit: [null, []], + transportDeviceMsgRateLimit: [null, []], + transportDeviceTelemetryMsgRateLimit: [null, []], + transportDeviceTelemetryDataPointsRateLimit: [null, []], + tenantEntityExportRateLimit: [null, []], + tenantEntityImportRateLimit: [null, []], maxTransportMessages: [null, [Validators.required, Validators.min(0)]], maxTransportDataPoints: [null, [Validators.required, Validators.min(0)]], maxREExecutions: [null, [Validators.required, Validators.min(0)]], @@ -85,8 +84,8 @@ export class DefaultTenantProfileConfigurationComponent implements ControlValueA defaultStorageTtlDays: [null, [Validators.required, Validators.min(0)]], alarmsTtlDays: [null, [Validators.required, Validators.min(0)]], rpcTtlDays: [null, [Validators.required, Validators.min(0)]], - tenantServerRestLimitsConfiguration: [null, [Validators.pattern(this.rateLimitsPattern)]], - customerServerRestLimitsConfiguration: [null, [Validators.pattern(this.rateLimitsPattern)]], + tenantServerRestLimitsConfiguration: [null, []], + customerServerRestLimitsConfiguration: [null, []], maxWsSessionsPerTenant: [null, [Validators.min(0)]], maxWsSessionsPerCustomer: [null, [Validators.min(0)]], maxWsSessionsPerRegularUser: [null, [Validators.min(0)]], @@ -96,8 +95,8 @@ export class DefaultTenantProfileConfigurationComponent implements ControlValueA maxWsSubscriptionsPerCustomer: [null, [Validators.min(0)]], maxWsSubscriptionsPerRegularUser: [null, [Validators.min(0)]], maxWsSubscriptionsPerPublicUser: [null, [Validators.min(0)]], - wsUpdatesPerSessionRateLimit: [null, [Validators.pattern(this.rateLimitsPattern)]], - cassandraQueryTenantRateLimitsConfiguration: [null, [Validators.pattern(this.rateLimitsPattern)]] + wsUpdatesPerSessionRateLimit: [null, []], + cassandraQueryTenantRateLimitsConfiguration: [null, []] }); this.defaultTenantProfileConfigurationFormGroup.valueChanges.subscribe(() => { this.updateModel(); diff --git a/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-list.component.html b/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-list.component.html index 7d1f3e4561..768b351070 100644 --- a/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-list.component.html +++ b/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-list.component.html @@ -47,6 +47,7 @@ class="tb-rate-limits-button" *ngIf="!rateLimitsFormArray().disabled" (click)="removeRateLimits($index)" + [disabled]="disabled" [matTooltip]="'tenant-profile.rate-limits.remove-limit' | translate" matTooltipPosition="above"> remove_circle_outline @@ -55,6 +56,7 @@
From a0fd18221de1c4a0cc43f3dd35f554e473ec8b74 Mon Sep 17 00:00:00 2001 From: Artem Babak Date: Thu, 21 Jul 2022 16:29:40 +0300 Subject: [PATCH 016/108] Remove redundant import --- .../profile/tenant/rate-limits/rate-limits.component.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits.component.ts b/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits.component.ts index 9029d36a9f..753ef133a9 100644 --- a/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits.component.ts +++ b/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits.component.ts @@ -35,7 +35,6 @@ import { RateLimitsType, stringToRateLimitsArray } from '@shared/models/rate-limits.models'; -import { isNull } from 'util'; @Component({ selector: 'tb-rate-limits', From 41c86f3ba491815c8244c21939aa4d65df0d2bb4 Mon Sep 17 00:00:00 2001 From: devaskim Date: Thu, 21 Jul 2022 19:08:26 +0500 Subject: [PATCH 017/108] Add relation tab to user details. --- .../src/app/modules/home/pages/user/user-tabs.component.html | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ui-ngx/src/app/modules/home/pages/user/user-tabs.component.html b/ui-ngx/src/app/modules/home/pages/user/user-tabs.component.html index 6417c2ac9f..7a9243e8a7 100644 --- a/ui-ngx/src/app/modules/home/pages/user/user-tabs.component.html +++ b/ui-ngx/src/app/modules/home/pages/user/user-tabs.component.html @@ -32,6 +32,10 @@ [entityName]="entity.name"> + + + From 33fe04a7a0e11e6d8ff7e1db09982f145b2e7afc Mon Sep 17 00:00:00 2001 From: Vladyslav_Prykhodko Date: Mon, 25 Jul 2022 13:34:40 +0300 Subject: [PATCH 018/108] UI: Not redirect to the previous link after login with 2FA --- ui-ngx/src/app/core/auth/auth.service.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ui-ngx/src/app/core/auth/auth.service.ts b/ui-ngx/src/app/core/auth/auth.service.ts index c7b1a283d3..172e4d5ac9 100644 --- a/ui-ngx/src/app/core/auth/auth.service.ts +++ b/ui-ngx/src/app/core/auth/auth.service.ts @@ -268,7 +268,9 @@ export class AuthService { public defaultUrl(isAuthenticated: boolean, authState?: AuthState, path?: string, params?: any): UrlTree { let result: UrlTree = null; if (isAuthenticated) { - if (!path || path === 'login' || this.forceDefaultPlace(authState, path, params)) { + if (authState.authUser.authority === Authority.PRE_VERIFICATION_TOKEN) { + result = this.router.parseUrl('login/mfa'); + } else if (!path || path === 'login' || this.forceDefaultPlace(authState, path, params)) { if (this.redirectUrl) { const redirectUrl = this.redirectUrl; this.redirectUrl = null; From b3fdc881f48a8b985acd6ab15e24cca6ddb71de7 Mon Sep 17 00:00:00 2001 From: deaflynx Date: Mon, 25 Jul 2022 17:19:07 +0300 Subject: [PATCH 019/108] Fixed bugs, removed redundant code --- ...enant-profile-configuration.component.html | 24 +++++++------- ...-tenant-profile-configuration.component.ts | 2 +- .../rate-limits-details-dialog.component.html | 10 ++---- .../rate-limits-details-dialog.component.ts | 21 +++--------- .../rate-limits-list.component.html | 22 ++++++------- .../rate-limits/rate-limits-list.component.ts | 32 +++++++------------ .../rate-limits-text.component.html | 2 +- .../rate-limits-text.component.scss | 8 ----- .../rate-limits/rate-limits-text.component.ts | 25 ++------------- .../rate-limits/rate-limits.component.ts | 2 +- .../tenant/rate-limits}/rate-limits.models.ts | 0 11 files changed, 47 insertions(+), 101 deletions(-) rename ui-ngx/src/app/{shared/models => modules/home/components/profile/tenant/rate-limits}/rate-limits.models.ts (100%) diff --git a/ui-ngx/src/app/modules/home/components/profile/tenant/default-tenant-profile-configuration.component.html b/ui-ngx/src/app/modules/home/components/profile/tenant/default-tenant-profile-configuration.component.html index 847aae7bf1..a3f285bece 100644 --- a/ui-ngx/src/app/modules/home/components/profile/tenant/default-tenant-profile-configuration.component.html +++ b/ui-ngx/src/app/modules/home/components/profile/tenant/default-tenant-profile-configuration.component.html @@ -422,18 +422,18 @@ {{ 'tenant-profile.rate-limits.rate-limits' | translate }}
- -
- -
@@ -445,34 +445,34 @@
- -
- -
- -
- -
diff --git a/ui-ngx/src/app/modules/home/components/profile/tenant/default-tenant-profile-configuration.component.ts b/ui-ngx/src/app/modules/home/components/profile/tenant/default-tenant-profile-configuration.component.ts index d44715cc63..9649966bd1 100644 --- a/ui-ngx/src/app/modules/home/components/profile/tenant/default-tenant-profile-configuration.component.ts +++ b/ui-ngx/src/app/modules/home/components/profile/tenant/default-tenant-profile-configuration.component.ts @@ -21,7 +21,7 @@ import { AppState } from '@app/core/core.state'; import { coerceBooleanProperty } from '@angular/cdk/coercion'; import { DefaultTenantProfileConfiguration, TenantProfileConfiguration } from '@shared/models/tenant.model'; import { isDefinedAndNotNull } from '@core/utils'; -import { RateLimitsType } from '@shared/models/rate-limits.models'; +import { RateLimitsType } from './rate-limits/rate-limits.models'; @Component({ selector: 'tb-default-tenant-profile-configuration', diff --git a/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-details-dialog.component.html b/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-details-dialog.component.html index 751ffe0e2c..6cbe5472c2 100644 --- a/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-details-dialog.component.html +++ b/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-details-dialog.component.html @@ -25,14 +25,11 @@ close - -
-
+
+ formControlName="rateLimits">
@@ -40,12 +37,11 @@
diff --git a/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-details-dialog.component.ts b/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-details-dialog.component.ts index 790ca57838..80b9e1ba34 100644 --- a/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-details-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-details-dialog.component.ts @@ -19,7 +19,7 @@ import { ErrorStateMatcher } from '@angular/material/core'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import { Store } from '@ngrx/store'; import { AppState } from '@core/core.state'; -import { FormBuilder, FormControl, FormGroup, FormGroupDirective, NgForm } from '@angular/forms'; +import { FormBuilder, FormGroup } from '@angular/forms'; import { Router } from '@angular/router'; import { DialogComponent } from '@app/shared/components/dialog.component'; import { TranslateService } from '@ngx-translate/core'; @@ -31,16 +31,12 @@ export interface RateLimitsDetailsDialogData { } @Component({ - templateUrl: './rate-limits-details-dialog.component.html', - providers: [{provide: ErrorStateMatcher, useExisting: RateLimitsDetailsDialogComponent}] + templateUrl: './rate-limits-details-dialog.component.html' }) -export class RateLimitsDetailsDialogComponent extends DialogComponent - implements OnInit, ErrorStateMatcher { +export class RateLimitsDetailsDialogComponent extends DialogComponent implements OnInit { editDetailsFormGroup: FormGroup; - submitted: boolean = false; - rateLimits: string = this.data.rateLimits; title: string = this.data.title; @@ -49,7 +45,7 @@ export class RateLimitsDetailsDialogComponent extends DialogComponent, + public dialogRef: MatDialogRef, private fb: FormBuilder, public translate: TranslateService) { super(store, router, dialogRef); @@ -65,18 +61,11 @@ export class RateLimitsDetailsDialogComponent extends DialogComponent -
-
-
+
+
+
tenant-profile.rate-limits.but-less-than
@@ -45,7 +45,7 @@
-
- -
+
tenant-profile.rate-limits.preview
diff --git a/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-list.component.ts b/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-list.component.ts index eb7a37cfde..dd5f52dbc2 100644 --- a/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-list.component.ts +++ b/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-list.component.ts @@ -32,7 +32,7 @@ import { RateLimits, rateLimitsArrayToString, stringToRateLimitsArray -} from '@shared/models/rate-limits.models'; +} from './rate-limits.models'; import { isDefinedAndNotNull } from '@core/utils'; @Component({ @@ -68,17 +68,17 @@ export class RateLimitsListComponent implements ControlValueAccessor, Validator, } ngOnInit(): void { - this.rateLimitsListFormGroup = this.fb.group({}); - this.rateLimitsListFormGroup.addControl('rateLimits', - this.fb.array([])); + this.rateLimitsListFormGroup = this.fb.group({ + rateLimits: this.fb.array([]) + }); this.rateLimitsControl = this.fb.control(null); - this.rateLimitsListFormGroup.valueChanges.subscribe((value) => { + this.valueChangeSubscription = this.rateLimitsListFormGroup.valueChanges.subscribe((value) => { this.updateView(value?.rateLimits); } ); } - rateLimitsFormArray(): FormArray { + get rateLimitsFormArray(): FormArray { return this.rateLimitsListFormGroup.get('rateLimits') as FormArray; } @@ -107,16 +107,11 @@ export class RateLimitsListComponent implements ControlValueAccessor, Validator, } writeValue(value: string) { - if (this.valueChangeSubscription) { - this.valueChangeSubscription.unsubscribe(); - } const rateLimitsControls: Array = []; if (value) { let rateLimitsArray = value.split(','); for (let i = 0; i < rateLimitsArray.length; i++) { - let valueTime = rateLimitsArray[i].split(':'); - let value = valueTime[0]; - let time = valueTime[1]; + const [value, time] = rateLimitsArray[i].split(':'); const rateLimitsControl = this.fb.group({ value: [value, [Validators.required]], time: [time, [Validators.required]] @@ -127,11 +122,8 @@ export class RateLimitsListComponent implements ControlValueAccessor, Validator, rateLimitsControls.push(rateLimitsControl); } } - this.rateLimitsListFormGroup.setControl('rateLimits', this.fb.array(rateLimitsControls)); + this.rateLimitsListFormGroup.setControl('rateLimits', this.fb.array(rateLimitsControls), {emitEvent: false}); this.rateLimitsControl.patchValue(stringToRateLimitsArray(value), {emitEvent: false}); - this.valueChangeSubscription = this.rateLimitsListFormGroup.valueChanges.subscribe((value) => { - this.updateView(value?.rateLimits); - }); } public removeRateLimits(index: number) { @@ -139,17 +131,17 @@ export class RateLimitsListComponent implements ControlValueAccessor, Validator, } public addRateLimits() { - const rateLimitsArray = this.rateLimitsListFormGroup.get('rateLimits') as FormArray; - rateLimitsArray.push(this.fb.group({ + this.rateLimitsFormArray.push(this.fb.group({ value: [null, [Validators.required]], time: [null, [Validators.required]] })); - this.rateLimitsListFormGroup.updateValueAndValidity(); } updateView(rateLimitsArray: Array) { if (rateLimitsArray.length > 0) { - const notNullRateLimits = rateLimitsArray.filter(rateLimits => isDefinedAndNotNull(rateLimits.value) && isDefinedAndNotNull(rateLimits.time)); + const notNullRateLimits = rateLimitsArray.filter(rateLimits => + isDefinedAndNotNull(rateLimits.value) && isDefinedAndNotNull(rateLimits.time) + ); const rateLimitsString = rateLimitsArrayToString(notNullRateLimits); this.propagateChange(rateLimitsString); this.rateLimitsControl.patchValue(stringToRateLimitsArray(rateLimitsString), {emitEvent: false}); diff --git a/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-text.component.html b/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-text.component.html index 98a30b055e..077ede2e0b 100644 --- a/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-text.component.html +++ b/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-text.component.html @@ -15,5 +15,5 @@ limitations under the License. --> -
diff --git a/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-text.component.scss b/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-text.component.scss index a8f8f8553f..b78f1033bd 100644 --- a/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-text.component.scss +++ b/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-text.component.scss @@ -20,14 +20,6 @@ &.disabled { opacity: 0.7; } - &.required { - color: #f44336; - padding: 0 4px; - } - &.nowrap { - white-space: nowrap; - overflow: hidden; - } } } diff --git a/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-text.component.ts b/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-text.component.ts index 9ab7e9b56b..604318d6fd 100644 --- a/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-text.component.ts +++ b/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-text.component.ts @@ -18,8 +18,7 @@ import { Component, forwardRef, Input, OnInit } from '@angular/core'; import { ControlValueAccessor, FormBuilder, NG_VALUE_ACCESSOR } from '@angular/forms'; import { MatDialog } from '@angular/material/dialog'; import { TranslateService } from '@ngx-translate/core'; -import { coerceBooleanProperty } from '@angular/cdk/coercion'; -import { RateLimits, rateLimitsArrayToHtml } from '@shared/models/rate-limits.models'; +import { RateLimits, rateLimitsArrayToHtml } from './rate-limits.models'; @Component({ selector: 'tb-rate-limits-text', @@ -35,26 +34,11 @@ import { RateLimits, rateLimitsArrayToHtml } from '@shared/models/rate-limits.mo }) export class RateLimitsTextComponent implements ControlValueAccessor, OnInit { - private requiredValue: boolean; - get required(): boolean { - return this.requiredValue; - } - @Input() - set required(value: boolean) { - this.requiredValue = coerceBooleanProperty(value); - } - @Input() disabled: boolean; - @Input() noRateLimitsText = this.translate.instant('tenant-profile.rate-limits.not-set'); - @Input() - nowrap = false; - - requiredClass = false; - public rateLimitsText: string; private propagateChange = (v: any) => { }; @@ -83,15 +67,10 @@ export class RateLimitsTextComponent implements ControlValueAccessor, OnInit { } private updateText(value: Array) { - this.requiredClass = false; if (value && value.length) { this.rateLimitsText = rateLimitsArrayToHtml(this.translate, value); } else { - if (this.required && !this.disabled) { - this.requiredClass = true; - } else { - this.rateLimitsText = this.noRateLimitsText; - } + this.rateLimitsText = this.noRateLimitsText; } } diff --git a/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits.component.ts b/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits.component.ts index 753ef133a9..dcf0403a22 100644 --- a/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits.component.ts +++ b/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits.component.ts @@ -34,7 +34,7 @@ import { rateLimitsLabelTranslationMap, RateLimitsType, stringToRateLimitsArray -} from '@shared/models/rate-limits.models'; +} from './rate-limits.models'; @Component({ selector: 'tb-rate-limits', diff --git a/ui-ngx/src/app/shared/models/rate-limits.models.ts b/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits.models.ts similarity index 100% rename from ui-ngx/src/app/shared/models/rate-limits.models.ts rename to ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits.models.ts From 88599262daa26a19e365acadd2375d44666c9d0b Mon Sep 17 00:00:00 2001 From: deaflynx Date: Mon, 25 Jul 2022 17:55:15 +0300 Subject: [PATCH 020/108] Rate limits update styles --- .../rate-limits-details-dialog.component.html | 5 +++-- .../rate-limits-details-dialog.component.ts | 13 ++----------- .../rate-limits/rate-limits-list.component.scss | 4 ++++ .../tenant/rate-limits/rate-limits.component.ts | 3 ++- 4 files changed, 11 insertions(+), 14 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-details-dialog.component.html b/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-details-dialog.component.html index 6cbe5472c2..e69b95a3e2 100644 --- a/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-details-dialog.component.html +++ b/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-details-dialog.component.html @@ -20,7 +20,7 @@

{{ title | translate }}

@@ -37,7 +37,8 @@
-
-
- - -
-
+
tenant-profile.rate-limits.preview -
- -
+
diff --git a/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-list.component.scss b/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-list.component.scss index 64f9c7afe2..2a53096c17 100644 --- a/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-list.component.scss +++ b/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-list.component.scss @@ -27,7 +27,7 @@ span { padding-left: 1em; } - div { + tb-rate-limits-text { border: 1px groove rgba(0, 0, 0, .25); border-radius: 4px; padding: 1em; diff --git a/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-text.component.html b/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-text.component.html index 077ede2e0b..e154a7ce54 100644 --- a/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-text.component.html +++ b/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-text.component.html @@ -15,5 +15,4 @@ limitations under the License. --> -
+
diff --git a/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-text.component.ts b/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-text.component.ts index 604318d6fd..0b65e97d5d 100644 --- a/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-text.component.ts +++ b/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-text.component.ts @@ -14,64 +14,41 @@ /// limitations under the License. /// -import { Component, forwardRef, Input, OnInit } from '@angular/core'; -import { ControlValueAccessor, FormBuilder, NG_VALUE_ACCESSOR } from '@angular/forms'; -import { MatDialog } from '@angular/material/dialog'; +import { Component, Input, OnChanges, SimpleChanges } from '@angular/core'; import { TranslateService } from '@ngx-translate/core'; import { RateLimits, rateLimitsArrayToHtml } from './rate-limits.models'; @Component({ selector: 'tb-rate-limits-text', templateUrl: './rate-limits-text.component.html', - styleUrls: ['./rate-limits-text.component.scss'], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => RateLimitsTextComponent), - multi: true - } - ] + styleUrls: ['./rate-limits-text.component.scss'] }) -export class RateLimitsTextComponent implements ControlValueAccessor, OnInit { +export class RateLimitsTextComponent implements OnChanges { @Input() - disabled: boolean; - - noRateLimitsText = this.translate.instant('tenant-profile.rate-limits.not-set'); - - public rateLimitsText: string; - - private propagateChange = (v: any) => { }; - - constructor(private dialog: MatDialog, - private fb: FormBuilder, - private translate: TranslateService) { - } - - registerOnChange(fn: any): void { - this.propagateChange = fn; - } + rateLimitsArray: Array; - registerOnTouched(fn: any): void { - } + @Input() + disabled: boolean; - ngOnInit() { - } + rateLimitsText: string; - setDisabledState(isDisabled: boolean): void { - this.disabled = isDisabled; - } + constructor(private translate: TranslateService) {} - writeValue(value: Array): void { - this.updateText(value); + ngOnChanges(changes: SimpleChanges): void { + for (const propName of Object.keys(changes)) { + if (propName === 'rateLimitsArray') { + const change = changes[propName]; + this.updateView(change.currentValue); + } + } } - private updateText(value: Array) { - if (value && value.length) { + private updateView(value: Array): void { + if (value?.length) { this.rateLimitsText = rateLimitsArrayToHtml(this.translate, value); } else { - this.rateLimitsText = this.noRateLimitsText; + this.rateLimitsText = this.translate.instant('tenant-profile.rate-limits.not-set'); } } - } diff --git a/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits.component.html b/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits.component.html index 3a6591790f..ac341c8b69 100644 --- a/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits.component.html +++ b/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits.component.html @@ -21,7 +21,7 @@
- +
tenant-profile.rate-limits.preview - +
diff --git a/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-list.component.ts b/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-list.component.ts index 0d8abf6657..0c135d0d9a 100644 --- a/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-list.component.ts +++ b/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-list.component.ts @@ -95,6 +95,10 @@ export class RateLimitsListComponent implements ControlValueAccessor, Validator, return this.rateLimitsListFormGroup.get('rateLimits') as FormArray; } + get rateLimitsArray(): Array { + return this.rateLimitsControl.value; + } + registerOnChange(fn: any): void { this.propagateChange = fn; } From c2f0d4725531da8bd307769defd24912d3f68567 Mon Sep 17 00:00:00 2001 From: deaflynx Date: Tue, 26 Jul 2022 15:44:51 +0300 Subject: [PATCH 025/108] Code cleanup --- .../rate-limits/rate-limits-details-dialog.component.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-details-dialog.component.ts b/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-details-dialog.component.ts index 9d01ddcd5b..46a50bf484 100644 --- a/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-details-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-details-dialog.component.ts @@ -15,14 +15,12 @@ /// import { Component, Inject, SkipSelf } from '@angular/core'; -import { ErrorStateMatcher } from '@angular/material/core'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import { Store } from '@ngrx/store'; import { AppState } from '@core/core.state'; import { FormBuilder, FormGroup } from '@angular/forms'; import { Router } from '@angular/router'; import { DialogComponent } from '@app/shared/components/dialog.component'; -import { TranslateService } from '@ngx-translate/core'; export interface RateLimitsDetailsDialogData { rateLimits: string; @@ -44,10 +42,8 @@ export class RateLimitsDetailsDialogComponent extends DialogComponent, protected router: Router, @Inject(MAT_DIALOG_DATA) public data: RateLimitsDetailsDialogData, - @SkipSelf() private errorStateMatcher: ErrorStateMatcher, public dialogRef: MatDialogRef, - private fb: FormBuilder, - public translate: TranslateService) { + private fb: FormBuilder) { super(store, router, dialogRef); this.editDetailsFormGroup = this.fb.group({ rateLimits: [this.rateLimits, []] From 4811a3d56cbe44d2c5a6576748273554ef15855e Mon Sep 17 00:00:00 2001 From: deaflynx Date: Tue, 26 Jul 2022 16:04:55 +0300 Subject: [PATCH 026/108] Code cleanup --- .../tenant/rate-limits/rate-limits-details-dialog.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-details-dialog.component.ts b/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-details-dialog.component.ts index 46a50bf484..4818304491 100644 --- a/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-details-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-details-dialog.component.ts @@ -14,7 +14,7 @@ /// limitations under the License. /// -import { Component, Inject, SkipSelf } from '@angular/core'; +import { Component, Inject } from '@angular/core'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import { Store } from '@ngrx/store'; import { AppState } from '@core/core.state'; From 43b847b9d85ed89bd7a4b6e1a077e2548d79a6f3 Mon Sep 17 00:00:00 2001 From: Vladyslav_Prykhodko Date: Tue, 26 Jul 2022 16:39:56 +0300 Subject: [PATCH 027/108] UI: Refactoring code --- .../rate-limits-list.component.html | 2 +- .../rate-limits/rate-limits-list.component.ts | 32 ++++++------------- .../rate-limits/rate-limits-text.component.ts | 3 +- .../rate-limits/rate-limits.component.html | 2 +- .../tenant/rate-limits/rate-limits.models.ts | 19 +++++------ 5 files changed, 22 insertions(+), 36 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-list.component.html b/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-list.component.html index ec25c80683..ba51cbc358 100644 --- a/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-list.component.html +++ b/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-list.component.html @@ -61,6 +61,6 @@
tenant-profile.rate-limits.preview - +
diff --git a/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-list.component.ts b/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-list.component.ts index 0c135d0d9a..e6ad1c5b20 100644 --- a/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-list.component.ts +++ b/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-list.component.ts @@ -19,7 +19,6 @@ import { ControlValueAccessor, FormArray, FormBuilder, - FormControl, FormGroup, NG_VALIDATORS, NG_VALUE_ACCESSOR, @@ -28,11 +27,7 @@ import { Validators } from '@angular/forms'; import { Subject, Subscription } from 'rxjs'; -import { - RateLimits, - rateLimitsArrayToString, - stringToRateLimitsArray -} from './rate-limits.models'; +import { RateLimits, rateLimitsArrayToString, stringToRateLimitsArray } from './rate-limits.models'; import { isDefinedAndNotNull } from '@core/utils'; import { takeUntil } from 'rxjs/operators'; @@ -59,11 +54,11 @@ export class RateLimitsListComponent implements ControlValueAccessor, Validator, rateLimitsListFormGroup: FormGroup; - rateLimitsControl: FormControl; + rateLimitsArray: Array; - private propagateChange = (v: any) => { }; private valueChangeSubscription: Subscription = null; private destroy$ = new Subject(); + private propagateChange = (v: any) => { }; constructor(private fb: FormBuilder) {} @@ -71,7 +66,6 @@ export class RateLimitsListComponent implements ControlValueAccessor, Validator, this.rateLimitsListFormGroup = this.fb.group({ rateLimits: this.fb.array([]) }); - this.rateLimitsControl = this.fb.control(null); this.valueChangeSubscription = this.rateLimitsListFormGroup.valueChanges .pipe(takeUntil(this.destroy$)) .subscribe((value) => { @@ -95,10 +89,6 @@ export class RateLimitsListComponent implements ControlValueAccessor, Validator, return this.rateLimitsListFormGroup.get('rateLimits') as FormArray; } - get rateLimitsArray(): Array { - return this.rateLimitsControl.value; - } - registerOnChange(fn: any): void { this.propagateChange = fn; } @@ -110,23 +100,21 @@ export class RateLimitsListComponent implements ControlValueAccessor, Validator, this.disabled = isDisabled; if (this.disabled) { this.rateLimitsListFormGroup.disable({emitEvent: false}); - this.rateLimitsControl.disable({emitEvent: false}); } else { this.rateLimitsListFormGroup.enable({emitEvent: false}); - this.rateLimitsControl.enable({emitEvent: false}); } } validate(): ValidationErrors | null { - return this.rateLimitsListFormGroup.valid && this.rateLimitsControl.valid ? null : { + return this.rateLimitsListFormGroup.valid ? null : { rateLimitsList: {valid: false} }; } - writeValue(value: string) { + writeValue(rateLimits: string) { const rateLimitsControls: Array = []; - if (value) { - let rateLimitsArray = value.split(','); + if (rateLimits) { + const rateLimitsArray = rateLimits.split(','); for (let i = 0; i < rateLimitsArray.length; i++) { const [value, time] = rateLimitsArray[i].split(':'); const rateLimitsControl = this.fb.group({ @@ -140,7 +128,7 @@ export class RateLimitsListComponent implements ControlValueAccessor, Validator, } } this.rateLimitsListFormGroup.setControl('rateLimits', this.fb.array(rateLimitsControls), {emitEvent: false}); - this.rateLimitsControl.patchValue(stringToRateLimitsArray(value), {emitEvent: false}); + this.rateLimitsArray = stringToRateLimitsArray(rateLimits); } updateView(rateLimitsArray: Array) { @@ -150,10 +138,10 @@ export class RateLimitsListComponent implements ControlValueAccessor, Validator, ); const rateLimitsString = rateLimitsArrayToString(notNullRateLimits); this.propagateChange(rateLimitsString); - this.rateLimitsControl.patchValue(stringToRateLimitsArray(rateLimitsString), {emitEvent: false}); + this.rateLimitsArray = stringToRateLimitsArray(rateLimitsString); } else { this.propagateChange(null); - this.rateLimitsControl.patchValue(null, {emitEvent: false}); + this.rateLimitsArray = null; } } diff --git a/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-text.component.ts b/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-text.component.ts index 0b65e97d5d..9081acc208 100644 --- a/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-text.component.ts +++ b/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits-text.component.ts @@ -33,7 +33,8 @@ export class RateLimitsTextComponent implements OnChanges { rateLimitsText: string; - constructor(private translate: TranslateService) {} + constructor(private translate: TranslateService) { + } ngOnChanges(changes: SimpleChanges): void { for (const propName of Object.keys(changes)) { diff --git a/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits.component.html b/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits.component.html index ac341c8b69..0ab20fc533 100644 --- a/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits.component.html +++ b/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits.component.html @@ -21,7 +21,7 @@
- +
diff --git a/ui-ngx/src/app/modules/home/components/widget/widget-container.component.html b/ui-ngx/src/app/modules/home/components/widget/widget-container.component.html index a6520e02bd..9f99ffbf29 100644 --- a/ui-ngx/src/app/modules/home/components/widget/widget-container.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/widget-container.component.html @@ -46,6 +46,7 @@
- + -
- timewindow.last - +
+
+ + +
+
+ timewindow.last + +
-
- timewindow.interval - +
+
+ + +
+
+ timewindow.interval + +
+ +
diff --git a/ui-ngx/src/app/shared/components/time/timewindow-panel.component.ts b/ui-ngx/src/app/shared/components/time/timewindow-panel.component.ts index 09fa20aaa3..67ee2ac72b 100644 --- a/ui-ngx/src/app/shared/components/time/timewindow-panel.component.ts +++ b/ui-ngx/src/app/shared/components/time/timewindow-panel.component.ts @@ -36,6 +36,7 @@ export const TIMEWINDOW_PANEL_DATA = new InjectionToken('TimewindowPanelDat export interface TimewindowPanelData { historyOnly: boolean; + quickIntervalOnly: boolean; timewindow: Timewindow; aggregation: boolean; timezone: boolean; @@ -51,6 +52,8 @@ export class TimewindowPanelComponent extends PageComponent implements OnInit { historyOnly = false; + quickIntervalOnly = false; + aggregation = false; timezone = false; @@ -83,6 +86,7 @@ export class TimewindowPanelComponent extends PageComponent implements OnInit { public viewContainerRef: ViewContainerRef) { super(store); this.historyOnly = data.historyOnly; + this.quickIntervalOnly = data.quickIntervalOnly; this.timewindow = data.timewindow; this.aggregation = data.aggregation; this.timezone = data.timezone; @@ -91,6 +95,8 @@ export class TimewindowPanelComponent extends PageComponent implements OnInit { ngOnInit(): void { const hideInterval = this.timewindow.hideInterval || false; + const hideLastInterval = this.timewindow.hideLastInterval || false; + const hideQuickInterval = this.timewindow.hideQuickInterval || false; const hideAggregation = this.timewindow.hideAggregation || false; const hideAggInterval = this.timewindow.hideAggInterval || false; const hideTimezone = this.timewindow.hideTimezone || false; @@ -103,10 +109,11 @@ export class TimewindowPanelComponent extends PageComponent implements OnInit { ? this.timewindow.realtime.realtimeType : RealtimeWindowType.LAST_INTERVAL, disabled: hideInterval }), - timewindowMs: [ - this.timewindow.realtime && typeof this.timewindow.realtime.timewindowMs !== 'undefined' - ? this.timewindow.realtime.timewindowMs : null - ], + timewindowMs: this.fb.control({ + value: this.timewindow.realtime && typeof this.timewindow.realtime.timewindowMs !== 'undefined' + ? this.timewindow.realtime.timewindowMs : null, + disabled: hideInterval || hideLastInterval + }), interval: [ this.timewindow.realtime && typeof this.timewindow.realtime.interval !== 'undefined' ? this.timewindow.realtime.interval : null @@ -114,7 +121,7 @@ export class TimewindowPanelComponent extends PageComponent implements OnInit { quickInterval: this.fb.control({ value: this.timewindow.realtime && typeof this.timewindow.realtime.quickInterval !== 'undefined' ? this.timewindow.realtime.quickInterval : null, - disabled: hideInterval + disabled: hideInterval || hideQuickInterval }) } ), @@ -289,8 +296,40 @@ export class TimewindowPanelComponent extends PageComponent implements OnInit { this.timewindowForm.get('history.fixedTimewindow').enable({emitEvent: false}); this.timewindowForm.get('history.quickInterval').enable({emitEvent: false}); this.timewindowForm.get('realtime.realtimeType').enable({emitEvent: false}); - this.timewindowForm.get('realtime.timewindowMs').enable({emitEvent: false}); - this.timewindowForm.get('realtime.quickInterval').enable({emitEvent: false}); + if (!this.timewindow.hideLastInterval) { + this.timewindowForm.get('realtime.timewindowMs').enable({emitEvent: false}); + } + if (!this.timewindow.hideQuickInterval) { + this.timewindowForm.get('realtime.quickInterval').enable({emitEvent: false}); + } + } + this.timewindowForm.markAsDirty(); + } + + onHideLastIntervalChanged() { + if (this.timewindow.hideLastInterval) { + this.timewindowForm.get('realtime.timewindowMs').disable({emitEvent: false}); + if (!this.timewindow.hideQuickInterval) { + this.timewindowForm.get('realtime.realtimeType').setValue(RealtimeWindowType.INTERVAL); + } + } else { + if (!this.timewindow.hideInterval) { + this.timewindowForm.get('realtime.timewindowMs').enable({emitEvent: false}); + } + } + this.timewindowForm.markAsDirty(); + } + + onHideQuickIntervalChanged() { + if (this.timewindow.hideQuickInterval) { + this.timewindowForm.get('realtime.quickInterval').disable({emitEvent: false}); + if (!this.timewindow.hideLastInterval) { + this.timewindowForm.get('realtime.realtimeType').setValue(RealtimeWindowType.LAST_INTERVAL); + } + } else { + if (!this.timewindow.hideInterval) { + this.timewindowForm.get('realtime.quickInterval').enable({emitEvent: false}); + } } this.timewindowForm.markAsDirty(); } diff --git a/ui-ngx/src/app/shared/components/time/timewindow.component.ts b/ui-ngx/src/app/shared/components/time/timewindow.component.ts index 6f34131241..951f157a59 100644 --- a/ui-ngx/src/app/shared/components/time/timewindow.component.ts +++ b/ui-ngx/src/app/shared/components/time/timewindow.component.ts @@ -82,6 +82,17 @@ export class TimewindowComponent implements OnInit, OnDestroy, ControlValueAcces return this.historyOnlyValue; } + quickIntervalOnlyValue = false; + + @Input() + set quickIntervalOnly(val) { + this.quickIntervalOnlyValue = coerceBooleanProperty(val); + } + + get quickIntervalOnly() { + return this.quickIntervalOnlyValue; + } + aggregationValue = false; @Input() @@ -240,6 +251,7 @@ export class TimewindowComponent implements OnInit, OnDestroy, ControlValueAcces { timewindow: deepClone(this.innerValue), historyOnly: this.historyOnly, + quickIntervalOnly: this.quickIntervalOnly, aggregation: this.aggregation, timezone: this.timezone, isEdit: this.isEdit @@ -278,7 +290,7 @@ export class TimewindowComponent implements OnInit, OnDestroy, ControlValueAcces } writeValue(obj: Timewindow): void { - this.innerValue = initModelFromDefaultTimewindow(obj, this.timeService); + this.innerValue = initModelFromDefaultTimewindow(obj, this.quickIntervalOnly, this.timeService); this.timewindowDisabled = this.isTimewindowDisabled(); this.updateDisplayValue(); } diff --git a/ui-ngx/src/app/shared/models/query/query.models.ts b/ui-ngx/src/app/shared/models/query/query.models.ts index e55beaf7e4..95c756f7f9 100644 --- a/ui-ngx/src/app/shared/models/query/query.models.ts +++ b/ui-ngx/src/app/shared/models/query/query.models.ts @@ -768,7 +768,6 @@ export interface EntityData { latest: {[entityKeyType: string]: {[key: string]: TsValue}}; timeseries: {[key: string]: Array}; aggLatest?: {[aggType: string]: {[key: string]: TsValue}}; - aggFloating?: {[key: string]: Array}; } export interface AlarmData extends AlarmInfo { diff --git a/ui-ngx/src/app/shared/models/telemetry/telemetry.models.ts b/ui-ngx/src/app/shared/models/telemetry/telemetry.models.ts index e519fd4a25..04d98567cf 100644 --- a/ui-ngx/src/app/shared/models/telemetry/telemetry.models.ts +++ b/ui-ngx/src/app/shared/models/telemetry/telemetry.models.ts @@ -188,7 +188,6 @@ export interface AggTimeSeriesCmd { keys: Array; startTs: number; timeWindow: number; - floating: boolean; } export class EntityDataCmd implements WebsocketCmd { @@ -315,6 +314,10 @@ export interface SubscriptionData { [key: string]: [number, any, number?][]; } +export interface AggSubscriptionData { + [aggType: string]: SubscriptionData; +} + export interface SubscriptionDataHolder { data: SubscriptionData; } diff --git a/ui-ngx/src/app/shared/models/time/time.models.ts b/ui-ngx/src/app/shared/models/time/time.models.ts index 2f90d39ca1..d657d5cda4 100644 --- a/ui-ngx/src/app/shared/models/time/time.models.ts +++ b/ui-ngx/src/app/shared/models/time/time.models.ts @@ -96,6 +96,8 @@ export interface Timewindow { displayValue?: string; displayTimezoneAbbr?: string; hideInterval?: boolean; + hideQuickInterval?: boolean; + hideLastInterval?: boolean; hideAggregation?: boolean; hideAggInterval?: boolean; hideTimezone?: boolean; @@ -188,6 +190,8 @@ export function defaultTimewindow(timeService: TimeService): Timewindow { return { displayValue: '', hideInterval: false, + hideLastInterval: false, + hideQuickInterval: false, hideAggregation: false, hideAggInterval: false, hideTimezone: false, @@ -223,10 +227,12 @@ function getTimewindowType(timewindow: Timewindow): TimewindowType { } } -export function initModelFromDefaultTimewindow(value: Timewindow, timeService: TimeService): Timewindow { +export function initModelFromDefaultTimewindow(value: Timewindow, quickIntervalOnly: boolean, timeService: TimeService): Timewindow { const model = defaultTimewindow(timeService); if (value) { model.hideInterval = value.hideInterval; + model.hideLastInterval = value.hideLastInterval; + model.hideQuickInterval = value.hideQuickInterval; model.hideAggregation = value.hideAggregation; model.hideAggInterval = value.hideAggInterval; model.hideTimezone = value.hideTimezone; @@ -281,6 +287,9 @@ export function initModelFromDefaultTimewindow(value: Timewindow, timeService: T } model.timezone = value.timezone; } + if (quickIntervalOnly) { + model.realtime.realtimeType = RealtimeWindowType.INTERVAL; + } return model; } @@ -304,6 +313,8 @@ export function toHistoryTimewindow(timewindow: Timewindow, startTimeMs: number, } return { hideInterval: timewindow.hideInterval || false, + hideLastInterval: timewindow.hideLastInterval || false, + hideQuickInterval: timewindow.hideQuickInterval || false, hideAggregation: timewindow.hideAggregation || false, hideAggInterval: timewindow.hideAggInterval || false, hideTimezone: timewindow.hideTimezone || false, @@ -694,6 +705,8 @@ export function createTimewindowForComparison(subscriptionTimewindow: Subscripti export function cloneSelectedTimewindow(timewindow: Timewindow): Timewindow { const cloned: Timewindow = {}; cloned.hideInterval = timewindow.hideInterval || false; + cloned.hideLastInterval = timewindow.hideLastInterval || false; + cloned.hideQuickInterval = timewindow.hideQuickInterval || false; cloned.hideAggregation = timewindow.hideAggregation || false; cloned.hideAggInterval = timewindow.hideAggInterval || false; cloned.hideTimezone = timewindow.hideTimezone || false; diff --git a/ui-ngx/src/app/shared/models/widget.models.ts b/ui-ngx/src/app/shared/models/widget.models.ts index 3d0b1196a5..9efb47758d 100644 --- a/ui-ngx/src/app/shared/models/widget.models.ts +++ b/ui-ngx/src/app/shared/models/widget.models.ts @@ -338,7 +338,7 @@ export interface Datasource { export function datasourcesHasAggregation(datasources?: Array): boolean { if (datasources) { const foundDatasource = datasources.find(datasource => { - const found = datasource.dataKeys.find(key => key.type === DataKeyType.timeseries && + const found = datasource.dataKeys && datasource.dataKeys.find(key => key.type === DataKeyType.timeseries && key.aggregationType && key.aggregationType !== AggregationType.NONE); return !!found; }); From 6879021027e9f8d97560664c50202cd5813ec77d Mon Sep 17 00:00:00 2001 From: Andrii Shvaika Date: Tue, 13 Sep 2022 15:50:50 +0300 Subject: [PATCH 093/108] Fix for multiple commands in same subscription --- ...efaultTbEntityDataSubscriptionService.java | 124 +++++++----------- 1 file changed, 51 insertions(+), 73 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/subscription/DefaultTbEntityDataSubscriptionService.java b/application/src/main/java/org/thingsboard/server/service/subscription/DefaultTbEntityDataSubscriptionService.java index 998938b5e2..99f25861a1 100644 --- a/application/src/main/java/org/thingsboard/server/service/subscription/DefaultTbEntityDataSubscriptionService.java +++ b/application/src/main/java/org/thingsboard/server/service/subscription/DefaultTbEntityDataSubscriptionService.java @@ -29,7 +29,6 @@ import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; import org.springframework.web.socket.CloseStatus; import org.thingsboard.common.util.ThingsBoardThreadFactory; -import org.thingsboard.server.common.data.kv.Aggregation; import org.thingsboard.server.common.data.kv.BaseReadTsKvQuery; import org.thingsboard.server.common.data.kv.ReadTsKvQuery; import org.thingsboard.server.common.data.kv.ReadTsKvQueryResult; @@ -70,7 +69,6 @@ import javax.annotation.PreDestroy; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; -import java.util.HashSet; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; @@ -178,6 +176,8 @@ public class DefaultTbEntityDataSubscriptionService implements TbEntityDataSubsc ctx = createSubCtx(session, cmd); } ctx.setCurrentCmd(cmd); + + // Fetch entity list using entity data query if (cmd.getQuery() != null) { if (ctx.getQuery() == null) { log.debug("[{}][{}] Initializing data using query: {}", session.getSessionId(), cmd.getCmdId(), cmd.getQuery()); @@ -209,54 +209,54 @@ public class DefaultTbEntityDataSubscriptionService implements TbEntityDataSubsc finalCtx.setRefreshTask(task); } } - if (cmd.getAggHistoryCmd() != null) { - handleAggHistoryCmd(ctx, cmd.getAggHistoryCmd(), cmd.getLatestCmd()); - } else if (cmd.getAggTsCmd() != null) { - handleAggTsCmd(ctx, cmd.getAggTsCmd(), cmd.getLatestCmd()); - } else if (cmd.hasRegularCmds()) { - handleRegularCommands(ctx, cmd); - } else { - checkAndSendInitialData(ctx); - } - } - private void handleRegularCommands(TbEntityDataSubCtx ctx, EntityDataCmd cmd) { - ListenableFuture historyFuture; - if (cmd.getHistoryCmd() != null) { - log.trace("[{}][{}] Going to process history command: {}", ctx.getSessionId(), cmd.getCmdId(), cmd.getHistoryCmd()); - try { - historyFuture = handleHistoryCmd(ctx, cmd.getHistoryCmd()); - } catch (RuntimeException e) { - handleWsCmdRuntimeException(ctx.getSessionId(), e, cmd); - return; + try { + List> cmdFutures = new ArrayList<>(); + if (cmd.getAggHistoryCmd() != null) { + cmdFutures.add(handleAggHistoryCmd(ctx, cmd.getAggHistoryCmd())); } - } else { - historyFuture = Futures.immediateFuture(ctx); - } - Futures.addCallback(historyFuture, new FutureCallback<>() { - @Override - public void onSuccess(@Nullable TbEntityDataSubCtx theCtx) { - try { - if (cmd.getLatestCmd() != null || cmd.getTsCmd() != null) { - if (cmd.getLatestCmd() != null) { - handleLatestCmd(theCtx, cmd.getLatestCmd()); - } - if (cmd.getTsCmd() != null) { - handleTimeSeriesCmd(theCtx, cmd.getTsCmd()); - } - } else { - checkAndSendInitialData(theCtx); + if (cmd.getAggTsCmd() != null) { + cmdFutures.add(handleAggTsCmd(ctx, cmd.getAggTsCmd())); + } + if (cmd.getHistoryCmd() != null) { + cmdFutures.add(handleHistoryCmd(ctx, cmd.getHistoryCmd())); + } + if (cmdFutures.isEmpty()) { + handleRegularCommands(ctx, cmd); + } else { + TbEntityDataSubCtx finalCtx = ctx; + Futures.addCallback(Futures.allAsList(cmdFutures), new FutureCallback<>() { + @Override + public void onSuccess(@Nullable List result) { + handleRegularCommands(finalCtx, cmd); } - } catch (RuntimeException e) { - handleWsCmdRuntimeException(theCtx.getSessionId(), e, cmd); - } + + @Override + public void onFailure(Throwable t) { + log.warn("[{}][{}] Failed to process command", finalCtx.getSessionId(), finalCtx.getCmdId()); + } + }, wsCallBackExecutor); } + } catch (RuntimeException e) { + handleWsCmdRuntimeException(ctx.getSessionId(), e, cmd); + } + } - @Override - public void onFailure(Throwable t) { - log.warn("[{}][{}] Failed to process command", ctx.getSessionId(), cmd.getCmdId()); + private void handleRegularCommands(TbEntityDataSubCtx ctx, EntityDataCmd cmd) { + try { + if (cmd.getLatestCmd() != null || cmd.getTsCmd() != null) { + if (cmd.getLatestCmd() != null) { + handleLatestCmd(ctx, cmd.getLatestCmd()); + } + if (cmd.getTsCmd() != null) { + handleTimeSeriesCmd(ctx, cmd.getTsCmd()); + } + } else { + checkAndSendInitialData(ctx); } - }, wsCallBackExecutor); + } catch (RuntimeException e) { + handleWsCmdRuntimeException(ctx.getSessionId(), e, cmd); + } } private void checkAndSendInitialData(@Nullable TbEntityDataSubCtx theCtx) { @@ -267,30 +267,30 @@ public class DefaultTbEntityDataSubscriptionService implements TbEntityDataSubsc } } - private void handleAggHistoryCmd(TbEntityDataSubCtx ctx, AggHistoryCmd cmd, LatestValueCmd latestCmd) { + private ListenableFuture handleAggHistoryCmd(TbEntityDataSubCtx ctx, AggHistoryCmd cmd) { var keys = cmd.getKeys(); long interval = cmd.getEndTs() - cmd.getStartTs(); List queries = keys.stream().map(key -> new BaseReadTsKvQuery( key.getKey(), cmd.getStartTs(), cmd.getEndTs(), interval, 1, key.getAgg() )).distinct().collect(Collectors.toList()); - handleAggCmd(ctx, cmd.getKeys(), queries, cmd.getStartTs(), cmd.getEndTs(), latestCmd, false); + return handleAggCmd(ctx, cmd.getKeys(), queries, cmd.getStartTs(), cmd.getEndTs(), false); } - private void handleAggTsCmd(TbEntityDataSubCtx ctx, AggTimeSeriesCmd cmd, LatestValueCmd latestCmd) { + private ListenableFuture handleAggTsCmd(TbEntityDataSubCtx ctx, AggTimeSeriesCmd cmd) { long endTs = cmd.getStartTs() + cmd.getTimeWindow(); List queries = cmd.getKeys().stream() .map(key -> new BaseReadTsKvQuery(key.getKey(), cmd.getStartTs(), endTs, cmd.getTimeWindow(), 1, key.getAgg())) .distinct().collect(Collectors.toList()); - handleAggCmd(ctx, cmd.getKeys(), queries, cmd.getStartTs(), endTs, latestCmd, true); + return handleAggCmd(ctx, cmd.getKeys(), queries, cmd.getStartTs(), endTs, true); } - private void handleAggCmd(TbEntityDataSubCtx ctx, List keys, List queries, - long startTs, long endTs, LatestValueCmd latestCmd, boolean subscribe) { + private ListenableFuture handleAggCmd(TbEntityDataSubCtx ctx, List keys, List queries, + long startTs, long endTs, boolean subscribe) { Map>> fetchResultMap = new HashMap<>(); List entityDataList = ctx.getData().getData(); entityDataList.forEach(entityData -> fetchResultMap.put(entityData, tsService.findAllByQueries(ctx.getTenantId(), entityData.getEntityId(), queries))); - var mainFuture = Futures.transform(Futures.allAsList(fetchResultMap.values()), f -> { + return Futures.transform(Futures.allAsList(fetchResultMap.values()), f -> { // Map that holds last ts for each key for each entity. Map> lastTsEntityMap = new HashMap<>(); fetchResultMap.forEach((entityData, future) -> { @@ -333,28 +333,6 @@ public class DefaultTbEntityDataSubscriptionService implements TbEntityDataSubsc } return ctx; }, wsCallBackExecutor); - - Futures.addCallback(mainFuture, new FutureCallback<>() { - - @Override - public void onSuccess(@Nullable TbEntityDataSubCtx theCtx) { - if (latestCmd != null) { - if (subscribe) { - var commandEntityKeys = new HashSet<>(latestCmd.getKeys()); - var alreadySubscribedKeys = keys.stream().map(key -> new EntityKey(EntityKeyType.TIME_SERIES, key.getKey())).collect(Collectors.toList()); - if (commandEntityKeys.removeAll(alreadySubscribedKeys)) { - latestCmd.setKeys(new ArrayList<>(commandEntityKeys)); - } - } - handleLatestCmd(ctx, latestCmd); - } - } - - @Override - public void onFailure(Throwable t) { - log.warn("[{}][{}] Failed to process command", ctx.getSessionId(), ctx.getCmdId()); - } - }, wsCallBackExecutor); } private void handleWsCmdRuntimeException(String sessionId, RuntimeException e, EntityDataCmd cmd) { From 355d09569b3cf8c14494b93ba0f124e2a77bac5f Mon Sep 17 00:00:00 2001 From: nickAS21 Date: Tue, 13 Sep 2022 16:36:01 +0300 Subject: [PATCH 094/108] fix_bug: commit --- .../server/service/queue/DefaultTbClusterService.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbClusterService.java b/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbClusterService.java index c3df3c6522..8ec29672de 100644 --- a/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbClusterService.java +++ b/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbClusterService.java @@ -165,10 +165,7 @@ public class DefaultTbClusterService implements TbClusterService { @Override public void pushMsgToRuleEngine(TenantId tenantId, EntityId entityId, TbMsg tbMsg, TbQueueCallback callback) { - if (tenantId == null) { - log.warn("tenantId [null] [{}] Received invalid message: {}", entityId, tbMsg); - return; - } else if (tenantId.isNullUid()) { + if (tenantId == null || tenantId.isNullUid()) { if (entityId.getEntityType().equals(EntityType.TENANT)) { tenantId = TenantId.fromUUID(entityId.getId()); } else { From cb307ce9a5b533098924e45d89452412525312c8 Mon Sep 17 00:00:00 2001 From: Igor Kulikov Date: Tue, 13 Sep 2022 17:01:52 +0300 Subject: [PATCH 095/108] UI: Add latest data support to tooltip value format function of flot widget. --- .../app/core/api/entity-data-subscription.ts | 13 +++-- .../widget/lib/flot-widget.models.ts | 4 +- .../home/components/widget/lib/flot-widget.ts | 49 ++++++++++++++++--- .../chart/flot-key-settings.component.html | 2 +- .../chart/flot-widget-settings.component.html | 2 +- 5 files changed, 53 insertions(+), 17 deletions(-) diff --git a/ui-ngx/src/app/core/api/entity-data-subscription.ts b/ui-ngx/src/app/core/api/entity-data-subscription.ts index 0d6c534e4c..8032a32973 100644 --- a/ui-ngx/src/app/core/api/entity-data-subscription.ts +++ b/ui-ngx/src/app/core/api/entity-data-subscription.ts @@ -457,7 +457,7 @@ export class EntityDataSubscription { } this.prepareSubscriptionTimewindow(); - this.prepareData(); + this.prepareData(true); if (this.datasourceType === DatasourceType.entity) { this.subsCommand = new EntityDataCmd(); @@ -567,7 +567,7 @@ export class EntityDataSubscription { this.generateData(true); } - private prepareData() { + private prepareData(isUpdate: boolean) { if (this.timeseriesTimer) { clearTimeout(this.timeseriesTimer); this.timeseriesTimer = null; @@ -641,11 +641,14 @@ export class EntityDataSubscription { for (let dataIndex = 0; dataIndex < this.pageData.data.length; dataIndex++) { this.onAggData(aggSubscriptionData, DataKeyType.timeseries, dataIndex, true, this.entityDataSubscriptionOptions.type === widgetType.timeseries, true, - (data1, dataIndex1, dataKeyIndex) => { + (data, dataIndex1, dataKeyIndex, detectChanges, isLatest) => { if (!this.data[dataIndex1]) { this.data[dataIndex1] = []; } - this.data[dataIndex1][dataKeyIndex] = data1; + this.data[dataIndex1][dataKeyIndex] = data; + if (isUpdate) { + this.notifyListener(data, dataIndex1, dataKeyIndex, detectChanges, isLatest); + } }); } } @@ -706,7 +709,7 @@ export class EntityDataSubscription { this.pageData = pageData; if (this.entityDataSubscriptionOptions.isPaginatedDataSubscription) { - this.prepareData(); + this.prepareData(false); } else if (isInitialData) { this.resetData(); } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/flot-widget.models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/flot-widget.models.ts index 595384abaf..78c9245614 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/flot-widget.models.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/flot-widget.models.ts @@ -17,7 +17,7 @@ // tslint:disable-next-line:no-reference /// -import { DataKey, Datasource, DatasourceData, JsonSettingsSchema } from '@shared/models/widget.models'; +import { DataKey, Datasource, DatasourceData, FormattedData, JsonSettingsSchema } from '@shared/models/widget.models'; import { DataKeyType } from '@shared/models/telemetry/telemetry.models'; import { ComparisonDuration } from '@shared/models/time/time.models'; @@ -25,7 +25,7 @@ export declare type ChartType = 'line' | 'pie' | 'bar' | 'state' | 'graph'; export declare type TbFlotSettings = TbFlotBaseSettings & TbFlotGraphSettings & TbFlotBarSettings & TbFlotPieSettings; -export declare type TooltipValueFormatFunction = (value: any) => string; +export declare type TooltipValueFormatFunction = (value: any, latestData: FormattedData) => string; export declare type TbFlotTicksFormatterFunction = (t: number, a?: TbFlotPlotAxis) => string; diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/flot-widget.ts b/ui-ngx/src/app/modules/home/components/widget/lib/flot-widget.ts index bf59e36804..c601df72d4 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/flot-widget.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/flot-widget.ts @@ -18,7 +18,7 @@ import { WidgetContext } from '@home/models/widget-component.models'; import { createLabelFromDatasource, - deepClone, + deepClone, formattedDataFormDatasourceData, insertVariable, isDefined, isDefinedAndNotNull, @@ -28,7 +28,14 @@ import { isUndefined } from '@app/core/utils'; import { IWidgetSubscription, WidgetSubscriptionOptions } from '@core/api/widget-api.models'; -import { DataKey, Datasource, DatasourceData, DatasourceType, widgetType } from '@app/shared/models/widget.models'; +import { + DataKey, + Datasource, + DatasourceData, + DatasourceType, + FormattedData, + widgetType +} from '@app/shared/models/widget.models'; import { ChartType, TbFlotAxisOptions, @@ -88,6 +95,8 @@ export class TbFlot { private latestDataThresholds: TbFlotThresholdMarking[]; private attributesThresholds: TbFlotThresholdMarking[]; + private latestData: FormattedData[]; + private labelPatternsSourcesSubscription: IWidgetSubscription; private labelPatternsSourcesData: DatasourceData[]; @@ -379,7 +388,7 @@ export class TbFlot { let tooltipValueFormatFunction: TooltipValueFormatFunction = null; if (this.settings.tooltipValueFormatter && this.settings.tooltipValueFormatter.length) { try { - tooltipValueFormatFunction = new Function('value', this.settings.tooltipValueFormatter) as TooltipValueFormatFunction; + tooltipValueFormatFunction = new Function('value', 'latestData', this.settings.tooltipValueFormatter) as TooltipValueFormatFunction; } catch (e) { tooltipValueFormatFunction = null; } @@ -392,7 +401,7 @@ export class TbFlot { series.dataKey.tooltipValueFormatFunction = tooltipValueFormatFunction; if (keySettings.tooltipValueFormatter && keySettings.tooltipValueFormatter.length) { try { - series.dataKey.tooltipValueFormatFunction = new Function('value', + series.dataKey.tooltipValueFormatFunction = new Function('value', 'latestData', keySettings.tooltipValueFormatter) as TooltipValueFormatFunction; } catch (e) { series.dataKey.tooltipValueFormatFunction = tooltipValueFormatFunction; @@ -546,6 +555,13 @@ export class TbFlot { } this.latestDataThresholds = this.thresholdsSourcesDataUpdated(allThresholds, this.subscription.latestData, true); this.options.grid.markings = allThresholds.concat(this.latestDataThresholds); + if (this.subscription.latestData) { + this.latestData = formattedDataFormDatasourceData(this.subscription.latestData); + } else { + this.latestData = []; + } + } else if (this.chartType === 'pie') { + this.latestData = formattedDataFormDatasourceData(this.subscription.data); } this.checkMouseEvents(); @@ -653,6 +669,7 @@ export class TbFlot { this.updateData(); } } else if (this.chartType === 'pie') { + this.latestData = formattedDataFormDatasourceData(this.subscription.data); if (this.animatedPie) { this.nextPieDataAnimation(true); } else { @@ -683,6 +700,11 @@ export class TbFlot { this.plot.getOptions().grid.markings = this.options.grid.markings; this.updateData(); } + if (this.subscription.latestData) { + this.latestData = formattedDataFormDatasourceData(this.subscription.latestData); + } else { + this.latestData = []; + } } } else if (this.isMouseInteraction && this.plot) { this.latestUpdateTimeoutHandle = setTimeout(this.latestDataUpdate.bind(this), 30); @@ -690,6 +712,14 @@ export class TbFlot { } } + private latestDataByDataIndex(index: number): FormattedData { + if (this.latestData[index]) { + return this.latestData[index]; + } else { + return {} as FormattedData; + } + } + private scalingPieRadius() { let scalingLine; this.ctx.width > this.ctx.height ? scalingLine = this.ctx.height : scalingLine = this.ctx.width; @@ -1004,7 +1034,8 @@ export class TbFlot { private seriesInfoDiv(label: string, color: string, value: any, units: string, trackDecimals: number, active: boolean, - percent: number, valueFormatFunction: TooltipValueFormatFunction): JQuery { + percent: number, seriesIndex: number, + valueFormatFunction: TooltipValueFormatFunction): JQuery { const divElement = $('
'); divElement.css({ display: 'flex', @@ -1034,7 +1065,7 @@ export class TbFlot { divElement.append(labelSpan); let valueContent: string; if (valueFormatFunction) { - valueContent = valueFormatFunction(value); + valueContent = valueFormatFunction(value, this.latestDataByDataIndex(seriesIndex)); } else { valueContent = this.ctx.utils.formatValue(value, trackDecimals, units); } @@ -1059,7 +1090,8 @@ export class TbFlot { const units = seriesHoverInfo.units && seriesHoverInfo.units.length ? seriesHoverInfo.units : this.trackUnits; const decimals = isDefinedAndNotNull(seriesHoverInfo.decimals) ? seriesHoverInfo.decimals : this.trackDecimals; const divElement = this.seriesInfoDiv(seriesHoverInfo.label, seriesHoverInfo.color, - seriesHoverInfo.value, units, decimals, seriesHoverInfo.index === seriesIndex, null, seriesHoverInfo.tooltipValueFormatFunction); + seriesHoverInfo.value, units, decimals, seriesHoverInfo.index === seriesIndex, null, seriesHoverInfo.index, + seriesHoverInfo.tooltipValueFormatFunction); return divElement.prop('outerHTML'); } @@ -1086,7 +1118,8 @@ export class TbFlot { const units = item.series.dataKey.units && item.series.dataKey.units.length ? item.series.dataKey.units : this.trackUnits; const decimals = isDefinedAndNotNull(item.series.dataKey.decimals) ? item.series.dataKey.decimals : this.trackDecimals; const divElement = this.seriesInfoDiv(item.series.dataKey.label, item.series.dataKey.color, - item.datapoint[1][0][1], units, decimals, true, item.series.percent, item.series.dataKey.tooltipValueFormatFunction); + item.datapoint[1][0][1], units, decimals, true, item.series.percent, 0, + item.series.dataKey.tooltipValueFormatFunction); return divElement.prop('outerHTML'); } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-key-settings.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-key-settings.component.html index 05879cb124..5741bfae9f 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-key-settings.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-key-settings.component.html @@ -123,7 +123,7 @@ diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-widget-settings.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-widget-settings.component.html index beebf38268..06b9bc5f86 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-widget-settings.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-widget-settings.component.html @@ -96,7 +96,7 @@ From 369af93e51b6e7cb6480af13ce7c0515629541de Mon Sep 17 00:00:00 2001 From: Yuriy Lytvynchuk Date: Tue, 13 Sep 2022 17:09:04 +0300 Subject: [PATCH 096/108] fixbug --- .../rule/engine/metadata/TbGetTelemetryNode.java | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTelemetryNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTelemetryNode.java index 320502005b..914eb4cddd 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTelemetryNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTelemetryNode.java @@ -91,7 +91,9 @@ public class TbGetTelemetryNode implements TbNode { orderByFetchAll = ASC_ORDER; } aggregation = parseAggregationConfig(config.getAggregation()); - + if (!fetchMode.equals(FETCH_MODE_ALL)) { + aggregation = Aggregation.NONE; + } mapper = new ObjectMapper(); mapper.configure(JsonWriteFeature.QUOTE_FIELD_NAMES.mappedFeature(), false); mapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true); @@ -236,16 +238,16 @@ public class TbGetTelemetryNode implements TbNode { } private void isUndefined(TbMsg msg, String startIntervalPattern, String endIntervalPattern) { - if (getMetadataValue(msg, startIntervalPattern) == null && getMetadataValue(msg, endIntervalPattern) == null) { + if (getValuePattern(msg, startIntervalPattern) == null && getValuePattern(msg, endIntervalPattern) == null) { throw new IllegalArgumentException("Message metadata values: '" + replaceRegex(startIntervalPattern) + "' and '" + replaceRegex(endIntervalPattern) + "' are undefined"); } else { - if (getMetadataValue(msg, startIntervalPattern) == null) { + if (getValuePattern(msg, startIntervalPattern) == null) { throw new IllegalArgumentException("Message metadata value: '" + replaceRegex(startIntervalPattern) + "' is undefined"); } - if (getMetadataValue(msg, endIntervalPattern) == null) { + if (getValuePattern(msg, endIntervalPattern) == null) { throw new IllegalArgumentException("Message metadata value: '" + replaceRegex(endIntervalPattern) + "' is undefined"); } @@ -269,8 +271,9 @@ public class TbGetTelemetryNode implements TbNode { } } - private String getMetadataValue(TbMsg msg, String pattern) { - return msg.getMetaData().getValue(replaceRegex(pattern)); + private String getValuePattern(TbMsg msg, String pattern) { + String valuePattern = TbNodeUtils.processPattern(pattern, msg); + return valuePattern.equals(pattern) ? null : valuePattern; } private String replaceRegex(String pattern) { From 9d30b7558fbd472003a9b0f840b65fe4f05b7f56 Mon Sep 17 00:00:00 2001 From: Andrii Shvaika Date: Wed, 14 Sep 2022 14:22:43 +0300 Subject: [PATCH 097/108] Support of Comparison Queries --- ...efaultTbEntityDataSubscriptionService.java | 73 +++++++++++++------ .../subscription/ReadTsKvQueryInfo.java | 29 ++++++++ .../service/telemetry/cmd/v2/AggKey.java | 6 ++ .../common/data/kv/BaseReadTsKvQuery.java | 3 +- .../server/common/data/kv/BaseTsKvQuery.java | 5 ++ .../common/data/kv/ReadTsKvQueryResult.java | 4 +- .../server/common/data/kv/TsKvQuery.java | 2 + .../common/data/query/ComparisonTsValue.java | 29 ++++++++ .../server/common/data/query/EntityData.java | 4 +- ...stractChunkedAggregationTimeseriesDao.java | 2 +- .../sqlts/BaseAbstractSqlTimeseriesDao.java | 2 +- .../timescale/TimescaleTimeseriesDao.java | 2 +- .../dao/timeseries/BaseTimeseriesService.java | 1 + .../CassandraBaseTimeseriesDao.java | 6 +- 14 files changed, 131 insertions(+), 37 deletions(-) create mode 100644 application/src/main/java/org/thingsboard/server/service/subscription/ReadTsKvQueryInfo.java create mode 100644 common/data/src/main/java/org/thingsboard/server/common/data/query/ComparisonTsValue.java diff --git a/application/src/main/java/org/thingsboard/server/service/subscription/DefaultTbEntityDataSubscriptionService.java b/application/src/main/java/org/thingsboard/server/service/subscription/DefaultTbEntityDataSubscriptionService.java index 99f25861a1..b583446f17 100644 --- a/application/src/main/java/org/thingsboard/server/service/subscription/DefaultTbEntityDataSubscriptionService.java +++ b/application/src/main/java/org/thingsboard/server/service/subscription/DefaultTbEntityDataSubscriptionService.java @@ -35,6 +35,7 @@ import org.thingsboard.server.common.data.kv.ReadTsKvQueryResult; import org.thingsboard.server.common.data.kv.TsKvEntry; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.query.AlarmDataQuery; +import org.thingsboard.server.common.data.query.ComparisonTsValue; import org.thingsboard.server.common.data.query.EntityData; import org.thingsboard.server.common.data.query.EntityDataQuery; import org.thingsboard.server.common.data.query.EntityKey; @@ -74,6 +75,7 @@ import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -268,28 +270,36 @@ public class DefaultTbEntityDataSubscriptionService implements TbEntityDataSubsc } private ListenableFuture handleAggHistoryCmd(TbEntityDataSubCtx ctx, AggHistoryCmd cmd) { - var keys = cmd.getKeys(); - long interval = cmd.getEndTs() - cmd.getStartTs(); - List queries = keys.stream().map(key -> new BaseReadTsKvQuery( - key.getKey(), cmd.getStartTs(), cmd.getEndTs(), interval, 1, key.getAgg() - )).distinct().collect(Collectors.toList()); + ConcurrentMap queries = new ConcurrentHashMap<>(); + for (AggKey key : cmd.getKeys()) { + if (key.getPreviousValueOnly() == null || !key.getPreviousValueOnly()) { + var query = new BaseReadTsKvQuery(key.getKey(), cmd.getStartTs(), cmd.getEndTs(), cmd.getEndTs() - cmd.getStartTs(), 1, key.getAgg()); + queries.put(query.getId(), new ReadTsKvQueryInfo(key, query, false)); + } + if (key.getPreviousStartTs() != null && key.getPreviousEndTs() != null && key.getPreviousEndTs() >= key.getPreviousStartTs()) { + var query = new BaseReadTsKvQuery(key.getKey(), key.getPreviousStartTs(), key.getPreviousEndTs(), key.getPreviousEndTs() - key.getPreviousStartTs(), 1, key.getAgg()); + queries.put(query.getId(), new ReadTsKvQueryInfo(key, query, true)); + } + } return handleAggCmd(ctx, cmd.getKeys(), queries, cmd.getStartTs(), cmd.getEndTs(), false); } private ListenableFuture handleAggTsCmd(TbEntityDataSubCtx ctx, AggTimeSeriesCmd cmd) { - long endTs = cmd.getStartTs() + cmd.getTimeWindow(); - List queries = cmd.getKeys().stream() - .map(key -> new BaseReadTsKvQuery(key.getKey(), cmd.getStartTs(), endTs, cmd.getTimeWindow(), 1, key.getAgg())) - .distinct().collect(Collectors.toList()); - return handleAggCmd(ctx, cmd.getKeys(), queries, cmd.getStartTs(), endTs, true); + ConcurrentMap queries = new ConcurrentHashMap<>(); + for (AggKey key : cmd.getKeys()) { + var query = new BaseReadTsKvQuery(key.getKey(), cmd.getStartTs(), cmd.getStartTs() + cmd.getTimeWindow(), cmd.getTimeWindow(), 1, key.getAgg()); + queries.put(query.getId(), new ReadTsKvQueryInfo(key, query, false)); + } + return handleAggCmd(ctx, cmd.getKeys(), queries, cmd.getStartTs(), cmd.getStartTs() + cmd.getTimeWindow(), true); } - private ListenableFuture handleAggCmd(TbEntityDataSubCtx ctx, List keys, List queries, + private ListenableFuture handleAggCmd(TbEntityDataSubCtx ctx, List keys, ConcurrentMap queries, long startTs, long endTs, boolean subscribe) { Map>> fetchResultMap = new HashMap<>(); List entityDataList = ctx.getData().getData(); + List queryList = queries.values().stream().map(ReadTsKvQueryInfo::getQuery).collect(Collectors.toList()); entityDataList.forEach(entityData -> fetchResultMap.put(entityData, - tsService.findAllByQueries(ctx.getTenantId(), entityData.getEntityId(), queries))); + tsService.findAllByQueries(ctx.getTenantId(), entityData.getEntityId(), queryList))); return Futures.transform(Futures.allAsList(fetchResultMap.values()), f -> { // Map that holds last ts for each key for each entity. Map> lastTsEntityMap = new HashMap<>(); @@ -301,13 +311,19 @@ public class DefaultTbEntityDataSubscriptionService implements TbEntityDataSubsc List queryResults = future.get(); if (queryResults != null) { for (ReadTsKvQueryResult queryResult : queryResults) { - entityData.getAggLatest().computeIfAbsent(queryResult.getAgg(), agg -> new HashMap<>()).put(queryResult.getKey(), queryResult.toTsValue()); - lastTsMap.put(queryResult.getKey(), queryResult.getLastEntryTs()); + ReadTsKvQueryInfo queryInfo = queries.get(queryResult.getQueryId()); + ComparisonTsValue comparisonTsValue = entityData.getAggLatest().computeIfAbsent(queryInfo.getKey().getId(), agg -> new ComparisonTsValue()); + if (queryInfo.isPrevious()) { + comparisonTsValue.setPrevious(queryResult.toTsValue()); + } else { + comparisonTsValue.setCurrent(queryResult.toTsValue()); + lastTsMap.put(queryInfo.getQuery().getKey(), queryResult.getLastEntryTs()); + } } } // Populate with empty values if no data found. keys.forEach(key -> { - entityData.getAggLatest().computeIfAbsent(key.getAgg(), agg -> new HashMap<>()).putIfAbsent(key.getKey(), TsValue.EMPTY); + entityData.getAggLatest().putIfAbsent(key.getId(), new ComparisonTsValue(TsValue.EMPTY, TsValue.EMPTY)); }); } catch (InterruptedException | ExecutionException e) { log.warn("[{}][{}][{}] Failed to fetch historical data", ctx.getSessionId(), ctx.getCmdId(), entityData.getEntityId(), e); @@ -507,16 +523,26 @@ public class DefaultTbEntityDataSubscriptionService implements TbEntityDataSubsc } private ListenableFuture handleGetTsCmd(TbEntityDataSubCtx ctx, GetTsCmd cmd, boolean subscribe) { + Map queriesKeys = new ConcurrentHashMap<>(); + List keys = cmd.getKeys(); List finalTsKvQueryList; - List tsKvQueryList = keys.stream().map(key -> new BaseReadTsKvQuery( - key, cmd.getStartTs(), cmd.getEndTs(), cmd.getInterval(), getLimit(cmd.getLimit()), cmd.getAgg() - )).collect(Collectors.toList()); + List tsKvQueryList = keys.stream().map(key -> { + var query = new BaseReadTsKvQuery( + key, cmd.getStartTs(), cmd.getEndTs(), cmd.getInterval(), getLimit(cmd.getLimit()), cmd.getAgg() + ); + queriesKeys.put(query.getId(), query.getKey()); + return query; + }).collect(Collectors.toList()); if (cmd.isFetchLatestPreviousPoint()) { finalTsKvQueryList = new ArrayList<>(tsKvQueryList); - finalTsKvQueryList.addAll(keys.stream().map(key -> new BaseReadTsKvQuery( - key, cmd.getStartTs() - TimeUnit.DAYS.toMillis(365), cmd.getStartTs(), cmd.getInterval(), 1, cmd.getAgg() - )).collect(Collectors.toList())); + finalTsKvQueryList.addAll(keys.stream().map(key -> { + var query = new BaseReadTsKvQuery( + key, cmd.getStartTs() - TimeUnit.DAYS.toMillis(365), cmd.getStartTs(), cmd.getInterval(), 1, cmd.getAgg()); + queriesKeys.put(query.getId(), query.getKey()); + return query; + } + ).collect(Collectors.toList())); } else { finalTsKvQueryList = tsKvQueryList; } @@ -535,8 +561,9 @@ public class DefaultTbEntityDataSubscriptionService implements TbEntityDataSubsc List queryResults = future.get(); if (queryResults != null) { for (ReadTsKvQueryResult queryResult : queryResults) { - entityData.getTimeseries().put(queryResult.getKey(), queryResult.toTsValues()); - lastTsMap.put(queryResult.getKey(), queryResult.getLastEntryTs()); + String queryKey = queriesKeys.get(queryResult.getQueryId()); + entityData.getTimeseries().put(queryKey, queryResult.toTsValues()); + lastTsMap.put(queryKey, queryResult.getLastEntryTs()); } } // Populate with empty values if no data found. diff --git a/application/src/main/java/org/thingsboard/server/service/subscription/ReadTsKvQueryInfo.java b/application/src/main/java/org/thingsboard/server/service/subscription/ReadTsKvQueryInfo.java new file mode 100644 index 0000000000..28ca2f6729 --- /dev/null +++ b/application/src/main/java/org/thingsboard/server/service/subscription/ReadTsKvQueryInfo.java @@ -0,0 +1,29 @@ +/** + * Copyright © 2016-2022 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.service.subscription; + +import lombok.Data; +import org.thingsboard.server.common.data.kv.ReadTsKvQuery; +import org.thingsboard.server.service.telemetry.cmd.v2.AggKey; + +@Data +public class ReadTsKvQueryInfo { + + private final AggKey key; + private final ReadTsKvQuery query; + private final boolean previous; + +} diff --git a/application/src/main/java/org/thingsboard/server/service/telemetry/cmd/v2/AggKey.java b/application/src/main/java/org/thingsboard/server/service/telemetry/cmd/v2/AggKey.java index aaf3997193..d567149d01 100644 --- a/application/src/main/java/org/thingsboard/server/service/telemetry/cmd/v2/AggKey.java +++ b/application/src/main/java/org/thingsboard/server/service/telemetry/cmd/v2/AggKey.java @@ -21,6 +21,12 @@ import org.thingsboard.server.common.data.kv.Aggregation; @Data public class AggKey { + private int id; private String key; private Aggregation agg; + + private Long previousStartTs; + private Long previousEndTs; + private Boolean previousValueOnly; + } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/kv/BaseReadTsKvQuery.java b/common/data/src/main/java/org/thingsboard/server/common/data/kv/BaseReadTsKvQuery.java index fc111da8e2..29b98d5e83 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/kv/BaseReadTsKvQuery.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/kv/BaseReadTsKvQuery.java @@ -31,8 +31,7 @@ public class BaseReadTsKvQuery extends BaseTsKvQuery implements ReadTsKvQuery { this(key, startTs, endTs, interval, limit, aggregation, "DESC"); } - public BaseReadTsKvQuery(String key, long startTs, long endTs, long interval, int limit, Aggregation aggregation, - String order) { + public BaseReadTsKvQuery(String key, long startTs, long endTs, long interval, int limit, Aggregation aggregation, String order) { super(key, startTs, endTs); this.interval = interval; this.limit = limit; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/kv/BaseTsKvQuery.java b/common/data/src/main/java/org/thingsboard/server/common/data/kv/BaseTsKvQuery.java index 4102b30a6f..245af53d55 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/kv/BaseTsKvQuery.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/kv/BaseTsKvQuery.java @@ -20,11 +20,16 @@ import lombok.Data; @Data public class BaseTsKvQuery implements TsKvQuery { + private static final ThreadLocal idSeq = ThreadLocal.withInitial(() -> 0); + + private final int id; private final String key; private final long startTs; private final long endTs; public BaseTsKvQuery(String key, long startTs, long endTs) { + this.id = idSeq.get(); + idSeq.set(id + 1); this.key = key; this.startTs = startTs; this.endTs = endTs; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/kv/ReadTsKvQueryResult.java b/common/data/src/main/java/org/thingsboard/server/common/data/kv/ReadTsKvQueryResult.java index 26a8a0c2c5..9c7a2f1754 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/kv/ReadTsKvQueryResult.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/kv/ReadTsKvQueryResult.java @@ -24,9 +24,7 @@ import java.util.List; @Data public class ReadTsKvQueryResult { - private final String key; - // Holds the aggregation from the query - private final Aggregation agg; + private final int queryId; // Holds the data list; private final List data; // Holds the max ts of the records that match aggregation intervals (not the ts of the aggregation window, but the ts of the last record among all the intervals) diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/kv/TsKvQuery.java b/common/data/src/main/java/org/thingsboard/server/common/data/kv/TsKvQuery.java index cf01c322a5..78bf01c0e9 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/kv/TsKvQuery.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/kv/TsKvQuery.java @@ -17,6 +17,8 @@ package org.thingsboard.server.common.data.kv; public interface TsKvQuery { + int getId(); + String getKey(); long getStartTs(); diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/query/ComparisonTsValue.java b/common/data/src/main/java/org/thingsboard/server/common/data/query/ComparisonTsValue.java new file mode 100644 index 0000000000..301fbdb0ee --- /dev/null +++ b/common/data/src/main/java/org/thingsboard/server/common/data/query/ComparisonTsValue.java @@ -0,0 +1,29 @@ +/** + * Copyright © 2016-2022 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.common.data.query; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class ComparisonTsValue { + + private TsValue current; + private TsValue previous; +} diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/query/EntityData.java b/common/data/src/main/java/org/thingsboard/server/common/data/query/EntityData.java index f1445faaab..2b24866ac4 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/query/EntityData.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/query/EntityData.java @@ -15,11 +15,9 @@ */ package org.thingsboard.server.common.data.query; -import lombok.AllArgsConstructor; import lombok.Data; import lombok.RequiredArgsConstructor; import org.thingsboard.server.common.data.id.EntityId; -import org.thingsboard.server.common.data.kv.Aggregation; import java.util.Map; @@ -30,7 +28,7 @@ public class EntityData { private final EntityId entityId; private final Map> latest; private final Map timeseries; - private final Map> aggLatest; + private final Map aggLatest; public EntityData(EntityId entityId, Map> latest, Map timeseries) { this(entityId, latest, timeseries, null); diff --git a/dao/src/main/java/org/thingsboard/server/dao/sqlts/AbstractChunkedAggregationTimeseriesDao.java b/dao/src/main/java/org/thingsboard/server/dao/sqlts/AbstractChunkedAggregationTimeseriesDao.java index b5905dcf7d..9acbfe85fb 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sqlts/AbstractChunkedAggregationTimeseriesDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sqlts/AbstractChunkedAggregationTimeseriesDao.java @@ -149,7 +149,7 @@ public abstract class AbstractChunkedAggregationTimeseriesDao extends AbstractSq tsKvEntities.forEach(tsKvEntity -> tsKvEntity.setStrKey(query.getKey())); List tsKvEntries = DaoUtil.convertDataList(tsKvEntities); long lastTs = tsKvEntries.stream().map(TsKvEntry::getTs).max(Long::compare).orElse(query.getStartTs()); - return new ReadTsKvQueryResult(query.getKey(), query.getAggregation(), tsKvEntries, lastTs); + return new ReadTsKvQueryResult(query.getId(), tsKvEntries, lastTs); } Optional findAndAggregateAsync(EntityId entityId, String key, long startTs, long endTs, long ts, Aggregation aggregation) { diff --git a/dao/src/main/java/org/thingsboard/server/dao/sqlts/BaseAbstractSqlTimeseriesDao.java b/dao/src/main/java/org/thingsboard/server/dao/sqlts/BaseAbstractSqlTimeseriesDao.java index 27bb3307be..1946198505 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sqlts/BaseAbstractSqlTimeseriesDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sqlts/BaseAbstractSqlTimeseriesDao.java @@ -99,7 +99,7 @@ public abstract class BaseAbstractSqlTimeseriesDao extends JpaAbstractDaoListeni if (lastTs.isEmpty()) { lastTs = data.stream().map(AbstractTsKvEntity::getTs).filter(Objects::nonNull).max(Long::compare); } - return new ReadTsKvQueryResult(query.getKey(), query.getAggregation(), DaoUtil.convertDataList(data), lastTs.orElse(query.getStartTs())); + return new ReadTsKvQueryResult(query.getId(), DaoUtil.convertDataList(data), lastTs.orElse(query.getStartTs())); } }, service); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sqlts/timescale/TimescaleTimeseriesDao.java b/dao/src/main/java/org/thingsboard/server/dao/sqlts/timescale/TimescaleTimeseriesDao.java index 9f2763fde9..76dabb24f6 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sqlts/timescale/TimescaleTimeseriesDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sqlts/timescale/TimescaleTimeseriesDao.java @@ -181,7 +181,7 @@ public class TimescaleTimeseriesDao extends AbstractSqlTimeseriesDao implements timescaleTsKvEntities.forEach(tsKvEntity -> tsKvEntity.setStrKey(strKey)); var tsKvEntries = DaoUtil.convertDataList(timescaleTsKvEntities); long lastTs = tsKvEntries.stream().map(TsKvEntry::getTs).max(Long::compare).orElse(query.getStartTs()); - return new ReadTsKvQueryResult(query.getKey(), query.getAggregation(), tsKvEntries, lastTs); + return new ReadTsKvQueryResult(query.getId(), tsKvEntries, lastTs); } private List> findAllAndAggregateAsync(EntityId entityId, String key, long startTs, long endTs, long timeBucket, Aggregation aggregation) { diff --git a/dao/src/main/java/org/thingsboard/server/dao/timeseries/BaseTimeseriesService.java b/dao/src/main/java/org/thingsboard/server/dao/timeseries/BaseTimeseriesService.java index b785ae2f9d..b4cb27cb53 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/timeseries/BaseTimeseriesService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/timeseries/BaseTimeseriesService.java @@ -46,6 +46,7 @@ import org.thingsboard.server.dao.service.Validator; import java.util.Collection; import java.util.Collections; import java.util.List; +import java.util.Map; import java.util.stream.Collectors; import static org.thingsboard.server.common.data.StringUtils.isBlank; diff --git a/dao/src/main/java/org/thingsboard/server/dao/timeseries/CassandraBaseTimeseriesDao.java b/dao/src/main/java/org/thingsboard/server/dao/timeseries/CassandraBaseTimeseriesDao.java index 01450bbb55..35eb5b8a18 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/timeseries/CassandraBaseTimeseriesDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/timeseries/CassandraBaseTimeseriesDao.java @@ -285,7 +285,7 @@ public class CassandraBaseTimeseriesDao extends AbstractCassandraBaseTimeseriesD @Override public ReadTsKvQueryResult apply(@Nullable List> input) { if (input == null) { - return new ReadTsKvQueryResult(query.getKey(), query.getAggregation(), Collections.emptyList(), query.getStartTs()); + return new ReadTsKvQueryResult(query.getId(), Collections.emptyList(), query.getStartTs()); } else { long maxTs = query.getStartTs(); List data = new ArrayList<>(); @@ -296,7 +296,7 @@ public class CassandraBaseTimeseriesDao extends AbstractCassandraBaseTimeseriesD data.add(tsKvEntryAggWrapper.getEntry()); } } - return new ReadTsKvQueryResult(query.getKey(), query.getAggregation(), data, maxTs); + return new ReadTsKvQueryResult(query.getId(), data, maxTs); } } @@ -333,7 +333,7 @@ public class CassandraBaseTimeseriesDao extends AbstractCassandraBaseTimeseriesD if (tsKvEntries != null) { lastTs = tsKvEntries.stream().map(TsKvEntry::getTs).max(Long::compare).orElse(query.getStartTs()); } - return new ReadTsKvQueryResult(query.getKey(), query.getAggregation(), tsKvEntries, lastTs); + return new ReadTsKvQueryResult(query.getId(), tsKvEntries, lastTs); }, MoreExecutors.directExecutor()); } From b5383aa42175f410724ab3d64d5bec9cb95f33f5 Mon Sep 17 00:00:00 2001 From: Igor Kulikov Date: Wed, 14 Sep 2022 17:49:37 +0300 Subject: [PATCH 098/108] UI: Update timeseries aggregation data structures. Implement timeseries aggregation delta calculation. --- ui-ngx/src/app/core/api/data-aggregator.ts | 169 ++++--- .../app/core/api/entity-data-subscription.ts | 426 +++++++++++------- .../src/app/core/api/entity-data.service.ts | 30 +- .../widget/data-key-config.component.html | 72 ++- .../widget/data-key-config.component.scss | 74 +++ .../widget/data-key-config.component.ts | 108 ++++- .../app/shared/models/query/query.models.ts | 7 +- .../models/telemetry/telemetry.models.ts | 8 +- ui-ngx/src/app/shared/models/widget.models.ts | 20 +- .../assets/locale/locale.constant-en_US.json | 6 +- 10 files changed, 619 insertions(+), 301 deletions(-) diff --git a/ui-ngx/src/app/core/api/data-aggregator.ts b/ui-ngx/src/app/core/api/data-aggregator.ts index 697fa2489a..6e77a0a161 100644 --- a/ui-ngx/src/app/core/api/data-aggregator.ts +++ b/ui-ngx/src/app/core/api/data-aggregator.ts @@ -16,8 +16,7 @@ import { AggKey, - AggSubscriptionData, - SubscriptionData + IndexedSubscriptionData, } from '@app/shared/models/telemetry/telemetry.models'; import { AggregationType, @@ -32,7 +31,7 @@ import { UtilsService } from '@core/services/utils.service'; import { deepClone, isDefinedAndNotNull, isNumber, isNumeric } from '@core/utils'; import Timeout = NodeJS.Timeout; -export declare type onAggregatedData = (data: AggSubscriptionData, detectChanges: boolean) => void; +export declare type onAggregatedData = (data: IndexedSubscriptionData, detectChanges: boolean) => void; interface AggData { count: number; @@ -71,12 +70,12 @@ class AggDataMap { } class AggregationMap { - aggMap: {[aggKey: string]: AggDataMap} = {}; + aggMap: {[id: number]: AggDataMap} = {}; detectRangeChanged(): boolean { let changed = false; - for (const aggKey of Object.keys(this.aggMap)) { - const aggDataMap = this.aggMap[aggKey]; + for (const id of Object.keys(this.aggMap)) { + const aggDataMap = this.aggMap[id]; if (aggDataMap.rangeChanged) { changed = true; aggDataMap.rangeChanged = false; @@ -86,8 +85,8 @@ class AggregationMap { } clearRangeChangedFlags() { - for (const aggKey of Object.keys(this.aggMap)) { - this.aggMap[aggKey].rangeChanged = false; + for (const id of Object.keys(this.aggMap)) { + this.aggMap[id].rangeChanged = false; } } } @@ -146,19 +145,18 @@ export class DataAggregator { private utils: UtilsService, private ignoreDataUpdateOnIntervalTick: boolean) { this.tsKeys.forEach((key) => { - if (!this.dataBuffer[key.agg]) { - this.dataBuffer[key.agg] = {}; + if (!this.dataBuffer[key.id]) { + this.dataBuffer[key.id] = []; } - this.dataBuffer[key.agg][key.key] = []; }); if (this.subsTw.aggregation.stateData) { this.lastPrevKvPairData = {}; } } - private dataBuffer: AggSubscriptionData = {}; - private data: AggSubscriptionData; - private readonly lastPrevKvPairData: {[aggKey: string]: [number, any]}; + private dataBuffer: IndexedSubscriptionData = []; + private data: IndexedSubscriptionData; + private readonly lastPrevKvPairData: {[id: number]: [number, any]}; private aggregationMap: AggregationMap; @@ -201,17 +199,6 @@ export class DataAggregator { } } - private static aggKeyToString(aggKey: AggKey): string { - return `${aggKey.key}_${aggKey.agg}`; - } - - private static aggKeyFromString(aggKeyString: string): AggKey { - const separatorIndex = aggKeyString.lastIndexOf('_'); - const key = aggKeyString.substring(0, separatorIndex); - const agg = AggregationType[aggKeyString.substring(separatorIndex + 1)]; - return { key, agg }; - } - public updateOnDataCb(newOnDataCb: onAggregatedData): onAggregatedData { const prevOnDataCb = this.onDataCb; this.onDataCb = newOnDataCb; @@ -241,7 +228,7 @@ export class DataAggregator { this.aggregationMap = null; } - public onData(data: AggSubscriptionData, update: boolean, history: boolean, detectChanges: boolean) { + public onData(data: IndexedSubscriptionData, update: boolean, history: boolean, detectChanges: boolean) { this.updatedData = true; if (!this.dataReceived || this.resetPending) { let updateIntervalScheduledTime = true; @@ -330,24 +317,24 @@ export class DataAggregator { } } - private updateData(): {[aggType: string]: SubscriptionData} { - this.dataBuffer = {}; + private updateData(): IndexedSubscriptionData { + this.dataBuffer = []; this.tsKeys.forEach((key) => { - if (!this.dataBuffer[key.agg]) { - this.dataBuffer[key.agg] = {}; + if (!this.dataBuffer[key.id]) { + this.dataBuffer[key.id] = []; } - this.dataBuffer[key.agg][key.key] = []; }); - for (const aggKeyString of Object.keys(this.aggregationMap.aggMap)) { - const aggKeyData = this.aggregationMap.aggMap[aggKeyString]; - const aggKey = DataAggregator.aggKeyFromString(aggKeyString); + for (const idStr of Object.keys(this.aggregationMap.aggMap)) { + const id = Number(idStr); + const aggKeyData = this.aggregationMap.aggMap[id]; + const aggKey = this.aggKeyById(id); const noAggregation = aggKey.agg === AggregationType.NONE; - let keyData = this.dataBuffer[aggKey.agg][aggKey.key]; + let keyData = this.dataBuffer[id]; aggKeyData.forEach((aggData, aggTimestamp) => { if (aggTimestamp < this.startTs) { if (this.subsTw.aggregation.stateData && - (!this.lastPrevKvPairData[aggKeyString] || this.lastPrevKvPairData[aggKeyString][0] < aggTimestamp)) { - this.lastPrevKvPairData[aggKeyString] = [aggTimestamp, aggData.aggValue]; + (!this.lastPrevKvPairData[id] || this.lastPrevKvPairData[id][0] < aggTimestamp)) { + this.lastPrevKvPairData[id] = [aggTimestamp, aggData.aggValue]; } aggKeyData.delete(aggTimestamp); this.updatedData = true; @@ -358,12 +345,12 @@ export class DataAggregator { }); keyData.sort((set1, set2) => set1[0] - set2[0]); if (this.subsTw.aggregation.stateData) { - this.updateStateBounds(keyData, deepClone(this.lastPrevKvPairData[aggKeyString])); + this.updateStateBounds(keyData, deepClone(this.lastPrevKvPairData[id])); } if (keyData.length > this.subsTw.aggregation.limit) { keyData = keyData.slice(keyData.length - this.subsTw.aggregation.limit); } - this.dataBuffer[aggKey.agg][aggKey.key] = keyData; + this.dataBuffer[id] = keyData; } return this.dataBuffer; } @@ -396,69 +383,71 @@ export class DataAggregator { } } - private processAggregatedData(data: AggSubscriptionData): AggregationMap { + private processAggregatedData(data: IndexedSubscriptionData): AggregationMap { const aggregationMap = new AggregationMap(); - for (const aggTypeString of Object.keys(data)) { - const aggType = AggregationType[aggTypeString]; + for (const idStr of Object.keys(data)) { + const id = Number(idStr); + const aggKey = this.aggKeyById(id); + const aggType = aggKey.agg; const isCount = aggType === AggregationType.COUNT; const noAggregation = aggType === AggregationType.NONE; - for (const key of Object.keys(data[aggType])) { - const aggKey = DataAggregator.aggKeyToString({key, agg: aggType}); - let aggKeyData = aggregationMap.aggMap[aggKey]; - if (!aggKeyData) { - aggKeyData = new AggDataMap(); - aggregationMap.aggMap[aggKey] = aggKeyData; - } - const keyData = data[aggType][key]; - keyData.forEach((kvPair) => { - const timestamp = kvPair[0]; - const value = DataAggregator.convertValue(kvPair[1], noAggregation); - const tsKey = timestamp; - const aggData = { - count: isCount ? value : isDefinedAndNotNull(kvPair[2]) ? kvPair[2] : 1, - sum: value, - aggValue: value - }; - aggKeyData.set(tsKey, aggData); - }); + let aggKeyData = aggregationMap.aggMap[id]; + if (!aggKeyData) { + aggKeyData = new AggDataMap(); + aggregationMap.aggMap[id] = aggKeyData; } + const keyData = data[id]; + keyData.forEach((kvPair) => { + const timestamp = kvPair[0]; + const value = DataAggregator.convertValue(kvPair[1], noAggregation); + const tsKey = timestamp; + const aggData = { + count: isCount ? value : isDefinedAndNotNull(kvPair[2]) ? kvPair[2] : 1, + sum: value, + aggValue: value + }; + aggKeyData.set(tsKey, aggData); + }); } return aggregationMap; } - private updateAggregatedData(data: AggSubscriptionData) { - for (const aggTypeString of Object.keys(data)) { - const aggType = AggregationType[aggTypeString]; + private updateAggregatedData(data: IndexedSubscriptionData) { + for (const idStr of Object.keys(data)) { + const id = Number(idStr); + const aggKey = this.aggKeyById(id); + const aggType = aggKey.agg; const isCount = aggType === AggregationType.COUNT; const noAggregation = aggType === AggregationType.NONE; - for (const key of Object.keys(data[aggType])) { - const aggKey = DataAggregator.aggKeyToString({key, agg: aggType}); - let aggKeyData = this.aggregationMap.aggMap[aggKey]; - if (!aggKeyData) { - aggKeyData = new AggDataMap(); - this.aggregationMap.aggMap[aggKey] = aggKeyData; - } - const keyData = data[aggType][key]; - keyData.forEach((kvPair) => { - const timestamp = kvPair[0]; - const value = DataAggregator.convertValue(kvPair[1], noAggregation); - const aggTimestamp = noAggregation ? timestamp : (this.startTs + - Math.floor((timestamp - this.startTs) / this.subsTw.aggregation.interval) * - this.subsTw.aggregation.interval + this.subsTw.aggregation.interval / 2); - let aggData = aggKeyData.get(aggTimestamp); - if (!aggData) { - aggData = { - count: isDefinedAndNotNull(kvPair[2]) ? kvPair[2] : 1, - sum: value, - aggValue: isCount ? 1 : value - }; - aggKeyData.set(aggTimestamp, aggData); - } else { - DataAggregator.getAggFunction(aggType)(aggData, value); - } - }); + let aggKeyData = this.aggregationMap.aggMap[id]; + if (!aggKeyData) { + aggKeyData = new AggDataMap(); + this.aggregationMap.aggMap[id] = aggKeyData; } + const keyData = data[id]; + keyData.forEach((kvPair) => { + const timestamp = kvPair[0]; + const value = DataAggregator.convertValue(kvPair[1], noAggregation); + const aggTimestamp = noAggregation ? timestamp : (this.startTs + + Math.floor((timestamp - this.startTs) / this.subsTw.aggregation.interval) * + this.subsTw.aggregation.interval + this.subsTw.aggregation.interval / 2); + let aggData = aggKeyData.get(aggTimestamp); + if (!aggData) { + aggData = { + count: isDefinedAndNotNull(kvPair[2]) ? kvPair[2] : 1, + sum: value, + aggValue: isCount ? 1 : value + }; + aggKeyData.set(aggTimestamp, aggData); + } else { + DataAggregator.getAggFunction(aggType)(aggData, value); + } + }); } } + private aggKeyById(id: number): AggKey { + return this.tsKeys.find(key => key.id === id); + } + } diff --git a/ui-ngx/src/app/core/api/entity-data-subscription.ts b/ui-ngx/src/app/core/api/entity-data-subscription.ts index 8032a32973..75c4e0b922 100644 --- a/ui-ngx/src/app/core/api/entity-data-subscription.ts +++ b/ui-ngx/src/app/core/api/entity-data-subscription.ts @@ -14,9 +14,16 @@ /// limitations under the License. /// -import { DataSet, DataSetHolder, DatasourceType, widgetType } from '@shared/models/widget.models'; -import { AggregationType, getCurrentTime, SubscriptionTimewindow } from '@shared/models/time/time.models'; +import { ComparisonResultType, DataSet, DataSetHolder, DatasourceType, widgetType } from '@shared/models/widget.models'; import { + AggregationType, + ComparisonDuration, + createTimewindowForComparison, + getCurrentTime, + SubscriptionTimewindow +} from '@shared/models/time/time.models'; +import { + ComparisonTsValue, EntityData, EntityDataPageLink, EntityFilter, @@ -29,10 +36,10 @@ import { } from '@shared/models/query/query.models'; import { AggKey, - AggSubscriptionData, DataKeyType, EntityCountCmd, EntityDataCmd, + IndexedSubscriptionData, SubscriptionData, TelemetryService, TelemetrySubscriber @@ -46,7 +53,6 @@ import { NULL_UUID } from '@shared/models/id/has-uuid'; import { EntityType } from '@shared/models/entity-type.models'; import { Observable, of, ReplaySubject, Subject } from 'rxjs'; import { EntityId } from '@shared/models/id/entity-id'; -import _ from 'lodash'; import Timeout = NodeJS.Timeout; declare type DataKeyFunction = (time: number, prevValue: any) => any; @@ -58,6 +64,10 @@ export interface SubscriptionDataKey { name: string; type: DataKeyType; aggregationType?: AggregationType; + comparisonEnabled?: boolean; + timeForComparison?: ComparisonDuration; + comparisonCustomIntervalValue?: number; + comparisonResultType?: ComparisonResultType; funcBody: string; func?: DataKeyFunction; postFuncBody: string; @@ -106,6 +116,7 @@ export class EntityDataSubscription { private tsFields: Array; private latestValues: Array; private aggTsValues: Array; + private aggTsComparisonValues: Array; private entityDataResolveSubject: Subject; private pageData: PageData; @@ -115,6 +126,7 @@ export class EntityDataSubscription { private dataAggregators: Array; private tsLatestDataAggregators: Array; private dataKeys: {[key: string]: Array | SubscriptionDataKey} = {}; + private dataKeysList: SubscriptionDataKey[] = []; private datasourceData: {[index: number]: {[key: string]: DataSetHolder}}; private datasourceOrigData: {[index: number]: {[key: string]: DataSetHolder}}; private entityIdToDataIndex: {[id: string]: number}; @@ -136,9 +148,37 @@ export class EntityDataSubscription { return val; } + private static calculateComparisonValue(key: SubscriptionDataKey, comparisonTsValue: ComparisonTsValue): [number, any, number?][] { + let timestamp: number; + let value: any; + switch (key.comparisonResultType) { + case ComparisonResultType.PREVIOUS_VALUE: + timestamp = comparisonTsValue.previous.ts; + value = comparisonTsValue.previous.value; + break; + case ComparisonResultType.DELTA_ABSOLUTE: + case ComparisonResultType.DELTA_PERCENT: + timestamp = comparisonTsValue.previous.ts; + const currentVal = EntityDataSubscription.convertValue(comparisonTsValue.current.value); + const prevVal = EntityDataSubscription.convertValue(comparisonTsValue.previous.value); + if (isNumeric(currentVal) && isNumeric(prevVal)) { + if (key.comparisonResultType === ComparisonResultType.DELTA_ABSOLUTE) { + value = currentVal - prevVal; + } else { + value = (currentVal - prevVal) / prevVal * 100; + } + } else { + value = ''; + } + break; + } + return [[timestamp, value]]; + } + private initializeSubscription() { for (let i = 0; i < this.entityDataSubscriptionOptions.dataKeys.length; i++) { const dataKey = deepClone(this.entityDataSubscriptionOptions.dataKeys[i]); + this.dataKeysList.push(dataKey); dataKey.index = i; if (this.datasourceType === DatasourceType.function) { if (!dataKey.func) { @@ -156,8 +196,8 @@ export class EntityDataSubscription { if (this.datasourceType === DatasourceType.function) { key = `${dataKey.name}_${dataKey.index}_${dataKey.type}${dataKey.latest ? '_latest' : ''}`; } else { - const aggSuffix = dataKey.aggregationType && dataKey.aggregationType !== AggregationType.NONE ? `_${dataKey.aggregationType.toLowerCase()}` : ''; - key = `${dataKey.name}_${dataKey.type}${aggSuffix}${dataKey.latest ? '_latest' : ''}`; + const keyIndexSuffix = dataKey.aggregationType && dataKey.aggregationType !== AggregationType.NONE ? `_${dataKey.index}` : ''; + key = `${dataKey.name}_${dataKey.type}${keyIndexSuffix}${dataKey.latest ? '_latest' : ''}`; } let dataKeysList = this.dataKeys[key] as Array; if (!dataKeysList) { @@ -213,7 +253,7 @@ export class EntityDataSubscription { } if (this.datasourceType === DatasourceType.entity) { const entityFields: Array = - this.entityDataSubscriptionOptions.dataKeys.filter(dataKey => dataKey.type === DataKeyType.entityField).map( + this.dataKeysList.filter(dataKey => dataKey.type === DataKeyType.entityField).map( dataKey => ({ type: EntityKeyType.ENTITY_FIELD, key: dataKey.name }) ); if (!entityFields.find(key => key.key === 'name')) { @@ -235,18 +275,18 @@ export class EntityDataSubscription { }); } - this.attrFields = this.entityDataSubscriptionOptions.dataKeys.filter(dataKey => dataKey.type === DataKeyType.attribute).map( + this.attrFields = this.dataKeysList.filter(dataKey => dataKey.type === DataKeyType.attribute).map( dataKey => ({ type: EntityKeyType.ATTRIBUTE, key: dataKey.name }) ); - this.tsFields = this.entityDataSubscriptionOptions.dataKeys. + this.tsFields = this.dataKeysList. filter(dataKey => dataKey.type === DataKeyType.timeseries && (!dataKey.aggregationType || dataKey.aggregationType === AggregationType.NONE) && !dataKey.latest).map( dataKey => ({ type: EntityKeyType.TIME_SERIES, key: dataKey.name }) ); if (this.entityDataSubscriptionOptions.type === widgetType.timeseries) { - const latestTsFields = this.entityDataSubscriptionOptions.dataKeys. + const latestTsFields = this.dataKeysList. filter(dataKey => dataKey.type === DataKeyType.timeseries && dataKey.latest && (!dataKey.aggregationType || dataKey.aggregationType === AggregationType.NONE)).map( dataKey => ({ type: EntityKeyType.TIME_SERIES, key: dataKey.name }) @@ -256,12 +296,19 @@ export class EntityDataSubscription { this.latestValues = this.attrFields.concat(this.tsFields); } - this.aggTsValues = this.entityDataSubscriptionOptions.dataKeys. + this.aggTsValues = this.dataKeysList. filter(dataKey => dataKey.type === DataKeyType.timeseries && - dataKey.aggregationType && dataKey.aggregationType !== AggregationType.NONE).map( - dataKey => ({ key: dataKey.name, agg: dataKey.aggregationType }) + dataKey.aggregationType && dataKey.aggregationType !== AggregationType.NONE && !dataKey.comparisonEnabled).map( + dataKey => ({ id: dataKey.index, key: dataKey.name, agg: dataKey.aggregationType }) ); + this.aggTsComparisonValues = this.dataKeysList. + filter(dataKey => dataKey.type === DataKeyType.timeseries && + dataKey.aggregationType && dataKey.aggregationType !== AggregationType.NONE && dataKey.comparisonEnabled).map( + dataKey => ({ id: dataKey.index, key: dataKey.name, agg: dataKey.aggregationType, + previousValueOnly: dataKey.comparisonResultType === ComparisonResultType.PREVIOUS_VALUE }) + ); + this.subscriber = new TelemetrySubscriber(this.telemetryService); this.dataCommand = new EntityDataCmd(); @@ -392,7 +439,7 @@ export class EntityDataSubscription { entityType: null }; - const countKey = this.entityDataSubscriptionOptions.dataKeys[0]; + const countKey = this.dataKeysList[0]; let dataReceived = false; @@ -530,24 +577,30 @@ export class EntityDataSubscription { } else if (this.entityDataSubscriptionOptions.type === widgetType.latest) { latestValuesKeys = this.latestValues; } - if (this.aggTsValues.length > 0) { - if (this.history) { - cmd.aggHistoryCmd = { - keys: this.aggTsValues, - startTs: this.subsTw.fixedWindow.startTimeMs, - endTs: this.subsTw.fixedWindow.endTimeMs - }; - } else if (!this.isFloatingTimewindow) { - cmd.aggTsCmd = { - keys: this.aggTsValues, - startTs: this.subsTw.startTs, - timeWindow: this.subsTw.aggregation.timeWindow - }; - if (latestValuesKeys.length > 0) { - const tsKeys = this.aggTsValues.map(key => key.key); - latestValuesKeys = latestValuesKeys.filter(latestKey => latestKey.type !== EntityKeyType.TIME_SERIES - || !tsKeys.includes(latestKey.key)); - } + if (this.history && (this.aggTsValues.length > 0 || this.aggTsComparisonValues.length > 0)) { + for (const aggTsComparison of this.aggTsComparisonValues) { + const subscriptionDataKey = this.dataKeyByIndex(aggTsComparison.id); + const timewindowForComparison = + createTimewindowForComparison(this.subsTw, subscriptionDataKey.timeForComparison, + subscriptionDataKey.comparisonCustomIntervalValue); + aggTsComparison.previousStartTs = timewindowForComparison.fixedWindow.startTimeMs; + aggTsComparison.previousEndTs = timewindowForComparison.fixedWindow.endTimeMs; + } + cmd.aggHistoryCmd = { + keys: [...this.aggTsValues, ...this.aggTsComparisonValues], + startTs: this.subsTw.fixedWindow.startTimeMs, + endTs: this.subsTw.fixedWindow.endTimeMs + }; + } else if (!this.isFloatingTimewindow && this.aggTsValues.length > 0) { + cmd.aggTsCmd = { + keys: this.aggTsValues, + startTs: this.subsTw.startTs, + timeWindow: this.subsTw.aggregation.timeWindow + }; + if (latestValuesKeys.length > 0) { + const tsKeys = this.aggTsValues.map(key => key.key); + latestValuesKeys = latestValuesKeys.filter(latestKey => latestKey.type !== EntityKeyType.TIME_SERIES + || !tsKeys.includes(latestKey.key)); } } if (latestValuesKeys.length > 0) { @@ -592,29 +645,21 @@ export class EntityDataSubscription { this.resetData(); if (this.entityDataSubscriptionOptions.type === widgetType.timeseries) { - let tsKeyNames: string[] = []; + let tsKeyIds: number[]; if (this.datasourceType === DatasourceType.function) { - for (const key of Object.keys(this.dataKeys)) { - const dataKeysList = this.dataKeys[key] as Array; - dataKeysList.forEach((subscriptionDataKey) => { - if (!subscriptionDataKey.latest) { - tsKeyNames.push(`${subscriptionDataKey.name}_${subscriptionDataKey.index}`); - } - }); - } + tsKeyIds = this.dataKeysList.filter(key => !key.latest).map(key => key.index); } else { - tsKeyNames = this.tsFields ? this.tsFields.map(field => field.key) : []; + tsKeyIds = this.dataKeysList. + filter(dataKey => dataKey.type === DataKeyType.timeseries && + (!dataKey.aggregationType || dataKey.aggregationType === AggregationType.NONE) && !dataKey.latest).map( + dataKey => dataKey.index + ); } - const aggKeys: AggKey[] = tsKeyNames.map(key => ({key, agg: this.subsTw.aggregation.type})); + const aggKeys: AggKey[] = tsKeyIds.map(key => ({id: key, key: key + '', agg: this.subsTw.aggregation.type})); if (aggKeys.length) { for (let dataIndex = 0; dataIndex < this.pageData.data.length; dataIndex++) { - if (this.datasourceType === DatasourceType.function) { - this.dataAggregators[dataIndex] = this.createRealtimeDataAggregator(this.subsTw, aggKeys, - false, DataKeyType.function, dataIndex, this.notifyListener.bind(this)); - } else { - this.dataAggregators[dataIndex] = this.createRealtimeDataAggregator(this.subsTw, aggKeys, - false, DataKeyType.timeseries, dataIndex, this.notifyListener.bind(this)); - } + this.dataAggregators[dataIndex] = this.createRealtimeDataAggregator(this.subsTw, aggKeys, + false, dataIndex, this.notifyListener.bind(this)); } } } @@ -625,34 +670,35 @@ export class EntityDataSubscription { aggLatestTimewindow.aggregation.interval = aggLatestTimewindow.aggregation.timeWindow; for (let dataIndex = 0; dataIndex < this.pageData.data.length; dataIndex++) { this.tsLatestDataAggregators[dataIndex] = this.createRealtimeDataAggregator(aggLatestTimewindow, this.aggTsValues, - true, DataKeyType.timeseries, dataIndex, this.notifyListener.bind(this)); + true, dataIndex, this.notifyListener.bind(this)); } } else { - const tsKeysByAggType = _.groupBy(this.aggTsValues, value => value.agg); - const aggSubscriptionData: AggSubscriptionData = {}; - for (const aggTypeString of Object.keys(tsKeysByAggType)) { - const tsKeys = tsKeysByAggType[aggTypeString]; - const latestTsAggSubsciptionData: SubscriptionData = {}; - for (const tsKey of tsKeys) { - latestTsAggSubsciptionData[tsKey.key] = [[0, 'Not supported!']]; - } - aggSubscriptionData[aggTypeString] = latestTsAggSubsciptionData; - } - for (let dataIndex = 0; dataIndex < this.pageData.data.length; dataIndex++) { - this.onAggData(aggSubscriptionData, DataKeyType.timeseries, dataIndex, true, - this.entityDataSubscriptionOptions.type === widgetType.timeseries, true, - (data, dataIndex1, dataKeyIndex, detectChanges, isLatest) => { - if (!this.data[dataIndex1]) { - this.data[dataIndex1] = []; - } - this.data[dataIndex1][dataKeyIndex] = data; - if (isUpdate) { - this.notifyListener(data, dataIndex1, dataKeyIndex, detectChanges, isLatest); - } - }); - } + this.reportNotSupported(this.aggTsValues, isUpdate); } } + if (!this.history && this.aggTsComparisonValues && this.aggTsComparisonValues.length) { + this.reportNotSupported(this.aggTsComparisonValues, isUpdate); + } + } + + private reportNotSupported(keys: AggKey[], isUpdate: boolean) { + const indexedData: IndexedSubscriptionData = []; + for (const key of keys) { + indexedData[key.id] = [[0, 'Not supported!']]; + } + for (let dataIndex = 0; dataIndex < this.pageData.data.length; dataIndex++) { + this.onIndexedData(indexedData, dataIndex, true, + this.entityDataSubscriptionOptions.type === widgetType.timeseries, + (data, dataIndex1, dataKeyIndex, detectChanges, isLatest) => { + if (!this.data[dataIndex1]) { + this.data[dataIndex1] = []; + } + this.data[dataIndex1][dataKeyIndex] = data; + if (isUpdate) { + this.notifyListener(data, dataIndex1, dataKeyIndex, detectChanges, isLatest); + } + }); + } } private resetData() { @@ -777,20 +823,29 @@ export class EntityDataSubscription { if (this.entityDataSubscriptionOptions.type === widgetType.latest || this.entityDataSubscriptionOptions.type === widgetType.timeseries) { if (entityData.aggLatest) { - if (this.tsLatestDataAggregators && this.tsLatestDataAggregators[dataIndex]) { - const dataAggregator = this.tsLatestDataAggregators[dataIndex]; - const aggSubscriptionData: AggSubscriptionData = {}; - for (const aggTypeString of Object.keys(entityData.aggLatest)) { - aggSubscriptionData[aggTypeString] = this.toSubscriptionData(entityData.aggLatest[aggTypeString], false); + const aggData: IndexedSubscriptionData = []; + for (const idStr of Object.keys(entityData.aggLatest)) { + const id = Number(idStr); + const dataKey = this.dataKeyByIndex(id); + const aggLatestData = entityData.aggLatest[id]; + if (dataKey.comparisonEnabled) { + const keyData = EntityDataSubscription.calculateComparisonValue(dataKey, aggLatestData); + this.onKeyData(keyData, dataKey.name, id, dataKey.type, dataIndex, true, + this.entityDataSubscriptionOptions.type === widgetType.timeseries, true, dataUpdatedCb); + } else { + aggData[id] = [[aggLatestData.current.ts, aggLatestData.current.value, aggLatestData.current.count]]; } + } + if (Object.keys(aggData).length > 0 && this.tsLatestDataAggregators && this.tsLatestDataAggregators[dataIndex]) { + const dataAggregator = this.tsLatestDataAggregators[dataIndex]; let prevDataCb; if (!isUpdate) { prevDataCb = dataAggregator.updateOnDataCb((data, detectChanges) => { - this.onAggData(data, DataKeyType.timeseries, dataIndex, detectChanges, - this.entityDataSubscriptionOptions.type === widgetType.timeseries, true, dataUpdatedCb); + this.onIndexedData(data, dataIndex, detectChanges, + this.entityDataSubscriptionOptions.type === widgetType.timeseries, dataUpdatedCb); }); } - dataAggregator.onData(aggSubscriptionData, false, this.history, true); + dataAggregator.onData(aggData, false, this.history, true); if (prevDataCb) { dataAggregator.updateOnDataCb(prevDataCb); } @@ -809,26 +864,20 @@ export class EntityDataSubscription { latestTsSubsciptionData[latestTsKey.key] = subscriptionData[latestTsKey.key]; } this.onData(latestTsSubsciptionData, dataKeyType, dataIndex, true, - this.entityDataSubscriptionOptions.type === widgetType.timeseries, false, dataUpdatedCb); + this.entityDataSubscriptionOptions.type === widgetType.timeseries, dataUpdatedCb); } const aggTsKeys = this.aggTsValues.filter(key => keys.includes(key.key)); if (!this.history && aggTsKeys.length && this.tsLatestDataAggregators && this.tsLatestDataAggregators[dataIndex]) { const dataAggregator = this.tsLatestDataAggregators[dataIndex]; - const tsKeysByAggType = _.groupBy(aggTsKeys, value => value.agg); - const aggSubscriptionData: AggSubscriptionData = {}; - for (const aggTypeString of Object.keys(tsKeysByAggType)) { - const tsKeys = tsKeysByAggType[aggTypeString]; - const latestTsAggSubsciptionData: SubscriptionData = {}; - for (const tsKey of tsKeys) { - latestTsAggSubsciptionData[tsKey.key] = subscriptionData[tsKey.key]; - } - aggSubscriptionData[aggTypeString] = latestTsAggSubsciptionData; + const indexedData: IndexedSubscriptionData = []; + for (const aggKey of aggTsKeys) { + indexedData[aggKey.id] = subscriptionData[aggKey.key]; } - dataAggregator.onData(aggSubscriptionData, true, false, true); + dataAggregator.onData(indexedData, true, false, true); } } else { this.onData(subscriptionData, dataKeyType, dataIndex, true, - this.entityDataSubscriptionOptions.type === widgetType.timeseries, false, dataUpdatedCb); + this.entityDataSubscriptionOptions.type === widgetType.timeseries, dataUpdatedCb); } } } @@ -837,100 +886,116 @@ export class EntityDataSubscription { const subscriptionData = this.toSubscriptionData(entityData.timeseries, true); if (this.dataAggregators && this.dataAggregators[dataIndex]) { const dataAggregator = this.dataAggregators[dataIndex]; - const aggSubscriptionData: AggSubscriptionData = {}; - aggSubscriptionData[this.subsTw.aggregation.type] = subscriptionData; + const keyNames = Object.keys(subscriptionData); + const dataKeys = this.timeseriesDataKeysByKeyNames(keyNames); + const indexedData: IndexedSubscriptionData = []; + for (const dataKey of dataKeys) { + indexedData[dataKey.index] = subscriptionData[dataKey.name]; + } let prevDataCb; if (!isUpdate) { prevDataCb = dataAggregator.updateOnDataCb((data, detectChanges) => { - this.onAggData(data, this.datasourceType === DatasourceType.function ? - DataKeyType.function : DataKeyType.timeseries, dataIndex, detectChanges, false, false, dataUpdatedCb); + this.onIndexedData(data, dataIndex, detectChanges, false, dataUpdatedCb); }); } - dataAggregator.onData(aggSubscriptionData, false, this.history, true); + dataAggregator.onData(indexedData, false, this.history, true); if (prevDataCb) { dataAggregator.updateOnDataCb(prevDataCb); } } else if (!this.history && !isUpdate) { - this.onData(subscriptionData, DataKeyType.timeseries, dataIndex, true, false, false, dataUpdatedCb); + this.onData(subscriptionData, DataKeyType.timeseries, dataIndex, true, false, dataUpdatedCb); } } } private onData(sourceData: SubscriptionData, type: DataKeyType, dataIndex: number, detectChanges: boolean, - isTsLatest: boolean, isAggLatest: boolean, dataUpdatedCb: DataUpdatedCb) { - const aggSubscriptionData: AggSubscriptionData = {}; - aggSubscriptionData[AggregationType.NONE] = sourceData; - this.onAggData(aggSubscriptionData, type, dataIndex, detectChanges, isTsLatest, isAggLatest, dataUpdatedCb); + isTsLatest: boolean, dataUpdatedCb: DataUpdatedCb) { + for (const key of Object.keys(sourceData)) { + const keyData = sourceData[key]; + this.onKeyData(keyData, key, 0, type, + dataIndex, detectChanges, isTsLatest, false, dataUpdatedCb); + } + } + + private onIndexedData(sourceData: IndexedSubscriptionData, dataIndex: number, detectChanges: boolean, + isTsLatest: boolean, dataUpdatedCb: DataUpdatedCb) { + for (const indexStr of Object.keys(sourceData)) { + const id = Number(indexStr); + const dataKey = this.dataKeyByIndex(id); + const isAggLatest = dataKey.aggregationType && dataKey.aggregationType !== AggregationType.NONE; + const keyData = sourceData[id]; + let keyName = dataKey.name; + if (dataKey.type === DataKeyType.function) { + keyName += `_${dataKey.index}`; + } + this.onKeyData(keyData, keyName, id, dataKey.type, + dataIndex, detectChanges, isTsLatest, isAggLatest, dataUpdatedCb); + } } - private onAggData(sourceData: AggSubscriptionData, type: DataKeyType, dataIndex: number, detectChanges: boolean, + private onKeyData(keyData: [number, any, number?][], keyName: string, id: number, type: DataKeyType, + dataIndex: number, detectChanges: boolean, isTsLatest: boolean, isAggLatest: boolean, dataUpdatedCb: DataUpdatedCb) { - for (const aggTypeString of Object.keys(sourceData)) { - const aggType = AggregationType[aggTypeString]; - const aggSuffix = isAggLatest ? (aggType !== AggregationType.NONE ? `_${aggType.toLowerCase()}` : '') : ''; - for (const keyName of Object.keys(sourceData[aggType])) { - const keyData = sourceData[aggType][keyName]; - const key = `${keyName}_${type}${aggSuffix}${isTsLatest ? '_latest' : ''}`; - const dataKeyList = this.dataKeys[key] as Array; - for (let keyIndex = 0; dataKeyList && keyIndex < dataKeyList.length; keyIndex++) { - const datasourceKey = `${key}_${keyIndex}`; - if (this.datasourceData[dataIndex][datasourceKey].data) { - const dataKey = dataKeyList[keyIndex]; - const data: DataSet = []; - let prevSeries: [number, any]; - let prevOrigSeries: [number, any]; - let datasourceKeyData: DataSet; - let datasourceOrigKeyData: DataSet; - let update = false; - if (this.realtime && !isTsLatest) { - datasourceKeyData = []; - datasourceOrigKeyData = []; - } else { - datasourceKeyData = this.datasourceData[dataIndex][datasourceKey].data; - datasourceOrigKeyData = this.datasourceOrigData[dataIndex][datasourceKey].data; - } - if (datasourceKeyData.length > 0) { - prevSeries = datasourceKeyData[datasourceKeyData.length - 1]; - prevOrigSeries = datasourceOrigKeyData[datasourceOrigKeyData.length - 1]; - } else { - prevSeries = [0, 0]; - prevOrigSeries = [0, 0]; - } - this.datasourceOrigData[dataIndex][datasourceKey].data = []; - if (this.entityDataSubscriptionOptions.type === widgetType.timeseries && !isTsLatest) { - keyData.forEach((keySeries) => { - let series = keySeries; - const time = series[0]; - this.datasourceOrigData[dataIndex][datasourceKey].data.push([series[0], series[1]]); - let value = EntityDataSubscription.convertValue(series[1]); - if (dataKey.postFunc) { - value = dataKey.postFunc(time, value, prevSeries[1], prevOrigSeries[0], prevOrigSeries[1]); - } - prevOrigSeries = [series[0], series[1]]; - series = [series[0], value]; - data.push([series[0], series[1]]); - prevSeries = [series[0], series[1]]; - }); - update = true; - } else if (this.entityDataSubscriptionOptions.type === widgetType.latest || isTsLatest) { - if (keyData.length > 0) { - let series = keyData[0]; - const time = series[0]; - this.datasourceOrigData[dataIndex][datasourceKey].data.push([series[0], series[1]]); - let value = EntityDataSubscription.convertValue(series[1]); - if (dataKey.postFunc) { - value = dataKey.postFunc(time, value, prevSeries[1], prevOrigSeries[0], prevOrigSeries[1]); - } - series = [time, value]; - data.push([series[0], series[1]]); - } - update = true; + const keyIdSuffix = isAggLatest ? `_${id}` : ''; + const key = `${keyName}_${type}${keyIdSuffix}${isTsLatest ? '_latest' : ''}`; + const dataKeyList = this.dataKeys[key] as Array; + for (let keyIndex = 0; dataKeyList && keyIndex < dataKeyList.length; keyIndex++) { + const datasourceKey = `${key}_${keyIndex}`; + if (this.datasourceData[dataIndex][datasourceKey].data) { + const dataKey = dataKeyList[keyIndex]; + const data: DataSet = []; + let prevSeries: [number, any]; + let prevOrigSeries: [number, any]; + let datasourceKeyData: DataSet; + let datasourceOrigKeyData: DataSet; + let update = false; + if (this.realtime && !isTsLatest) { + datasourceKeyData = []; + datasourceOrigKeyData = []; + } else { + datasourceKeyData = this.datasourceData[dataIndex][datasourceKey].data; + datasourceOrigKeyData = this.datasourceOrigData[dataIndex][datasourceKey].data; + } + if (datasourceKeyData.length > 0) { + prevSeries = datasourceKeyData[datasourceKeyData.length - 1]; + prevOrigSeries = datasourceOrigKeyData[datasourceOrigKeyData.length - 1]; + } else { + prevSeries = [0, 0]; + prevOrigSeries = [0, 0]; + } + this.datasourceOrigData[dataIndex][datasourceKey].data = []; + if (this.entityDataSubscriptionOptions.type === widgetType.timeseries && !isTsLatest) { + keyData.forEach((keySeries) => { + let series = keySeries; + const time = series[0]; + this.datasourceOrigData[dataIndex][datasourceKey].data.push([series[0], series[1]]); + let value = EntityDataSubscription.convertValue(series[1]); + if (dataKey.postFunc) { + value = dataKey.postFunc(time, value, prevSeries[1], prevOrigSeries[0], prevOrigSeries[1]); } - if (update) { - this.datasourceData[dataIndex][datasourceKey].data = data; - dataUpdatedCb(this.datasourceData[dataIndex][datasourceKey], dataIndex, dataKey.index, detectChanges, isTsLatest); + prevOrigSeries = [series[0], series[1]]; + series = [series[0], value]; + data.push([series[0], series[1]]); + prevSeries = [series[0], series[1]]; + }); + update = true; + } else if (this.entityDataSubscriptionOptions.type === widgetType.latest || isTsLatest) { + if (keyData.length > 0) { + let series = keyData[0]; + const time = series[0]; + this.datasourceOrigData[dataIndex][datasourceKey].data.push([series[0], series[1]]); + let value = EntityDataSubscription.convertValue(series[1]); + if (dataKey.postFunc) { + value = dataKey.postFunc(time, value, prevSeries[1], prevOrigSeries[0], prevOrigSeries[1]); } + series = [time, value]; + data.push([series[0], series[1]]); } + update = true; + } + if (update) { + this.datasourceData[dataIndex][datasourceKey].data = data; + dataUpdatedCb(this.datasourceData[dataIndex][datasourceKey], dataIndex, dataKey.index, detectChanges, isTsLatest); } } } @@ -957,13 +1022,12 @@ export class EntityDataSubscription { private createRealtimeDataAggregator(subsTw: SubscriptionTimewindow, tsKeys: Array, isLatestDataAgg: boolean, - dataKeyType: DataKeyType, dataIndex: number, dataUpdatedCb: DataUpdatedCb): DataAggregator { return new DataAggregator( (data, detectChanges) => { - this.onAggData(data, dataKeyType, dataIndex, detectChanges, - isLatestDataAgg && (this.entityDataSubscriptionOptions.type === widgetType.timeseries), isLatestDataAgg, dataUpdatedCb); + this.onIndexedData(data, dataIndex, detectChanges, + isLatestDataAgg && (this.entityDataSubscriptionOptions.type === widgetType.timeseries), dataUpdatedCb); }, tsKeys, isLatestDataAgg, @@ -973,6 +1037,20 @@ export class EntityDataSubscription { ); } + private dataKeyByIndex(index: number): SubscriptionDataKey { + return this.dataKeysList.find(key => key.index === index); + } + + private timeseriesDataKeysByKeyNames(keyNames: string[]): SubscriptionDataKey[] { + const result: SubscriptionDataKey[] = []; + for (const keyName of keyNames) { + const key = `${keyName}_${DataKeyType.timeseries}`; + const dataKeyList = this.dataKeys[key] as Array; + result.push(...dataKeyList); + } + return result; + } + private generateSeries(dataKey: SubscriptionDataKey, startTime: number, endTime: number): [number, any][] { const data: [number, any][] = []; let prevSeries: [number, any]; @@ -1051,9 +1129,7 @@ export class EntityDataSubscription { let startTime: number; let endTime: number; let delta: number; - const aggType = this.entityDataSubscriptionOptions.subscriptionTimewindow.aggregation.type; - const generatedData: AggSubscriptionData = {}; - generatedData[aggType] = {}; + const generatedData: IndexedSubscriptionData = []; if (!this.history) { delta = Math.floor(this.tickElapsed / this.frequency); } @@ -1086,7 +1162,7 @@ export class EntityDataSubscription { endTime = Math.min(currentTime, endTime); } } - generatedData[aggType][`${dataKey.name}_${dataKey.index}`] = this.generateSeries(dataKey, startTime, endTime); + generatedData[dataKey.index] = this.generateSeries(dataKey, startTime, endTime); } if (this.dataAggregators && this.dataAggregators.length) { this.dataAggregators[0].onData(generatedData, true, this.history, detectChanges); diff --git a/ui-ngx/src/app/core/api/entity-data.service.ts b/ui-ngx/src/app/core/api/entity-data.service.ts index 4557d96b0f..6d8ea94dc0 100644 --- a/ui-ngx/src/app/core/api/entity-data.service.ts +++ b/ui-ngx/src/app/core/api/entity-data.service.ts @@ -74,6 +74,21 @@ export class EntityDataService { } } + private static toSubscriptionDataKey(dataKey: DataKey, latest: boolean): SubscriptionDataKey { + return { + name: dataKey.name, + type: dataKey.type, + aggregationType: dataKey.aggregationType, + comparisonEnabled: dataKey.comparisonEnabled, + timeForComparison: dataKey.timeForComparison, + comparisonCustomIntervalValue: dataKey.comparisonCustomIntervalValue, + comparisonResultType: dataKey.comparisonResultType, + funcBody: dataKey.funcBody, + postFuncBody: dataKey.postFuncBody, + latest + }; + } + public prepareSubscription(listener: EntityDataListener, ignoreDataUpdateOnIntervalTick = false): Observable { const datasource = listener.configDatasource; @@ -147,11 +162,11 @@ export class EntityDataService { ignoreDataUpdateOnIntervalTick: boolean): EntityDataSubscriptionOptions { const subscriptionDataKeys: Array = []; datasource.dataKeys.forEach((dataKey) => { - subscriptionDataKeys.push(this.toSubscriptionDataKey(dataKey, false)); + subscriptionDataKeys.push(EntityDataService.toSubscriptionDataKey(dataKey, false)); }); if (datasource.latestDataKeys) { datasource.latestDataKeys.forEach((dataKey) => { - subscriptionDataKeys.push(this.toSubscriptionDataKey(dataKey, true)); + subscriptionDataKeys.push(EntityDataService.toSubscriptionDataKey(dataKey, true)); }); } const entityDataSubscriptionOptions: EntityDataSubscriptionOptions = { @@ -172,15 +187,4 @@ export class EntityDataService { entityDataSubscriptionOptions.ignoreDataUpdateOnIntervalTick = ignoreDataUpdateOnIntervalTick; return entityDataSubscriptionOptions; } - - private toSubscriptionDataKey(dataKey: DataKey, latest: boolean): SubscriptionDataKey { - return { - name: dataKey.name, - type: dataKey.type, - aggregationType: dataKey.aggregationType, - funcBody: dataKey.funcBody, - postFuncBody: dataKey.postFuncBody, - latest - }; - } } diff --git a/ui-ngx/src/app/modules/home/components/widget/data-key-config.component.html b/ui-ngx/src/app/modules/home/components/widget/data-key-config.component.html index 8cc9cb4ff3..fe4df7ca62 100644 --- a/ui-ngx/src/app/modules/home/components/widget/data-key-config.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/data-key-config.component.html @@ -62,15 +62,69 @@ - - datakey.aggregation-type - - - {{ (aggregation === aggregationTypes.NONE ? 'datakey.latest-value' : aggregationTypesTranslations.get(aggregationTypes[aggregation])) | translate }} - - - {{ dataKeyFormGroup.get('aggregationType').value ? (dataKeyAggregationTypeHintTranslations.get(aggregationTypes[dataKeyFormGroup.get('aggregationType').value]) | translate) : '' }} - +
+ + datakey.aggregation-type + + + {{ (aggregation === aggregationTypes.NONE ? 'datakey.latest-value' : aggregationTypesTranslations.get(aggregationTypes[aggregation])) | translate }} + + + {{ dataKeyFormGroup.get('aggregationType').value ? (dataKeyAggregationTypeHintTranslations.get(aggregationTypes[dataKeyFormGroup.get('aggregationType').value]) | translate) : '' }} + +
+ widgets.chart.comparison-settings + + + + + {{ 'widgets.chart.enable-comparison' | translate }} + + + + +
+ + widgets.chart.time-for-comparison + + + {{ 'widgets.chart.time-for-comparison-previous-interval' | translate }} + + + {{ 'widgets.chart.time-for-comparison-days' | translate }} + + + {{ 'widgets.chart.time-for-comparison-weeks' | translate }} + + + {{ 'widgets.chart.time-for-comparison-months' | translate }} + + + {{ 'widgets.chart.time-for-comparison-years' | translate }} + + + {{ 'widgets.chart.time-for-comparison-custom-interval' | translate }} + + + + + widgets.chart.custom-interval-value + + + + datakey.comparison-result + + + {{ comparisonResultTypeTranslations.get(comparisonResultTypes[comparisonResultType]) | translate }} + + + +
+
+
+
+
datakey.data-generation-func
diff --git a/ui-ngx/src/app/modules/home/components/widget/data-key-config.component.scss b/ui-ngx/src/app/modules/home/components/widget/data-key-config.component.scss index 8b71ee3664..d0d7e56137 100644 --- a/ui-ngx/src/app/modules/home/components/widget/data-key-config.component.scss +++ b/ui-ngx/src/app/modules/home/components/widget/data-key-config.component.scss @@ -28,6 +28,36 @@ padding-left: 12px; } } + + .fields-group { + padding: 0 16px 8px; + margin-bottom: 10px; + border: 1px groove rgba(0, 0, 0, .25); + border-radius: 4px; + + legend { + color: rgba(0, 0, 0, .7); + width: fit-content; + } + + legend + * { + display: block; + margin-top: 16px; + } + + &.fields-group-slider { + padding: 0; + + legend { + margin-left: 16px; + } + + > .tb-settings { + margin-top: 0; + padding: 0 16px 8px; + } + } + } } } @@ -42,5 +72,49 @@ } } } + .mat-expansion-panel { + &.tb-settings { + box-shadow: none; + + .mat-content { + overflow: visible; + } + + .mat-expansion-panel-header { + padding: 0; + color: rgba(0, 0, 0, 0.87); + + &:hover { + background: none; + } + + .mat-expansion-indicator { + padding: 2px; + } + } + + .mat-expansion-panel-header-description { + align-items: center; + } + + > .mat-expansion-panel-content { + > .mat-expansion-panel-body { + padding: 0; + } + } + } + + .mat-expansion-panel-content { + font: inherit; + } + } + + .mat-slide { + margin: 8px 0; + } + + .mat-slide-toggle-content { + white-space: normal; + } } } diff --git a/ui-ngx/src/app/modules/home/components/widget/data-key-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/data-key-config.component.ts index 4085e5dca2..a461796111 100644 --- a/ui-ngx/src/app/modules/home/components/widget/data-key-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/data-key-config.component.ts @@ -18,7 +18,13 @@ import { Component, ElementRef, forwardRef, Input, OnInit, ViewChild } from '@an import { PageComponent } from '@shared/components/page.component'; import { Store } from '@ngrx/store'; import { AppState } from '@core/core.state'; -import { DataKey, dataKeyAggregationTypeHintTranslationMap, Widget, widgetType } from '@shared/models/widget.models'; +import { + ComparisonResultType, comparisonResultTypeTranslationMap, + DataKey, + dataKeyAggregationTypeHintTranslationMap, + Widget, + widgetType +} from '@shared/models/widget.models'; import { ControlValueAccessor, FormBuilder, @@ -43,7 +49,7 @@ import { JsonFormComponentData } from '@shared/components/json-form/json-form-co import { WidgetService } from '@core/http/widget.service'; import { Dashboard } from '@shared/models/dashboard.models'; import { IAliasController } from '@core/api/widget-api.models'; -import { aggregationTranslations, AggregationType } from '@shared/models/time/time.models'; +import { aggregationTranslations, AggregationType, ComparisonDuration } from '@shared/models/time/time.models'; @Component({ selector: 'tb-data-key-config', @@ -76,6 +82,12 @@ export class DataKeyConfigComponent extends PageComponent implements OnInit, Con dataKeyAggregationTypeHintTranslations = dataKeyAggregationTypeHintTranslationMap; + comparisonResultTypes = ComparisonResultType; + + comparisonResults = Object.keys(ComparisonResultType); + + comparisonResultTypeTranslations = comparisonResultTypeTranslationMap; + @Input() entityAliasId: string; @@ -170,6 +182,10 @@ export class DataKeyConfigComponent extends PageComponent implements OnInit, Con this.dataKeyFormGroup = this.fb.group({ name: [null, []], aggregationType: [null, []], + comparisonEnabled: [null, []], + timeForComparison: [null, [Validators.required]], + comparisonCustomIntervalValue: [null, [Validators.required, Validators.min(1000)]], + comparisonResultType: [null, [Validators.required]], label: [null, [Validators.required]], color: [null, [Validators.required]], units: [null, []], @@ -189,6 +205,19 @@ export class DataKeyConfigComponent extends PageComponent implements OnInit, Con } this.dataKeyFormGroup.get('label').patchValue(newLabel); } + this.updateComparisonValidators(); + } + ); + + this.dataKeyFormGroup.get('comparisonEnabled').valueChanges.subscribe( + () => { + this.updateComparisonValues(); + } + ); + + this.dataKeyFormGroup.get('timeForComparison').valueChanges.subscribe( + () => { + this.updateComparisonValues(); } ); @@ -231,21 +260,82 @@ export class DataKeyConfigComponent extends PageComponent implements OnInit, Con this.modelValue.aggregationType = AggregationType.NONE; } this.dataKeyFormGroup.patchValue(this.modelValue, {emitEvent: false}); + this.updateValidators(); + if (this.displayAdvanced) { + this.dataKeySettingsData.model = this.modelValue.settings; + this.dataKeySettingsFormGroup.patchValue({ + settings: this.dataKeySettingsData + }, {emitEvent: false}); + } + } + + private updateValidators() { this.dataKeyFormGroup.get('name').setValidators(this.modelValue.type !== DataKeyType.function && - this.modelValue.type !== DataKeyType.count - ? [Validators.required] : []); + this.modelValue.type !== DataKeyType.count + ? [Validators.required] : []); if (this.modelValue.type === DataKeyType.count) { this.dataKeyFormGroup.get('name').disable({emitEvent: false}); } else { this.dataKeyFormGroup.get('name').enable({emitEvent: false}); } this.dataKeyFormGroup.get('name').updateValueAndValidity({emitEvent: false}); - if (this.displayAdvanced) { - this.dataKeySettingsData.model = this.modelValue.settings; - this.dataKeySettingsFormGroup.patchValue({ - settings: this.dataKeySettingsData - }, {emitEvent: false}); + this.updateComparisonValidators(); + } + + private updateComparisonValues() { + const comparisonEnabled = this.dataKeyFormGroup.get('comparisonEnabled').value; + if (comparisonEnabled) { + const timeForComparison: ComparisonDuration = this.dataKeyFormGroup.get('timeForComparison').value; + if (!timeForComparison) { + this.dataKeyFormGroup.get('timeForComparison').patchValue('previousInterval', {emitEvent: false}); + } else if (timeForComparison === 'customInterval') { + const comparisonCustomIntervalValue = this.dataKeyFormGroup.get('comparisonCustomIntervalValue').value; + if (!comparisonCustomIntervalValue) { + this.dataKeyFormGroup.get('comparisonCustomIntervalValue').patchValue(7200000, {emitEvent: false}); + } + } + const comparisonResultType: ComparisonResultType = this.dataKeyFormGroup.get('comparisonResultType').value; + if (!comparisonResultType) { + this.dataKeyFormGroup.get('comparisonResultType').patchValue(ComparisonResultType.DELTA_ABSOLUTE, {emitEvent: false}); + } + } + this.updateComparisonValidators(); + } + + private updateComparisonValidators() { + const aggregationType: AggregationType = this.dataKeyFormGroup.get('aggregationType').value; + if (aggregationType && aggregationType !== AggregationType.NONE) { + this.dataKeyFormGroup.get('comparisonEnabled').enable({emitEvent: false}); + const comparisonEnabled = this.dataKeyFormGroup.get('comparisonEnabled').value; + if (comparisonEnabled) { + this.dataKeyFormGroup.get('timeForComparison').enable({emitEvent: false}); + const timeForComparison: ComparisonDuration = this.dataKeyFormGroup.get('timeForComparison').value; + if (timeForComparison) { + this.dataKeyFormGroup.get('comparisonResultType').enable({emitEvent: false}); + if (timeForComparison === 'customInterval') { + this.dataKeyFormGroup.get('comparisonCustomIntervalValue').enable({emitEvent: false}); + } else { + this.dataKeyFormGroup.get('comparisonCustomIntervalValue').disable({emitEvent: false}); + } + } else { + this.dataKeyFormGroup.get('comparisonResultType').disable({emitEvent: false}); + this.dataKeyFormGroup.get('comparisonCustomIntervalValue').disable({emitEvent: false}); + } + } else { + this.dataKeyFormGroup.get('timeForComparison').disable({emitEvent: false}); + this.dataKeyFormGroup.get('comparisonResultType').disable({emitEvent: false}); + this.dataKeyFormGroup.get('comparisonCustomIntervalValue').disable({emitEvent: false}); + } + } else { + this.dataKeyFormGroup.get('comparisonEnabled').disable({emitEvent: false}); + this.dataKeyFormGroup.get('timeForComparison').disable({emitEvent: false}); + this.dataKeyFormGroup.get('comparisonResultType').disable({emitEvent: false}); + this.dataKeyFormGroup.get('comparisonCustomIntervalValue').disable({emitEvent: false}); } + this.dataKeyFormGroup.get('comparisonEnabled').updateValueAndValidity({emitEvent: false}); + this.dataKeyFormGroup.get('timeForComparison').updateValueAndValidity({emitEvent: false}); + this.dataKeyFormGroup.get('comparisonResultType').updateValueAndValidity({emitEvent: false}); + this.dataKeyFormGroup.get('comparisonCustomIntervalValue').updateValueAndValidity({emitEvent: false}); } private updateModel() { diff --git a/ui-ngx/src/app/shared/models/query/query.models.ts b/ui-ngx/src/app/shared/models/query/query.models.ts index 95c756f7f9..c1bf255cd3 100644 --- a/ui-ngx/src/app/shared/models/query/query.models.ts +++ b/ui-ngx/src/app/shared/models/query/query.models.ts @@ -763,11 +763,16 @@ export interface TsValue { count?: number; } +export interface ComparisonTsValue { + current?: TsValue; + previous?: TsValue; +} + export interface EntityData { entityId: EntityId; latest: {[entityKeyType: string]: {[key: string]: TsValue}}; timeseries: {[key: string]: Array}; - aggLatest?: {[aggType: string]: {[key: string]: TsValue}}; + aggLatest?: {[id: number]: ComparisonTsValue}; } export interface AlarmData extends AlarmInfo { diff --git a/ui-ngx/src/app/shared/models/telemetry/telemetry.models.ts b/ui-ngx/src/app/shared/models/telemetry/telemetry.models.ts index 04d98567cf..5fef4b832e 100644 --- a/ui-ngx/src/app/shared/models/telemetry/telemetry.models.ts +++ b/ui-ngx/src/app/shared/models/telemetry/telemetry.models.ts @@ -174,8 +174,12 @@ export interface TimeSeriesCmd { } export interface AggKey { + id: number; key: string; agg: AggregationType; + previousStartTs?: number; + previousEndTs?: number; + previousValueOnly?: boolean; } export interface AggEntityHistoryCmd { @@ -314,8 +318,8 @@ export interface SubscriptionData { [key: string]: [number, any, number?][]; } -export interface AggSubscriptionData { - [aggType: string]: SubscriptionData; +export interface IndexedSubscriptionData { + [id: number]: [number, any, number?][]; } export interface SubscriptionDataHolder { diff --git a/ui-ngx/src/app/shared/models/widget.models.ts b/ui-ngx/src/app/shared/models/widget.models.ts index 9efb47758d..c654c87784 100644 --- a/ui-ngx/src/app/shared/models/widget.models.ts +++ b/ui-ngx/src/app/shared/models/widget.models.ts @@ -17,7 +17,7 @@ import { BaseData } from '@shared/models/base-data'; import { TenantId } from '@shared/models/id/tenant-id'; import { WidgetTypeId } from '@shared/models/id/widget-type-id'; -import { AggregationType, Timewindow } from '@shared/models/time/time.models'; +import { AggregationType, ComparisonDuration, Timewindow } from '@shared/models/time/time.models'; import { EntityType } from '@shared/models/entity-type.models'; import { AlarmSearchStatus, AlarmSeverity } from '@shared/models/alarm.models'; import { DataKeyType } from './telemetry/telemetry.models'; @@ -259,9 +259,27 @@ export function defaultLegendConfig(wType: widgetType): LegendConfig { }; } +export enum ComparisonResultType { + PREVIOUS_VALUE = 'PREVIOUS_VALUE', + DELTA_ABSOLUTE = 'DELTA_ABSOLUTE', + DELTA_PERCENT = 'DELTA_PERCENT' +} + +export const comparisonResultTypeTranslationMap = new Map( + [ + [ComparisonResultType.PREVIOUS_VALUE, 'datakey.comparison-result-previous-value'], + [ComparisonResultType.DELTA_ABSOLUTE, 'datakey.comparison-result-delta-absolute'], + [ComparisonResultType.DELTA_PERCENT, 'datakey.comparison-result-delta-percent'] + ] +); + export interface KeyInfo { name: string; aggregationType?: AggregationType; + comparisonEnabled?: boolean; + timeForComparison?: ComparisonDuration; + comparisonCustomIntervalValue?: number; + comparisonResultType?: ComparisonResultType; label?: string; color?: string; funcBody?: string; diff --git a/ui-ngx/src/assets/locale/locale.constant-en_US.json b/ui-ngx/src/assets/locale/locale.constant-en_US.json index d07b262bcc..e64d7b9b78 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -1047,7 +1047,11 @@ "aggregation-type-max-hint": "Take max value", "aggregation-type-avg-hint": "Calculate average value", "aggregation-type-sum-hint": "Calculate sum value", - "aggregation-type-count-hint": "Calculate count value" + "aggregation-type-count-hint": "Calculate count value", + "comparison-result": "Comparison result", + "comparison-result-previous-value": "Previous value", + "comparison-result-delta-absolute": "Delta (absolute)", + "comparison-result-delta-percent": "Delta (percent)" }, "datasource": { "type": "Datasource type", From 70466bf71ca68e38b04239c60d0d13baa49beb66 Mon Sep 17 00:00:00 2001 From: Igor Kulikov Date: Thu, 15 Sep 2022 14:18:16 +0300 Subject: [PATCH 099/108] UI: Improve timewindow configuration for aggregation comparison --- .../app/core/api/entity-data-subscription.ts | 2 +- .../widget/widget-config.component.html | 2 + .../widget/widget-config.component.ts | 11 ++++- .../widget/widget-container.component.html | 2 + .../home/models/dashboard-component.models.ts | 9 ++++- .../components/time/timewindow.component.ts | 40 +++++++++++++++++-- ui-ngx/src/app/shared/models/widget.models.ts | 17 ++++++++ 7 files changed, 77 insertions(+), 6 deletions(-) diff --git a/ui-ngx/src/app/core/api/entity-data-subscription.ts b/ui-ngx/src/app/core/api/entity-data-subscription.ts index 75c4e0b922..4dc0e7c4e1 100644 --- a/ui-ngx/src/app/core/api/entity-data-subscription.ts +++ b/ui-ngx/src/app/core/api/entity-data-subscription.ts @@ -1033,7 +1033,7 @@ export class EntityDataSubscription { isLatestDataAgg, subsTw, this.utils, - this.entityDataSubscriptionOptions.ignoreDataUpdateOnIntervalTick + this.entityDataSubscriptionOptions.ignoreDataUpdateOnIntervalTick || isLatestDataAgg ); } diff --git a/ui-ngx/src/app/modules/home/components/widget/widget-config.component.html b/ui-ngx/src/app/modules/home/components/widget/widget-config.component.html index 1659ee636d..3adb2d4fb6 100644 --- a/ui-ngx/src/app/modules/home/components/widget/widget-config.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/widget-config.component.html @@ -34,6 +34,8 @@ style="padding-right: 8px;">widget-config.timewindow diff --git a/ui-ngx/src/app/modules/home/components/widget/widget-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/widget-config.component.ts index 7d82a6ca02..2286510ba3 100644 --- a/ui-ngx/src/app/modules/home/components/widget/widget-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/widget-config.component.ts @@ -20,7 +20,7 @@ import { Store } from '@ngrx/store'; import { AppState } from '@core/core.state'; import { DataKey, - Datasource, datasourcesHasAggregation, + Datasource, datasourcesHasAggregation, datasourcesHasOnlyComparisonAggregation, DatasourceType, datasourceTypeTranslationMap, defaultLegendConfig, @@ -743,6 +743,15 @@ export class WidgetConfigComponent extends PageComponent implements OnInit, Cont } } + public onlyHistoryTimewindow(): boolean { + if (this.widgetType === widgetType.latest) { + const datasources = this.dataSettings.get('datasources').value; + return datasourcesHasOnlyComparisonAggregation(datasources); + } else { + return false; + } + } + public onDatasourceDrop(event: CdkDragDrop) { const datasourcesFormArray = this.datasourcesFormArray(); const datasourceForm = datasourcesFormArray.at(event.previousIndex); diff --git a/ui-ngx/src/app/modules/home/components/widget/widget-container.component.html b/ui-ngx/src/app/modules/home/components/widget/widget-container.component.html index 9f99ffbf29..ad8f65a48b 100644 --- a/ui-ngx/src/app/modules/home/components/widget/widget-container.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/widget-container.component.html @@ -47,6 +47,8 @@ { + this.notifyChanged(); + }); + } else { + this.updateDisplayValue(); + } } notifyChanged() { @@ -309,7 +343,7 @@ export class TimewindowComponent implements OnInit, OnDestroy, ControlValueAcces this.millisecondsToTimeStringPipe.transform(this.innerValue.realtime.timewindowMs); } } else { - this.innerValue.displayValue = !this.historyOnly ? (this.translate.instant('timewindow.history') + ' - ') : ''; + this.innerValue.displayValue = (!this.historyOnly || this.alwaysDisplayTypePrefix) ? (this.translate.instant('timewindow.history') + ' - ') : ''; if (this.innerValue.history.historyType === HistoryWindowType.LAST_INTERVAL) { this.innerValue.displayValue += this.translate.instant('timewindow.last-prefix') + ' ' + this.millisecondsToTimeStringPipe.transform(this.innerValue.history.timewindowMs); diff --git a/ui-ngx/src/app/shared/models/widget.models.ts b/ui-ngx/src/app/shared/models/widget.models.ts index c654c87784..0472949680 100644 --- a/ui-ngx/src/app/shared/models/widget.models.ts +++ b/ui-ngx/src/app/shared/models/widget.models.ts @@ -367,6 +367,23 @@ export function datasourcesHasAggregation(datasources?: Array): bool return false; } +export function datasourcesHasOnlyComparisonAggregation(datasources?: Array): boolean { + if (!datasourcesHasAggregation(datasources)) { + return false; + } + if (datasources) { + const foundDatasource = datasources.find(datasource => { + const found = datasource.dataKeys && datasource.dataKeys.find(key => key.type === DataKeyType.timeseries && + key.aggregationType && key.aggregationType !== AggregationType.NONE && !key.comparisonEnabled); + return !!found; + }); + if (foundDatasource) { + return false; + } + } + return true; +} + export interface FormattedData { $datasource: Datasource; entityName: string; From 4bc66473db658e648695decfc8dae434583e6e2a Mon Sep 17 00:00:00 2001 From: Igor Kulikov Date: Thu, 15 Sep 2022 17:26:28 +0300 Subject: [PATCH 100/108] UI: Improve latest data key aggregation config --- .../widget/data-key-config.component.html | 22 +++++++++------ .../widget/data-key-config.component.scss | 1 + ui-ngx/src/app/shared/models/widget.models.ts | 6 ++--- .../assets/locale/locale.constant-en_US.json | 27 ++++++++++--------- 4 files changed, 33 insertions(+), 23 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/widget/data-key-config.component.html b/ui-ngx/src/app/modules/home/components/widget/data-key-config.component.html index fe4df7ca62..9088f5cc33 100644 --- a/ui-ngx/src/app/modules/home/components/widget/data-key-config.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/data-key-config.component.html @@ -63,24 +63,30 @@
- - datakey.aggregation-type + + datakey.aggregation - {{ (aggregation === aggregationTypes.NONE ? 'datakey.latest-value' : aggregationTypesTranslations.get(aggregationTypes[aggregation])) | translate }} + {{ aggregationTypesTranslations.get(aggregationTypes[aggregation]) | translate }} - {{ dataKeyFormGroup.get('aggregationType').value ? (dataKeyAggregationTypeHintTranslations.get(aggregationTypes[dataKeyFormGroup.get('aggregationType').value]) | translate) : '' }} + + {{ dataKeyFormGroup.get('aggregationType').value ? (dataKeyAggregationTypeHintTranslations.get(aggregationTypes[dataKeyFormGroup.get('aggregationType').value]) | translate) : '' }} +
+ {{ 'datakey.aggregation-type-hint-common' | translate }} +
+
- widgets.chart.comparison-settings + datakey.delta-calculation - + - {{ 'widgets.chart.enable-comparison' | translate }} + {{ 'datakey.enable-delta-calculation' | translate }} + {{ 'datakey.enable-delta-calculation-hint' | translate }} @@ -113,7 +119,7 @@ - datakey.comparison-result + datakey.delta-calculation-result {{ comparisonResultTypeTranslations.get(comparisonResultTypes[comparisonResultType]) | translate }} diff --git a/ui-ngx/src/app/modules/home/components/widget/data-key-config.component.scss b/ui-ngx/src/app/modules/home/components/widget/data-key-config.component.scss index d0d7e56137..7fd1fba872 100644 --- a/ui-ngx/src/app/modules/home/components/widget/data-key-config.component.scss +++ b/ui-ngx/src/app/modules/home/components/widget/data-key-config.component.scss @@ -83,6 +83,7 @@ .mat-expansion-panel-header { padding: 0; color: rgba(0, 0, 0, 0.87); + height: 140px; &:hover { background: none; diff --git a/ui-ngx/src/app/shared/models/widget.models.ts b/ui-ngx/src/app/shared/models/widget.models.ts index 0472949680..92b977e346 100644 --- a/ui-ngx/src/app/shared/models/widget.models.ts +++ b/ui-ngx/src/app/shared/models/widget.models.ts @@ -267,9 +267,9 @@ export enum ComparisonResultType { export const comparisonResultTypeTranslationMap = new Map( [ - [ComparisonResultType.PREVIOUS_VALUE, 'datakey.comparison-result-previous-value'], - [ComparisonResultType.DELTA_ABSOLUTE, 'datakey.comparison-result-delta-absolute'], - [ComparisonResultType.DELTA_PERCENT, 'datakey.comparison-result-delta-percent'] + [ComparisonResultType.PREVIOUS_VALUE, 'datakey.delta-calculation-result-previous-value'], + [ComparisonResultType.DELTA_ABSOLUTE, 'datakey.delta-calculation-result-delta-absolute'], + [ComparisonResultType.DELTA_PERCENT, 'datakey.delta-calculation-result-delta-percent'] ] ); diff --git a/ui-ngx/src/assets/locale/locale.constant-en_US.json b/ui-ngx/src/assets/locale/locale.constant-en_US.json index e64d7b9b78..1fd934d92d 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -1040,18 +1040,21 @@ "prev-value-description": "result of the previous function call;", "time-prev-description": "timestamp of the previous value;", "prev-orig-value-description": "original previous value;", - "aggregation-type": "Aggregation type", - "latest-value": "Latest value", - "aggregation-type-none-hint": "Take latest value", - "aggregation-type-min-hint": "Take min value", - "aggregation-type-max-hint": "Take max value", - "aggregation-type-avg-hint": "Calculate average value", - "aggregation-type-sum-hint": "Calculate sum value", - "aggregation-type-count-hint": "Calculate count value", - "comparison-result": "Comparison result", - "comparison-result-previous-value": "Previous value", - "comparison-result-delta-absolute": "Delta (absolute)", - "comparison-result-delta-percent": "Delta (percent)" + "aggregation": "Aggregation", + "aggregation-type-hint-common": "For performance reasons, the aggregated values calculation is available only for fixed time intervals like \"current day\", \"current month\", etc, and is not available for sliding window intervals like 'last 30 minutes' or 'last 24 hours'.", + "aggregation-type-none-hint": "Take latest value.", + "aggregation-type-min-hint": "Find minimum value among data points within a selected time window.", + "aggregation-type-max-hint": "Find maximum value among data points within a selected time window.", + "aggregation-type-avg-hint": "Calculate an average value among data points within a selected time window.", + "aggregation-type-sum-hint": "Sum all values of the data points within a selected time window.", + "aggregation-type-count-hint": "Total number of the data points within a selected time window.", + "delta-calculation": "Delta calculation", + "enable-delta-calculation": "Enable delta calculation", + "enable-delta-calculation-hint": "When enabled, the data key value is calculated based on the aggregated values for a selected time window and a specified comparison period. For performance reasons, the delta calculation is available only for history time windows and not for real-time values. For example, you may calculate the delta between the energy consumption for yesterday compared to the energy consumption for the day before yesterday.", + "delta-calculation-result": "Delta calculation result", + "delta-calculation-result-previous-value": "Previous value", + "delta-calculation-result-delta-absolute": "Delta (absolute)", + "delta-calculation-result-delta-percent": "Delta (percent)" }, "datasource": { "type": "Datasource type", From 189c1afb01b69faca09b6a05a8c1859005c1a7a3 Mon Sep 17 00:00:00 2001 From: Yuriy Lytvynchuk Date: Fri, 16 Sep 2022 10:12:08 +0300 Subject: [PATCH 101/108] refactor code --- .../engine/metadata/TbGetTelemetryNode.java | 22 +++++++++---------- 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTelemetryNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTelemetryNode.java index 914eb4cddd..f95909e813 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTelemetryNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTelemetryNode.java @@ -91,16 +91,14 @@ public class TbGetTelemetryNode implements TbNode { orderByFetchAll = ASC_ORDER; } aggregation = parseAggregationConfig(config.getAggregation()); - if (!fetchMode.equals(FETCH_MODE_ALL)) { - aggregation = Aggregation.NONE; - } + mapper = new ObjectMapper(); mapper.configure(JsonWriteFeature.QUOTE_FIELD_NAMES.mappedFeature(), false); mapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true); } Aggregation parseAggregationConfig(String aggName) { - if (StringUtils.isEmpty(aggName)) { + if (StringUtils.isEmpty(aggName) || !fetchMode.equals(FETCH_MODE_ALL)) { return Aggregation.NONE; } return Aggregation.valueOf(aggName); @@ -113,7 +111,7 @@ public class TbGetTelemetryNode implements TbNode { } else { try { if (config.isUseMetadataIntervalPatterns()) { - checkMetadataKeyPatterns(msg); + checkKeyPatterns(msg); } List keys = TbNodeUtils.processPatterns(tsKeyNames, msg); ListenableFuture> list = ctx.getTimeseriesService().findAll(ctx.getTenantId(), msg.getOriginator(), buildQueries(msg, keys)); @@ -232,23 +230,23 @@ public class TbGetTelemetryNode implements TbNode { return NumberUtils.isParsable(TbNodeUtils.processPattern(pattern, msg)); } - private void checkMetadataKeyPatterns(TbMsg msg) { + private void checkKeyPatterns(TbMsg msg) { isUndefined(msg, config.getStartIntervalPattern(), config.getEndIntervalPattern()); isInvalid(msg, config.getStartIntervalPattern(), config.getEndIntervalPattern()); } private void isUndefined(TbMsg msg, String startIntervalPattern, String endIntervalPattern) { if (getValuePattern(msg, startIntervalPattern) == null && getValuePattern(msg, endIntervalPattern) == null) { - throw new IllegalArgumentException("Message metadata values: '" + + throw new IllegalArgumentException("Message values: '" + replaceRegex(startIntervalPattern) + "' and '" + replaceRegex(endIntervalPattern) + "' are undefined"); } else { if (getValuePattern(msg, startIntervalPattern) == null) { - throw new IllegalArgumentException("Message metadata value: '" + + throw new IllegalArgumentException("Message value: '" + replaceRegex(startIntervalPattern) + "' is undefined"); } if (getValuePattern(msg, endIntervalPattern) == null) { - throw new IllegalArgumentException("Message metadata value: '" + + throw new IllegalArgumentException("Message value: '" + replaceRegex(endIntervalPattern) + "' is undefined"); } } @@ -256,16 +254,16 @@ public class TbGetTelemetryNode implements TbNode { private void isInvalid(TbMsg msg, String startIntervalPattern, String endIntervalPattern) { if (getInterval(msg).getStartTs() == null && getInterval(msg).getEndTs() == null) { - throw new IllegalArgumentException("Message metadata values: '" + + throw new IllegalArgumentException("Message values: '" + replaceRegex(startIntervalPattern) + "' and '" + replaceRegex(endIntervalPattern) + "' have invalid format"); } else { if (getInterval(msg).getStartTs() == null) { - throw new IllegalArgumentException("Message metadata value: '" + + throw new IllegalArgumentException("Message value: '" + replaceRegex(startIntervalPattern) + "' has invalid format"); } if (getInterval(msg).getEndTs() == null) { - throw new IllegalArgumentException("Message metadata value: '" + + throw new IllegalArgumentException("Message value: '" + replaceRegex(endIntervalPattern) + "' has invalid format"); } } From 89c715cd189cb68675436cbde94bf113fa8f02bc Mon Sep 17 00:00:00 2001 From: Andrii Shvaika Date: Fri, 16 Sep 2022 11:55:48 +0300 Subject: [PATCH 102/108] Fix Cassandra DAO --- .../service/telemetry/cmd/v2/AggHistoryCmd.java | 1 - .../service/telemetry/cmd/v2/EntityDataCmd.java | 12 ------------ .../server/dao/timeseries/TimeseriesService.java | 1 - .../server/dao/model/ModelConstants.java | 8 ++++---- .../dao/timeseries/AggregatePartitionsFunction.java | 13 +++++++------ 5 files changed, 11 insertions(+), 24 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/telemetry/cmd/v2/AggHistoryCmd.java b/application/src/main/java/org/thingsboard/server/service/telemetry/cmd/v2/AggHistoryCmd.java index 4d191590c7..423c55bd0d 100644 --- a/application/src/main/java/org/thingsboard/server/service/telemetry/cmd/v2/AggHistoryCmd.java +++ b/application/src/main/java/org/thingsboard/server/service/telemetry/cmd/v2/AggHistoryCmd.java @@ -16,7 +16,6 @@ package org.thingsboard.server.service.telemetry.cmd.v2; import lombok.Data; -import org.thingsboard.server.common.data.kv.Aggregation; import java.util.List; diff --git a/application/src/main/java/org/thingsboard/server/service/telemetry/cmd/v2/EntityDataCmd.java b/application/src/main/java/org/thingsboard/server/service/telemetry/cmd/v2/EntityDataCmd.java index e18b1a745b..8a187afa7b 100644 --- a/application/src/main/java/org/thingsboard/server/service/telemetry/cmd/v2/EntityDataCmd.java +++ b/application/src/main/java/org/thingsboard/server/service/telemetry/cmd/v2/EntityDataCmd.java @@ -62,16 +62,4 @@ public class EntityDataCmd extends DataCmd { return historyCmd != null || latestCmd != null || tsCmd != null || aggHistoryCmd != null || aggTsCmd != null; } - @JsonIgnore - public boolean hasRegularCmds() { - return historyCmd != null || latestCmd != null || tsCmd != null; - } - - @JsonIgnore - public boolean hasAggCmds() { - return aggHistoryCmd != null || aggTsCmd != null; - } - - - } diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/timeseries/TimeseriesService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/timeseries/TimeseriesService.java index 0015ee73be..cf17eec88d 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/timeseries/TimeseriesService.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/timeseries/TimeseriesService.java @@ -27,7 +27,6 @@ import org.thingsboard.server.common.data.kv.TsKvEntry; import java.util.Collection; import java.util.List; -import java.util.Map; /** * @author Andrew Shvayka diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java b/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java index 5218de60e4..e27bf174a9 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java @@ -631,14 +631,14 @@ public class ModelConstants { protected static final String[] NONE_AGGREGATION_COLUMNS = new String[]{LONG_VALUE_COLUMN, DOUBLE_VALUE_COLUMN, BOOLEAN_VALUE_COLUMN, STRING_VALUE_COLUMN, JSON_VALUE_COLUMN, KEY_COLUMN, TS_COLUMN}; - protected static final String[] COUNT_AGGREGATION_COLUMNS = new String[]{count(LONG_VALUE_COLUMN), count(DOUBLE_VALUE_COLUMN), count(BOOLEAN_VALUE_COLUMN), count(STRING_VALUE_COLUMN), count(JSON_VALUE_COLUMN)}; + protected static final String[] COUNT_AGGREGATION_COLUMNS = new String[]{count(LONG_VALUE_COLUMN), count(DOUBLE_VALUE_COLUMN), count(BOOLEAN_VALUE_COLUMN), count(STRING_VALUE_COLUMN), count(JSON_VALUE_COLUMN), max(TS_COLUMN)}; protected static final String[] MIN_AGGREGATION_COLUMNS = - ArrayUtils.addAll(COUNT_AGGREGATION_COLUMNS, new String[]{min(LONG_VALUE_COLUMN), min(DOUBLE_VALUE_COLUMN), min(BOOLEAN_VALUE_COLUMN), min(STRING_VALUE_COLUMN), min(JSON_VALUE_COLUMN), max(TS_COLUMN)}); + ArrayUtils.addAll(COUNT_AGGREGATION_COLUMNS, new String[]{min(LONG_VALUE_COLUMN), min(DOUBLE_VALUE_COLUMN), min(BOOLEAN_VALUE_COLUMN), min(STRING_VALUE_COLUMN), min(JSON_VALUE_COLUMN)}); protected static final String[] MAX_AGGREGATION_COLUMNS = - ArrayUtils.addAll(COUNT_AGGREGATION_COLUMNS, new String[]{max(LONG_VALUE_COLUMN), max(DOUBLE_VALUE_COLUMN), max(BOOLEAN_VALUE_COLUMN), max(STRING_VALUE_COLUMN), max(JSON_VALUE_COLUMN), max(TS_COLUMN)}); + ArrayUtils.addAll(COUNT_AGGREGATION_COLUMNS, new String[]{max(LONG_VALUE_COLUMN), max(DOUBLE_VALUE_COLUMN), max(BOOLEAN_VALUE_COLUMN), max(STRING_VALUE_COLUMN), max(JSON_VALUE_COLUMN)}); protected static final String[] SUM_AGGREGATION_COLUMNS = - ArrayUtils.addAll(COUNT_AGGREGATION_COLUMNS, new String[]{sum(LONG_VALUE_COLUMN), sum(DOUBLE_VALUE_COLUMN), max(TS_COLUMN)}); + ArrayUtils.addAll(COUNT_AGGREGATION_COLUMNS, new String[]{sum(LONG_VALUE_COLUMN), sum(DOUBLE_VALUE_COLUMN)}); protected static final String[] AVG_AGGREGATION_COLUMNS = SUM_AGGREGATION_COLUMNS; public static String min(String s) { diff --git a/dao/src/main/java/org/thingsboard/server/dao/timeseries/AggregatePartitionsFunction.java b/dao/src/main/java/org/thingsboard/server/dao/timeseries/AggregatePartitionsFunction.java index 7a19e9fbf8..e774ad489a 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/timeseries/AggregatePartitionsFunction.java +++ b/dao/src/main/java/org/thingsboard/server/dao/timeseries/AggregatePartitionsFunction.java @@ -49,12 +49,13 @@ public class AggregatePartitionsFunction implements com.google.common.util.concu private static final int BOOL_CNT_POS = 2; private static final int STR_CNT_POS = 3; private static final int JSON_CNT_POS = 4; - private static final int LONG_POS = 5; - private static final int DOUBLE_POS = 6; - private static final int BOOL_POS = 7; - private static final int STR_POS = 8; - private static final int JSON_POS = 9; - private static final int MAX_TS_POS = 10; + private static final int MAX_TS_POS = 5; + private static final int LONG_POS = 6; + private static final int DOUBLE_POS = 7; + private static final int BOOL_POS = 8; + private static final int STR_POS = 9; + private static final int JSON_POS = 10; + private final Aggregation aggregation; private final String key; From 5816923b85b703924fbc1b0c3de99f94e023166a Mon Sep 17 00:00:00 2001 From: Kalutka Zhenya Date: Fri, 16 Sep 2022 12:50:10 +0300 Subject: [PATCH 103/108] delete "failure" type --- ui-ngx/src/app/shared/models/rule-node.models.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/ui-ngx/src/app/shared/models/rule-node.models.ts b/ui-ngx/src/app/shared/models/rule-node.models.ts index 6ff3b707de..c6549f5b39 100644 --- a/ui-ngx/src/app/shared/models/rule-node.models.ts +++ b/ui-ngx/src/app/shared/models/rule-node.models.ts @@ -371,8 +371,7 @@ export enum MessageType { ENTITY_ASSIGNED_FROM_TENANT = 'ENTITY_ASSIGNED_FROM_TENANT', ENTITY_ASSIGNED_TO_TENANT = 'ENTITY_ASSIGNED_TO_TENANT', TIMESERIES_UPDATED = 'TIMESERIES_UPDATED', - TIMESERIES_DELETED = 'TIMESERIES_DELETED', - FAILURE = 'FAILURE' + TIMESERIES_DELETED = 'TIMESERIES_DELETED' } export const messageTypeNames = new Map( @@ -405,8 +404,7 @@ export const messageTypeNames = new Map( [MessageType.ENTITY_ASSIGNED_FROM_TENANT, 'Entity Assigned From Tenant'], [MessageType.ENTITY_ASSIGNED_TO_TENANT, 'Entity Assigned To Tenant'], [MessageType.TIMESERIES_UPDATED, 'Timeseries Updated'], - [MessageType.TIMESERIES_DELETED, 'Timeseries Deleted'], - [MessageType.FAILURE, 'Failure'] + [MessageType.TIMESERIES_DELETED, 'Timeseries Deleted'] ] ); From eebe8d8cbf07fd187ba17e5eb3ceea153f09b549 Mon Sep 17 00:00:00 2001 From: Andrii Shvaika Date: Fri, 16 Sep 2022 15:20:27 +0300 Subject: [PATCH 104/108] Fix invalid logic related to endTs in read queries --- .../timescale/ts/TimescaleTsKvEntity.java | 1 - ...stractChunkedAggregationTimeseriesDao.java | 31 ++++++++++--------- .../timescale/AggregationRepository.java | 2 +- .../timescale/TimescaleTimeseriesDao.java | 15 +++++++-- .../CassandraBaseTimeseriesDao.java | 6 ++-- .../timeseries/BaseTimeseriesServiceTest.java | 18 +++++------ ...ctChunkedAggregationTimeseriesDaoTest.java | 23 +++++++------- 7 files changed, 53 insertions(+), 43 deletions(-) diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sqlts/timescale/ts/TimescaleTsKvEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sqlts/timescale/ts/TimescaleTsKvEntity.java index 9e072e25e4..ba5ad92f4f 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sqlts/timescale/ts/TimescaleTsKvEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sqlts/timescale/ts/TimescaleTsKvEntity.java @@ -79,7 +79,6 @@ import static org.thingsboard.server.dao.sqlts.timescale.AggregationRepository.F @ColumnResult(name = "longValueCount", type = Long.class), @ColumnResult(name = "doubleValueCount", type = Long.class), @ColumnResult(name = "jsonValueCount", type = Long.class), - @ColumnResult(name = "jsonValueCount", type = Long.class), @ColumnResult(name = "maxAggTs", type = Long.class), } ) diff --git a/dao/src/main/java/org/thingsboard/server/dao/sqlts/AbstractChunkedAggregationTimeseriesDao.java b/dao/src/main/java/org/thingsboard/server/dao/sqlts/AbstractChunkedAggregationTimeseriesDao.java index 9acbfe85fb..22c4661fcd 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sqlts/AbstractChunkedAggregationTimeseriesDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sqlts/AbstractChunkedAggregationTimeseriesDao.java @@ -121,15 +121,14 @@ public abstract class AbstractChunkedAggregationTimeseriesDao extends AbstractSq return Futures.immediateFuture(findAllAsyncWithLimit(entityId, query)); } else { List>> futures = new ArrayList<>(); - long endPeriod = query.getEndTs(); long startPeriod = query.getStartTs(); + long endPeriod = Math.max(query.getStartTs() + 1, query.getEndTs()); long step = query.getInterval(); - while (startPeriod <= endPeriod) { + while (startPeriod < endPeriod) { long startTs = startPeriod; - long endTs = Math.min(startPeriod + step, endPeriod + 1); + long endTs = Math.min(startPeriod + step, endPeriod); long ts = startTs + (endTs - startTs) / 2; - ListenableFuture> aggregateTsKvEntry = - service.submit(() -> findAndAggregateAsync(entityId, query.getKey(), startTs, endTs, ts, query.getAggregation())); + ListenableFuture> aggregateTsKvEntry = findAndAggregateAsync(entityId, query.getKey(), startTs, endTs, ts, query.getAggregation()); futures.add(aggregateTsKvEntry); startPeriod = endTs; } @@ -152,16 +151,18 @@ public abstract class AbstractChunkedAggregationTimeseriesDao extends AbstractSq return new ReadTsKvQueryResult(query.getId(), tsKvEntries, lastTs); } - Optional findAndAggregateAsync(EntityId entityId, String key, long startTs, long endTs, long ts, Aggregation aggregation) { - TsKvEntity entity = switchAggregation(entityId, key, startTs, endTs, aggregation); - if (entity != null && entity.isNotEmpty()) { - entity.setEntityId(entityId.getId()); - entity.setStrKey(key); - entity.setTs(ts); - return Optional.of(entity); - } else { - return Optional.empty(); - } + ListenableFuture> findAndAggregateAsync(EntityId entityId, String key, long startTs, long endTs, long ts, Aggregation aggregation) { + return service.submit(() -> { + TsKvEntity entity = switchAggregation(entityId, key, startTs, endTs, aggregation); + if (entity != null && entity.isNotEmpty()) { + entity.setEntityId(entityId.getId()); + entity.setStrKey(key); + entity.setTs(ts); + return Optional.of(entity); + } else { + return Optional.empty(); + } + }); } protected TsKvEntity switchAggregation(EntityId entityId, String key, long startTs, long endTs, Aggregation aggregation) { diff --git a/dao/src/main/java/org/thingsboard/server/dao/sqlts/timescale/AggregationRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sqlts/timescale/AggregationRepository.java index db0a1753d8..d37234dfde 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sqlts/timescale/AggregationRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sqlts/timescale/AggregationRepository.java @@ -39,7 +39,7 @@ public class AggregationRepository { public static final String FROM_WHERE_CLAUSE = "FROM ts_kv tskv WHERE " + "tskv.entity_id = cast(:entityId AS uuid) " + "AND tskv.key= cast(:entityKey AS int) " + - "AND tskv.ts > :startTs AND tskv.ts <= :endTs " + + "AND tskv.ts >= :startTs AND tskv.ts < :endTs " + "GROUP BY tskv.entity_id, tskv.key, tsBucket " + "ORDER BY tskv.entity_id, tskv.key, tsBucket"; diff --git a/dao/src/main/java/org/thingsboard/server/dao/sqlts/timescale/TimescaleTimeseriesDao.java b/dao/src/main/java/org/thingsboard/server/dao/sqlts/timescale/TimescaleTimeseriesDao.java index 76dabb24f6..6e9f9e61b8 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sqlts/timescale/TimescaleTimeseriesDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sqlts/timescale/TimescaleTimeseriesDao.java @@ -155,7 +155,7 @@ public class TimescaleTimeseriesDao extends AbstractSqlTimeseriesDao implements return Futures.immediateFuture(findAllAsyncWithLimit(entityId, query)); } else { long startTs = query.getStartTs(); - long endTs = query.getEndTs(); + long endTs = Math.max(query.getStartTs() + 1, query.getEndTs()); long timeBucket = query.getInterval(); List> data = findAllAndAggregateAsync(entityId, query.getKey(), startTs, endTs, timeBucket, query.getAggregation()); return getReadTsKvQueryResultFuture(query, Futures.immediateFuture(data)); @@ -185,7 +185,18 @@ public class TimescaleTimeseriesDao extends AbstractSqlTimeseriesDao implements } private List> findAllAndAggregateAsync(EntityId entityId, String key, long startTs, long endTs, long timeBucket, Aggregation aggregation) { - List timescaleTsKvEntities = switchAggregation(key, startTs, endTs, timeBucket, aggregation, entityId.getId()); + long interval = endTs - startTs; + long remainingPart = interval % timeBucket; + List timescaleTsKvEntities; + if (remainingPart == 0) { + timescaleTsKvEntities = switchAggregation(key, startTs, endTs, timeBucket, aggregation, entityId.getId()); + } else { + interval = interval - remainingPart; + timescaleTsKvEntities = new ArrayList<>(); + timescaleTsKvEntities.addAll(switchAggregation(key, startTs, startTs + interval, timeBucket, aggregation, entityId.getId())); + timescaleTsKvEntities.addAll(switchAggregation(key, startTs + interval, endTs, remainingPart, aggregation, entityId.getId())); + } + if (!CollectionUtils.isEmpty(timescaleTsKvEntities)) { List> result = new ArrayList<>(); timescaleTsKvEntities.forEach(entity -> { diff --git a/dao/src/main/java/org/thingsboard/server/dao/timeseries/CassandraBaseTimeseriesDao.java b/dao/src/main/java/org/thingsboard/server/dao/timeseries/CassandraBaseTimeseriesDao.java index 35eb5b8a18..367ad942a7 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/timeseries/CassandraBaseTimeseriesDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/timeseries/CassandraBaseTimeseriesDao.java @@ -268,12 +268,12 @@ public class CassandraBaseTimeseriesDao extends AbstractCassandraBaseTimeseriesD return findAllAsyncWithLimit(tenantId, entityId, query); } else { long startPeriod = query.getStartTs(); - long endPeriod = query.getEndTs(); + long endPeriod = Math.max(query.getStartTs() + 1, query.getEndTs()); long step = Math.max(query.getInterval(), MIN_AGGREGATION_STEP_MS); List>> futures = new ArrayList<>(); - while (startPeriod <= endPeriod) { + while (startPeriod < endPeriod) { long startTs = startPeriod; - long endTs = Math.min(startPeriod + step, endPeriod + 1); + long endTs = Math.min(startPeriod + step, endPeriod); long ts = endTs - startTs; ReadTsKvQuery subQuery = new BaseReadTsKvQuery(query.getKey(), startTs, endTs, ts, 1, query.getAggregation(), query.getOrder()); futures.add(findAndAggregateAsync(tenantId, entityId, subQuery, toPartitionTs(startTs), toPartitionTs(endTs))); diff --git a/dao/src/test/java/org/thingsboard/server/dao/service/timeseries/BaseTimeseriesServiceTest.java b/dao/src/test/java/org/thingsboard/server/dao/service/timeseries/BaseTimeseriesServiceTest.java index 5339863044..4e2fd17846 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/service/timeseries/BaseTimeseriesServiceTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/service/timeseries/BaseTimeseriesServiceTest.java @@ -213,17 +213,17 @@ public abstract class BaseTimeseriesServiceTest extends AbstractServiceTest { } saveEntries(deviceId, TS + 100L + 1L); - List queries = List.of(new BaseReadTsKvQuery(LONG_KEY, TS, TS + 100, 101, 1, Aggregation.COUNT, DESC_ORDER)); + List queries = List.of(new BaseReadTsKvQuery(LONG_KEY, TS, TS + 100, 100, 1, Aggregation.COUNT, DESC_ORDER)); List entries = tsService.findAll(tenantId, deviceId, queries).get(); Assert.assertEquals(1, entries.size()); - Assert.assertEquals(toTsEntry(TS + 50, new LongDataEntry(LONG_KEY, 11L)), entries.get(0)); + Assert.assertEquals(toTsEntry(TS + 50, new LongDataEntry(LONG_KEY, 10L)), entries.get(0)); EntityView entityView = saveAndCreateEntityView(deviceId, List.of(LONG_KEY)); entries = tsService.findAll(tenantId, entityView.getId(), queries).get(); Assert.assertEquals(1, entries.size()); - Assert.assertEquals(toTsEntry(TS + 50, new LongDataEntry(LONG_KEY, 11L)), entries.get(0)); + Assert.assertEquals(toTsEntry(TS + 50, new LongDataEntry(LONG_KEY, 10L)), entries.get(0)); } @Test @@ -240,14 +240,14 @@ public abstract class BaseTimeseriesServiceTest extends AbstractServiceTest { List entries = tsService.findAll(tenantId, deviceId, queries).get(); Assert.assertEquals(2, entries.size()); Assert.assertEquals(toTsEntry(TS + 25000, new LongDataEntry(LONG_KEY, 5L)), entries.get(0)); - Assert.assertEquals(toTsEntry(TS + 75000, new LongDataEntry(LONG_KEY, 5L)), entries.get(1)); + Assert.assertEquals(toTsEntry(TS + 75000 - 1, new LongDataEntry(LONG_KEY, 5L)), entries.get(1)); EntityView entityView = saveAndCreateEntityView(deviceId, List.of(LONG_KEY)); entries = tsService.findAll(tenantId, entityView.getId(), queries).get(); Assert.assertEquals(2, entries.size()); Assert.assertEquals(toTsEntry(TS + 25000, new LongDataEntry(LONG_KEY, 5L)), entries.get(0)); - Assert.assertEquals(toTsEntry(TS + 75000, new LongDataEntry(LONG_KEY, 5L)), entries.get(1)); + Assert.assertEquals(toTsEntry(TS + 75000 - 1, new LongDataEntry(LONG_KEY, 5L)), entries.get(1)); } @Test @@ -264,14 +264,14 @@ public abstract class BaseTimeseriesServiceTest extends AbstractServiceTest { List entries = tsService.findAll(tenantId, deviceId, queries).get(); Assert.assertEquals(2, entries.size()); Assert.assertEquals(toTsEntry(TS + 25000, new LongDataEntry(LONG_KEY, 5L)), entries.get(0)); - Assert.assertEquals(toTsEntry(TS + 65000, new LongDataEntry(LONG_KEY, 4L)), entries.get(1)); + Assert.assertEquals(toTsEntry(TS + 65000, new LongDataEntry(LONG_KEY, 3L)), entries.get(1)); EntityView entityView = saveAndCreateEntityView(deviceId, List.of(LONG_KEY)); entries = tsService.findAll(tenantId, entityView.getId(), queries).get(); Assert.assertEquals(2, entries.size()); Assert.assertEquals(toTsEntry(TS + 25000, new LongDataEntry(LONG_KEY, 5L)), entries.get(0)); - Assert.assertEquals(toTsEntry(TS + 65000, new LongDataEntry(LONG_KEY, 4L)), entries.get(1)); + Assert.assertEquals(toTsEntry(TS + 65000, new LongDataEntry(LONG_KEY, 3L)), entries.get(1)); } @Test @@ -286,14 +286,14 @@ public abstract class BaseTimeseriesServiceTest extends AbstractServiceTest { List entries = tsService.findAll(tenantId, deviceId, queries).get(); Assert.assertEquals(2, entries.size()); Assert.assertEquals(toTsEntry(TS + 25000, new LongDataEntry(LONG_KEY, 5L)), entries.get(0)); - Assert.assertEquals(toTsEntry(TS + 75000, new LongDataEntry(LONG_KEY, 5L)), entries.get(1)); + Assert.assertEquals(toTsEntry(TS + 75000 - 1, new LongDataEntry(LONG_KEY, 4L)), entries.get(1)); EntityView entityView = saveAndCreateEntityView(deviceId, List.of(LONG_KEY)); entries = tsService.findAll(tenantId, entityView.getId(), queries).get(); Assert.assertEquals(2, entries.size()); Assert.assertEquals(toTsEntry(TS + 25000, new LongDataEntry(LONG_KEY, 5L)), entries.get(0)); - Assert.assertEquals(toTsEntry(TS + 75000, new LongDataEntry(LONG_KEY, 5L)), entries.get(1)); + Assert.assertEquals(toTsEntry(TS + 75000 - 1, new LongDataEntry(LONG_KEY, 4L)), entries.get(1)); } @Test diff --git a/dao/src/test/java/org/thingsboard/server/dao/sqlts/AbstractChunkedAggregationTimeseriesDaoTest.java b/dao/src/test/java/org/thingsboard/server/dao/sqlts/AbstractChunkedAggregationTimeseriesDaoTest.java index 40705809fd..9c4b1cbbea 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/sqlts/AbstractChunkedAggregationTimeseriesDaoTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/sqlts/AbstractChunkedAggregationTimeseriesDaoTest.java @@ -19,6 +19,8 @@ import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import org.junit.Before; import org.junit.Test; +import org.mockito.Mockito; +import org.springframework.test.util.ReflectionTestUtils; import org.thingsboard.server.common.data.kv.BaseReadTsKvQuery; import org.thingsboard.server.common.data.kv.ReadTsKvQuery; import org.thingsboard.server.common.data.kv.ReadTsKvQueryResult; @@ -44,13 +46,13 @@ public class AbstractChunkedAggregationTimeseriesDaoTest { final int LIMIT = 1; final String TEMP = "temp"; final String DESC = "DESC"; - AbstractChunkedAggregationTimeseriesDao tsDao; + private AbstractChunkedAggregationTimeseriesDao tsDao; @Before public void setUp() throws Exception { tsDao = spy(AbstractChunkedAggregationTimeseriesDao.class); Optional optionalListenableFuture = Optional.of(mock(TsKvEntry.class)); - willReturn(optionalListenableFuture).given(tsDao).findAndAggregateAsync(any(), anyString(), anyLong(), anyLong(), anyLong(), any()); + willReturn(Futures.immediateFuture(optionalListenableFuture)).given(tsDao).findAndAggregateAsync(any(), anyString(), anyLong(), anyLong(), anyLong(), any()); willReturn(Futures.immediateFuture(mock(ReadTsKvQueryResult.class))).given(tsDao).getReadTsKvQueryResultFuture(any(), any()); } @@ -58,11 +60,11 @@ public class AbstractChunkedAggregationTimeseriesDaoTest { public void givenIntervalNotMultiplePeriod_whenAggregateCount_thenLastIntervalShorterThanOthersAndEqualsEndTs() { ReadTsKvQuery query = new BaseReadTsKvQuery(TEMP, 1, 3000, 2000, LIMIT, COUNT, DESC); ReadTsKvQuery subQueryFirst = new BaseReadTsKvQuery(TEMP, 1, 2001, 1001, LIMIT, COUNT, DESC); - ReadTsKvQuery subQuerySecond = new BaseReadTsKvQuery(TEMP, 2001, 3001, 2501, LIMIT, COUNT, DESC); + ReadTsKvQuery subQuerySecond = new BaseReadTsKvQuery(TEMP, 2001, 3000, 2501, LIMIT, COUNT, DESC); tsDao.findAllAsync(SYS_TENANT_ID, SYS_TENANT_ID, query); verify(tsDao, times(2)).findAndAggregateAsync(any(), any(), anyLong(), anyLong(), anyLong(), any()); verify(tsDao, times(1)).findAndAggregateAsync(SYS_TENANT_ID, subQueryFirst.getKey(), 1, 2001, getTsForReadTsKvQuery(1, 2001), COUNT); - verify(tsDao, times(1)).findAndAggregateAsync(SYS_TENANT_ID, subQuerySecond.getKey(), 2001, 3000 + 1, getTsForReadTsKvQuery(2001, 3001), COUNT); + verify(tsDao, times(1)).findAndAggregateAsync(SYS_TENANT_ID, subQuerySecond.getKey(), 2001, 3000, getTsForReadTsKvQuery(2001, 3000), COUNT); } @Test @@ -72,19 +74,17 @@ public class AbstractChunkedAggregationTimeseriesDaoTest { willCallRealMethod().given(tsDao).findAllAsync(SYS_TENANT_ID, SYS_TENANT_ID, query); assertThat(tsDao.findAllAsync(SYS_TENANT_ID, SYS_TENANT_ID, query)).isNotNull(); verify(tsDao, times(1)).findAndAggregateAsync(any(), any(), anyLong(), anyLong(), anyLong(), any()); - verify(tsDao, times(1)).findAndAggregateAsync(SYS_TENANT_ID, subQueryFirst.getKey(), 1, 3000 + 1, getTsForReadTsKvQuery(1, 3001), COUNT); + verify(tsDao, times(1)).findAndAggregateAsync(SYS_TENANT_ID, subQueryFirst.getKey(), 1, 3000, getTsForReadTsKvQuery(1, 3000), COUNT); } @Test public void givenIntervalNotMultiplePeriod_whenAggregateCount_thenIntervalEqualsPeriodMinusOne() { ReadTsKvQuery query = new BaseReadTsKvQuery(TEMP, 1, 3000, 2999, LIMIT, COUNT, DESC); ReadTsKvQuery subQueryFirst = new BaseReadTsKvQuery(TEMP, 1, 3000, 1500, LIMIT, COUNT, DESC); - ReadTsKvQuery subQuerySecond = new BaseReadTsKvQuery(TEMP, 3000, 3001, 3000, LIMIT, COUNT, DESC); willCallRealMethod().given(tsDao).findAllAsync(SYS_TENANT_ID, SYS_TENANT_ID, query); tsDao.findAllAsync(SYS_TENANT_ID, SYS_TENANT_ID, query); - verify(tsDao, times(2)).findAndAggregateAsync(any(), any(), anyLong(), anyLong(), anyLong(), any()); + verify(tsDao, times(1)).findAndAggregateAsync(any(), any(), anyLong(), anyLong(), anyLong(), any()); verify(tsDao, times(1)).findAndAggregateAsync(SYS_TENANT_ID, subQueryFirst.getKey(), 1, 3000, getTsForReadTsKvQuery(1, 3000), COUNT); - verify(tsDao, times(1)).findAndAggregateAsync(SYS_TENANT_ID, subQuerySecond.getKey(), 3000, 3001, getTsForReadTsKvQuery(3000, 3001), COUNT); } @@ -95,7 +95,7 @@ public class AbstractChunkedAggregationTimeseriesDaoTest { willCallRealMethod().given(tsDao).findAllAsync(SYS_TENANT_ID, SYS_TENANT_ID, query); tsDao.findAllAsync(SYS_TENANT_ID, SYS_TENANT_ID, query); verify(tsDao, times(1)).findAndAggregateAsync(any(), any(), anyLong(), anyLong(), anyLong(), any()); - verify(tsDao, times(1)).findAndAggregateAsync(SYS_TENANT_ID, subQueryFirst.getKey(), 1, 3001, getTsForReadTsKvQuery(1, 3001), COUNT); + verify(tsDao, times(1)).findAndAggregateAsync(SYS_TENANT_ID, subQueryFirst.getKey(), 1, 3000, getTsForReadTsKvQuery(1, 3000), COUNT); } @Test @@ -135,7 +135,7 @@ public class AbstractChunkedAggregationTimeseriesDaoTest { willCallRealMethod().given(tsDao).findAllAsync(SYS_TENANT_ID, SYS_TENANT_ID, query); tsDao.findAllAsync(SYS_TENANT_ID, SYS_TENANT_ID, query); verify(tsDao, times(1)).findAndAggregateAsync(any(), any(), anyLong(), anyLong(), anyLong(), any()); - verify(tsDao, times(1)).findAndAggregateAsync(SYS_TENANT_ID, subQueryFirst.getKey(), 1, 3001, getTsForReadTsKvQuery(1, 3001), COUNT); + verify(tsDao, times(1)).findAndAggregateAsync(SYS_TENANT_ID, subQueryFirst.getKey(), 1, 3000, getTsForReadTsKvQuery(1, 3000), COUNT); } @Test @@ -145,8 +145,7 @@ public class AbstractChunkedAggregationTimeseriesDaoTest { tsDao.findAllAsync(SYS_TENANT_ID, SYS_TENANT_ID, query); verify(tsDao, times(1000)).findAndAggregateAsync(any(), any(), anyLong(), anyLong(), anyLong(), any()); for (long i = 1; i <= 3000; i += 3) { - ReadTsKvQuery querySub = new BaseReadTsKvQuery(TEMP, i, i + 3, i + (i + 3 - i) / 2, LIMIT, COUNT, DESC); - verify(tsDao, times(1)).findAndAggregateAsync(SYS_TENANT_ID, querySub.getKey(), i, i + 3, getTsForReadTsKvQuery(i, i + 3), COUNT); + verify(tsDao, times(1)).findAndAggregateAsync(SYS_TENANT_ID, TEMP, i, Math.min(i + 3, 3000), getTsForReadTsKvQuery(i, i + 3), COUNT); } } From d8135f0782b811fb391dee392b8af976a1b0211d Mon Sep 17 00:00:00 2001 From: ShvaykaD Date: Fri, 16 Sep 2022 16:11:25 +0300 Subject: [PATCH 105/108] refactor getInterval logic --- .../engine/metadata/TbGetTelemetryNode.java | 86 ++++++------------- 1 file changed, 28 insertions(+), 58 deletions(-) diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTelemetryNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTelemetryNode.java index f95909e813..478e49f004 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTelemetryNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTelemetryNode.java @@ -1,12 +1,12 @@ /** * Copyright © 2016-2022 The Thingsboard Authors - * + *

* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -110,11 +110,9 @@ public class TbGetTelemetryNode implements TbNode { ctx.tellFailure(msg, new IllegalStateException("Telemetry is not selected!")); } else { try { - if (config.isUseMetadataIntervalPatterns()) { - checkKeyPatterns(msg); - } + Interval interval = getInterval(msg); List keys = TbNodeUtils.processPatterns(tsKeyNames, msg); - ListenableFuture> list = ctx.getTimeseriesService().findAll(ctx.getTenantId(), msg.getOriginator(), buildQueries(msg, keys)); + ListenableFuture> list = ctx.getTimeseriesService().findAll(ctx.getTenantId(), msg.getOriginator(), buildQueries(interval, keys)); DonAsynchron.withCallback(list, data -> { process(data, msg, keys); ctx.tellSuccess(ctx.transformMsg(msg, msg.getType(), msg.getOriginator(), msg.getMetaData(), msg.getData())); @@ -129,8 +127,7 @@ public class TbGetTelemetryNode implements TbNode { public void destroy() { } - private List buildQueries(TbMsg msg, List keys) { - final Interval interval = getInterval(msg); + private List buildQueries(Interval interval, List keys) { final long aggIntervalStep = Aggregation.NONE.equals(aggregation) ? 1 : // exact how it validates on BaseTimeseriesService.validate() // see CassandraBaseTimeseriesDao.findAllAsync() @@ -210,72 +207,45 @@ public class TbGetTelemetryNode implements TbNode { } private Interval getInterval(TbMsg msg) { - Interval interval = new Interval(); if (config.isUseMetadataIntervalPatterns()) { - if (isParsable(msg, config.getStartIntervalPattern())) { - interval.setStartTs(Long.parseLong(TbNodeUtils.processPattern(config.getStartIntervalPattern(), msg))); - } - if (isParsable(msg, config.getEndIntervalPattern())) { - interval.setEndTs(Long.parseLong(TbNodeUtils.processPattern(config.getEndIntervalPattern(), msg))); - } + return getIntervalFromPatterns(msg); } else { + Interval interval = new Interval(); long ts = System.currentTimeMillis(); interval.setStartTs(ts - TimeUnit.valueOf(config.getStartIntervalTimeUnit()).toMillis(config.getStartInterval())); interval.setEndTs(ts - TimeUnit.valueOf(config.getEndIntervalTimeUnit()).toMillis(config.getEndInterval())); + return interval; } - return interval; } - private boolean isParsable(TbMsg msg, String pattern) { - return NumberUtils.isParsable(TbNodeUtils.processPattern(pattern, msg)); - } - - private void checkKeyPatterns(TbMsg msg) { - isUndefined(msg, config.getStartIntervalPattern(), config.getEndIntervalPattern()); - isInvalid(msg, config.getStartIntervalPattern(), config.getEndIntervalPattern()); + private Interval getIntervalFromPatterns(TbMsg msg) { + Interval interval = new Interval(); + interval.setStartTs(checkPattern(msg, config.getStartIntervalPattern())); + interval.setEndTs(checkPattern(msg, config.getEndIntervalPattern())); + return interval; } - private void isUndefined(TbMsg msg, String startIntervalPattern, String endIntervalPattern) { - if (getValuePattern(msg, startIntervalPattern) == null && getValuePattern(msg, endIntervalPattern) == null) { - throw new IllegalArgumentException("Message values: '" + - replaceRegex(startIntervalPattern) + "' and '" + - replaceRegex(endIntervalPattern) + "' are undefined"); - } else { - if (getValuePattern(msg, startIntervalPattern) == null) { - throw new IllegalArgumentException("Message value: '" + - replaceRegex(startIntervalPattern) + "' is undefined"); - } - if (getValuePattern(msg, endIntervalPattern) == null) { - throw new IllegalArgumentException("Message value: '" + - replaceRegex(endIntervalPattern) + "' is undefined"); - } + private long checkPattern(TbMsg msg, String pattern) { + String value = getValuePattern(msg, pattern); + if (value == null) { + throw new IllegalArgumentException("Message value: '" + + replaceRegex(pattern) + "' is undefined"); } - } - - private void isInvalid(TbMsg msg, String startIntervalPattern, String endIntervalPattern) { - if (getInterval(msg).getStartTs() == null && getInterval(msg).getEndTs() == null) { - throw new IllegalArgumentException("Message values: '" + - replaceRegex(startIntervalPattern) + "' and '" + - replaceRegex(endIntervalPattern) + "' have invalid format"); - } else { - if (getInterval(msg).getStartTs() == null) { - throw new IllegalArgumentException("Message value: '" + - replaceRegex(startIntervalPattern) + "' has invalid format"); - } - if (getInterval(msg).getEndTs() == null) { - throw new IllegalArgumentException("Message value: '" + - replaceRegex(endIntervalPattern) + "' has invalid format"); - } + boolean parsable = NumberUtils.isParsable(value); + if (!parsable) { + throw new IllegalArgumentException("Message value: '" + + replaceRegex(pattern) + "' has invalid format"); } + return Long.parseLong(value); } private String getValuePattern(TbMsg msg, String pattern) { - String valuePattern = TbNodeUtils.processPattern(pattern, msg); - return valuePattern.equals(pattern) ? null : valuePattern; + String value = TbNodeUtils.processPattern(pattern, msg); + return value.equals(pattern) ? null : value; } private String replaceRegex(String pattern) { - return pattern.replaceAll("[${}]", ""); + return pattern.replaceAll("[$\\[{}\\]]", ""); } private int validateLimit(int limit) { From 225f572b7aec3a40634b12fdb911280812505eda Mon Sep 17 00:00:00 2001 From: ShvaykaD Date: Fri, 16 Sep 2022 16:15:08 +0300 Subject: [PATCH 106/108] license:format --- .../rule/engine/metadata/TbGetTelemetryNode.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTelemetryNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTelemetryNode.java index 478e49f004..e3f4613d33 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTelemetryNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTelemetryNode.java @@ -1,12 +1,12 @@ /** * Copyright © 2016-2022 The Thingsboard Authors - *

+ * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

+ * + * http://www.apache.org/licenses/LICENSE-2.0 + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. From 14898ef7b3204015883d44e6024d229410239052 Mon Sep 17 00:00:00 2001 From: Yuriy Lytvynchuk Date: Wed, 21 Sep 2022 12:53:30 +0300 Subject: [PATCH 107/108] update test --- .../engine/metadata/TbGetTelemetryNodeTest.java | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetTelemetryNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetTelemetryNodeTest.java index bb086af15a..9c97f6f85b 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetTelemetryNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetTelemetryNodeTest.java @@ -15,8 +15,12 @@ */ package org.thingsboard.rule.engine.metadata; +import com.fasterxml.jackson.databind.ObjectMapper; import org.junit.Before; import org.junit.Test; +import org.thingsboard.common.util.JacksonUtil; +import org.thingsboard.rule.engine.api.TbContext; +import org.thingsboard.rule.engine.api.TbNodeConfiguration; import org.thingsboard.server.common.data.kv.Aggregation; import static org.hamcrest.CoreMatchers.is; @@ -24,14 +28,25 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.BDDMockito.willCallRealMethod; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; public class TbGetTelemetryNodeTest { TbGetTelemetryNode node; + TbGetTelemetryNodeConfiguration config; + TbNodeConfiguration nodeConfiguration; + TbContext ctx; @Before public void setUp() throws Exception { - node = mock(TbGetTelemetryNode.class); + ctx = mock(TbContext.class); + node = spy(new TbGetTelemetryNode()); + config = new TbGetTelemetryNodeConfiguration(); + config.setFetchMode("ALL"); + ObjectMapper mapper = JacksonUtil.OBJECT_MAPPER; + nodeConfiguration = new TbNodeConfiguration(mapper.valueToTree(config)); + node.init(ctx, nodeConfiguration); + willCallRealMethod().given(node).parseAggregationConfig(any()); } From baf17c6488090a9aea8527be1c03fafc7e90968d Mon Sep 17 00:00:00 2001 From: Yuriy Lytvynchuk Date: Wed, 21 Sep 2022 16:57:22 +0300 Subject: [PATCH 108/108] code review --- .../thingsboard/server/common/data/EntityFieldsData.java | 7 +++++++ .../metadata/TbGetOriginatorFieldsConfiguration.java | 4 ++-- .../rule/engine/metadata/TbGetOriginatorFieldsNode.java | 8 ++++---- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/EntityFieldsData.java b/common/data/src/main/java/org/thingsboard/server/common/data/EntityFieldsData.java index c3cd2b12b4..04c526b6fe 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/EntityFieldsData.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/EntityFieldsData.java @@ -50,6 +50,10 @@ public class EntityFieldsData { } public String getFieldValue(String field) { + return getFieldValue(field, false); + } + + public String getFieldValue(String field, boolean ignoreNullStrings) { String[] fieldsTree = field.split("\\."); JsonNode current = fieldsData; for (String key : fieldsTree) { @@ -61,6 +65,9 @@ public class EntityFieldsData { } } if (current != null) { + if(current.isNull() && ignoreNullStrings){ + return null; + } if (current.isValueNode()) { return current.asText(); } else { diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetOriginatorFieldsConfiguration.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetOriginatorFieldsConfiguration.java index 0648b81588..b0e9bf39e5 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetOriginatorFieldsConfiguration.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetOriginatorFieldsConfiguration.java @@ -25,7 +25,7 @@ import java.util.Map; public class TbGetOriginatorFieldsConfiguration implements NodeConfiguration { private Map fieldsMapping; - private boolean ignoreStringNull; + private boolean ignoreNullStrings; @Override public TbGetOriginatorFieldsConfiguration defaultConfiguration() { @@ -34,7 +34,7 @@ public class TbGetOriginatorFieldsConfiguration implements NodeConfiguration { config.getFieldsMapping().forEach((field, metaKey) -> { - String val = data.getFieldValue(field); - if (val != null && (!val.equals("null") || !ignoreStringNull)) { + String val = data.getFieldValue(field, ignoreNullStrings); + if (val != null) { msg.getMetaData().putValue(metaKey, val); } });