From 143d5a95b33e090d932747db72edf024285e2ebc Mon Sep 17 00:00:00 2001 From: Vladyslav_Prykhodko Date: Thu, 5 Dec 2024 11:23:51 +0200 Subject: [PATCH 01/28] UI: Fixed double open dialog when edit mobile bundle --- .../mobile-bundle-table-config.resolve.ts | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/ui-ngx/src/app/modules/home/pages/mobile/bundes/mobile-bundle-table-config.resolve.ts b/ui-ngx/src/app/modules/home/pages/mobile/bundes/mobile-bundle-table-config.resolve.ts index 24a503147e..177f41ba1b 100644 --- a/ui-ngx/src/app/modules/home/pages/mobile/bundes/mobile-bundle-table-config.resolve.ts +++ b/ui-ngx/src/app/modules/home/pages/mobile/bundes/mobile-bundle-table-config.resolve.ts @@ -24,13 +24,13 @@ import { EntityTableConfig } from '@home/models/entity/entities-table-config.models'; import { MobileAppBundleInfo } from '@shared/models/mobile-app.models'; -import { ActivatedRouteSnapshot } from '@angular/router'; +import { ActivatedRouteSnapshot, Router } from '@angular/router'; import { EntityType, entityTypeResources, entityTypeTranslations } from '@shared/models/entity-type.models'; import { Direction } from '@shared/models/page/sort-order'; import { MobileBundleTableHeaderComponent } from '@home/pages/mobile/bundes/mobile-bundle-table-header.component'; import { DatePipe } from '@angular/common'; import { MobileAppService } from '@core/http/mobile-app.service'; -import { map, take } from 'rxjs/operators'; +import { finalize, map, skip, take, takeUntil } from 'rxjs/operators'; import { TranslateService } from '@ngx-translate/core'; import { EntityAction } from '@home/models/entity/entity-component.models'; import { MatDialog } from '@angular/material/dialog'; @@ -52,11 +52,14 @@ export class MobileBundleTableConfigResolver { private readonly config: EntityTableConfig = new EntityTableConfig(); + private openingEditDialog = false; + constructor( private datePipe: DatePipe, private mobileAppService: MobileAppService, private translate : TranslateService, private dialog: MatDialog, + private router: Router, private store: Store ) { this.config.selectionEnabled = false; @@ -108,9 +111,15 @@ export class MobileBundleTableConfigResolver { this.config.handleRowClick = ($event, bundle) => { $event?.stopPropagation(); - this.mobileAppService.getMobileAppBundleInfoById(bundle.id.id).subscribe(appBundleInfo => { - this.editBundle($event, appBundleInfo); - }) + if (!this.openingEditDialog) { + this.openingEditDialog = true; + this.mobileAppService.getMobileAppBundleInfoById(bundle.id.id).pipe( + takeUntil(this.router.events.pipe(skip(1))), + finalize(() => {this.openingEditDialog = false;}) + ).subscribe( + appBundleInfo => this.editBundle($event, appBundleInfo) + ); + } return true; }; From 9a5d37c3c229bdeb843c6dc3b39f3a61734fd3d2 Mon Sep 17 00:00:00 2001 From: Artem Dzhereleiko Date: Thu, 5 Dec 2024 12:02:40 +0200 Subject: [PATCH 02/28] UI: Fixed for value less than min and more than max --- .../system/scada_symbols/dynamic-horizontal-scale-hp.svg | 8 ++++---- .../system/scada_symbols/dynamic-vertical-scale-hp.svg | 8 ++++---- .../system/scada_symbols/simple-horizontal-scale-hp.svg | 8 ++++---- .../system/scada_symbols/simple-vertical-scale-hp.svg | 8 ++++---- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/application/src/main/data/json/system/scada_symbols/dynamic-horizontal-scale-hp.svg b/application/src/main/data/json/system/scada_symbols/dynamic-horizontal-scale-hp.svg index 5576c939c4..bfd711cd38 100644 --- a/application/src/main/data/json/system/scada_symbols/dynamic-horizontal-scale-hp.svg +++ b/application/src/main/data/json/system/scada_symbols/dynamic-horizontal-scale-hp.svg @@ -18,12 +18,12 @@ }, { "tag": "highCriticalScale", - "stateRenderFunction": "function calculateOffset(value, minValue, maxValue) {\n var clampedValue = Math.max(minValue, Math.min(value, maxValue));\n var normalizedValue = (clampedValue - minValue) / (maxValue - minValue);\n var offset = normalizedValue * 653;\n return offset;\n}\n\nvar value = ctx.values.value;\nvar minValue = ctx.properties.minValue;\nvar maxValue = ctx.properties.maxValue;\nvar showHighCriticalScale = ctx.properties.showHighCriticalScale;\nvar highCriticalState = ctx.values.highCriticalState;\nif (showHighCriticalScale && highCriticalState !== null) {\n element.show();\n var offset = calculateOffset(highCriticalState, minValue, maxValue);\n element.width(653-offset);\n} else {\n element.hide();\n}\n\nif (showHighCriticalScale && value !== null && highCriticalState !== null) {\n if (value >= highCriticalState && value <= ctx.properties.maxValue) {\n element.fill(ctx.properties.activeCriticalScaleColor);\n } else {\n element.fill(ctx.properties.defaultCriticalScaleColor)\n }\n}", + "stateRenderFunction": "function calculateOffset(value, minValue, maxValue) {\n var clampedValue = Math.max(minValue, Math.min(value, maxValue));\n var normalizedValue = (clampedValue - minValue) / (maxValue - minValue);\n var offset = normalizedValue * 653;\n return offset;\n}\n\nvar value = ctx.values.value;\nvar minValue = ctx.properties.minValue;\nvar maxValue = ctx.properties.maxValue;\nvar showHighCriticalScale = ctx.properties.showHighCriticalScale;\nvar highCriticalState = ctx.values.highCriticalState;\nif (showHighCriticalScale && highCriticalState !== null) {\n element.show();\n var offset = calculateOffset(highCriticalState, minValue, maxValue);\n element.width(653-offset);\n} else {\n element.hide();\n}\n\nif (showHighCriticalScale && value !== null && highCriticalState !== null) {\n if (value >= highCriticalState) {\n element.fill(ctx.properties.activeCriticalScaleColor);\n } else {\n element.fill(ctx.properties.defaultCriticalScaleColor)\n }\n}", "actions": null }, { "tag": "highWarningScale", - "stateRenderFunction": "function calculateOffset(value, minValue, maxValue) {\n var clampedValue = Math.max(minValue, Math.min(value, maxValue));\n var normalizedValue = (clampedValue - minValue) / (maxValue - minValue);\n var offset = normalizedValue * 653;\n\n return offset;\n}\n\nvar value = ctx.values.value;\nvar minValue = ctx.properties.minValue;\nvar maxValue = ctx.properties.maxValue;\nvar showHighCriticalScale = ctx.properties.showHighCriticalScale;\nvar showHighWarningScale = ctx.properties.showHighWarningScale;\nvar highWarningState = ctx.values.highWarningState;\nvar highCriticalState = ctx.values.highCriticalState;\nif (showHighWarningScale && highWarningState !== null) {\n element.show();\n var offset = calculateOffset(highWarningState, minValue, maxValue);\n element.width(653-offset);\n} else {\n element.hide();\n}\n\nif (showHighWarningScale && value !== null) {\n if (!showHighCriticalScale) {\n highCriticalState = ctx.properties.maxValue;\n }\n \n if (highWarningState !== null && highCriticalState !== null) {\n if (value < highCriticalState && value >= highWarningState) {\n element.fill(ctx.properties.activeWarningScaleColor);\n } else {\n element.fill(ctx.properties.defaultWarningScaleColor);\n }\n }\n}", + "stateRenderFunction": "function calculateOffset(value, minValue, maxValue) {\n var clampedValue = Math.max(minValue, Math.min(value, maxValue));\n var normalizedValue = (clampedValue - minValue) / (maxValue - minValue);\n var offset = normalizedValue * 653;\n\n return offset;\n}\n\nvar value = ctx.values.value;\nvar minValue = ctx.properties.minValue;\nvar maxValue = ctx.properties.maxValue;\nvar showHighCriticalScale = ctx.properties.showHighCriticalScale;\nvar showHighWarningScale = ctx.properties.showHighWarningScale;\nvar highWarningState = ctx.values.highWarningState;\nvar highCriticalState = ctx.values.highCriticalState;\nif (showHighWarningScale && highWarningState !== null) {\n element.show();\n var offset = calculateOffset(highWarningState, minValue, maxValue);\n element.width(653-offset);\n} else {\n element.hide();\n}\n\nif (showHighWarningScale && value !== null) {\n if (!showHighCriticalScale) {\n highCriticalState = Number.MAX_SAFE_INTEGER;\n }\n \n if (highWarningState !== null && highCriticalState !== null) {\n if (value < highCriticalState && value >= highWarningState) {\n element.fill(ctx.properties.activeWarningScaleColor);\n } else {\n element.fill(ctx.properties.defaultWarningScaleColor);\n }\n }\n}", "actions": null }, { @@ -33,12 +33,12 @@ }, { "tag": "lowCriticalScale", - "stateRenderFunction": "function calculateOffset(value, minValue, maxValue) {\n var clampedValue = Math.max(minValue, Math.min(value, maxValue));\n var normalizedValue = (clampedValue - minValue) / (maxValue - minValue);\n var offset = normalizedValue * 653;\n\n return offset;\n}\n\nvar value = ctx.values.value;\nvar minValue = ctx.properties.minValue;\nvar maxValue = ctx.properties.maxValue;\nvar showLowCriticalScale = ctx.properties.showLowCriticalScale;\nvar lowCriticalValue = ctx.values.lowCriticalState;\n\nif (showLowCriticalScale && lowCriticalValue !== null) {\n element.show();\n var offset = calculateOffset(lowCriticalValue, minValue, maxValue);\n element.width(offset);\n} else {\n element.hide();\n}\n\nif (showLowCriticalScale && value !== null) {\n var lowCriticalScale = ctx.values.lowCriticalState;\n if (value <= lowCriticalScale && value >= ctx.properties.minValue) {\n element.fill(ctx.properties.activeCriticalScaleColor);\n } else {\n element.fill(ctx.properties.defaultCriticalScaleColor)\n }\n}", + "stateRenderFunction": "function calculateOffset(value, minValue, maxValue) {\n var clampedValue = Math.max(minValue, Math.min(value, maxValue));\n var normalizedValue = (clampedValue - minValue) / (maxValue - minValue);\n var offset = normalizedValue * 653;\n\n return offset;\n}\n\nvar value = ctx.values.value;\nvar minValue = ctx.properties.minValue;\nvar maxValue = ctx.properties.maxValue;\nvar showLowCriticalScale = ctx.properties.showLowCriticalScale;\nvar lowCriticalValue = ctx.values.lowCriticalState;\n\nif (showLowCriticalScale && lowCriticalValue !== null) {\n element.show();\n var offset = calculateOffset(lowCriticalValue, minValue, maxValue);\n element.width(offset);\n} else {\n element.hide();\n}\n\nif (showLowCriticalScale && value !== null) {\n var lowCriticalScale = ctx.values.lowCriticalState;\n if (value <= lowCriticalScale) {\n element.fill(ctx.properties.activeCriticalScaleColor);\n } else {\n element.fill(ctx.properties.defaultCriticalScaleColor)\n }\n}", "actions": null }, { "tag": "lowWarningScale", - "stateRenderFunction": "function calculateOffset(value, minValue, maxValue) {\n var clampedValue = Math.max(minValue, Math.min(value, maxValue));\n var normalizedValue = (clampedValue - minValue) / (maxValue - minValue);\n var offset = normalizedValue * 653;\n return offset;\n}\n\nvar value = ctx.values.value;\nvar minValue = ctx.properties.minValue;\nvar maxValue = ctx.properties.maxValue;\nvar showLowWarningScale = ctx.properties.showLowWarningScale;\nvar showLowCriticalScale = ctx.properties.showLowCriticalScale;\nvar lowWarningState = ctx.values.lowWarningState;\nvar lowCriticalState = ctx.values.lowCriticalState;\nif (showLowWarningScale && lowWarningState !== null) {\n element.show();\n var offset = calculateOffset(lowWarningState, minValue, maxValue);\n element.width(offset);\n} else {\n element.hide();\n}\n\nif (showLowWarningScale && value !== null) {\n if (!showLowCriticalScale) {\n lowCriticalState = ctx.properties.minValue;\n }\n if (lowCriticalState !== null && lowWarningState !== null) {\n if (value > lowCriticalState && value <= lowWarningState) {\n element.fill(ctx.properties.activeWarningScaleColor);\n } else {\n element.fill(ctx.properties.defaultWarningScaleColor);\n }\n }\n}", + "stateRenderFunction": "function calculateOffset(value, minValue, maxValue) {\n var clampedValue = Math.max(minValue, Math.min(value, maxValue));\n var normalizedValue = (clampedValue - minValue) / (maxValue - minValue);\n var offset = normalizedValue * 653;\n return offset;\n}\n\nvar value = ctx.values.value;\nvar minValue = ctx.properties.minValue;\nvar maxValue = ctx.properties.maxValue;\nvar showLowWarningScale = ctx.properties.showLowWarningScale;\nvar showLowCriticalScale = ctx.properties.showLowCriticalScale;\nvar lowWarningState = ctx.values.lowWarningState;\nvar lowCriticalState = ctx.values.lowCriticalState;\nif (showLowWarningScale && lowWarningState !== null) {\n element.show();\n var offset = calculateOffset(lowWarningState, minValue, maxValue);\n element.width(offset);\n} else {\n element.hide();\n}\n\nif (showLowWarningScale && value !== null) {\n if (!showLowCriticalScale) {\n lowCriticalState = Number.MIN_SAFE_INTEGER;\n }\n if (lowCriticalState !== null && lowWarningState !== null) {\n if (value > lowCriticalState && value <= lowWarningState) {\n element.fill(ctx.properties.activeWarningScaleColor);\n } else {\n element.fill(ctx.properties.defaultWarningScaleColor);\n }\n }\n}", "actions": null }, { diff --git a/application/src/main/data/json/system/scada_symbols/dynamic-vertical-scale-hp.svg b/application/src/main/data/json/system/scada_symbols/dynamic-vertical-scale-hp.svg index b7d5e0184b..5dd6dd43a3 100644 --- a/application/src/main/data/json/system/scada_symbols/dynamic-vertical-scale-hp.svg +++ b/application/src/main/data/json/system/scada_symbols/dynamic-vertical-scale-hp.svg @@ -18,12 +18,12 @@ }, { "tag": "highCriticalScale", - "stateRenderFunction": "function calculateOffset(value, minValue, maxValue) {\n var clampedValue = Math.max(minValue, Math.min(value, maxValue));\n var normalizedValue = (clampedValue - minValue) / (maxValue - minValue);\n var offset = normalizedValue * 653;\n\n return offset;\n}\n\nvar value = ctx.values.value;\nvar minValue = ctx.properties.minValue;\nvar maxValue = ctx.properties.maxValue;\nvar showHighCriticalScale = ctx.properties.showHighCriticalScale;\nvar highCriticalState = ctx.values.highCriticalState;\nif (showHighCriticalScale && highCriticalState !== null) {\n element.show();\n var offset = calculateOffset(highCriticalState, minValue, maxValue);\n element.height(653-offset);\n} else {\n element.hide();\n}\n\nif (showHighCriticalScale && value !== null && highCriticalState !== null) {\n if (value >= highCriticalState && value <= ctx.properties.maxValue) {\n element.fill(ctx.properties.activeCriticalScaleColor);\n } else {\n element.fill(ctx.properties.defaultCriticalScaleColor)\n }\n}", + "stateRenderFunction": "function calculateOffset(value, minValue, maxValue) {\n var clampedValue = Math.max(minValue, Math.min(value, maxValue));\n var normalizedValue = (clampedValue - minValue) / (maxValue - minValue);\n var offset = normalizedValue * 653;\n\n return offset;\n}\n\nvar value = ctx.values.value;\nvar minValue = ctx.properties.minValue;\nvar maxValue = ctx.properties.maxValue;\nvar showHighCriticalScale = ctx.properties.showHighCriticalScale;\nvar highCriticalState = ctx.values.highCriticalState;\nif (showHighCriticalScale && highCriticalState !== null) {\n element.show();\n var offset = calculateOffset(highCriticalState, minValue, maxValue);\n element.height(653-offset);\n} else {\n element.hide();\n}\n\nif (showHighCriticalScale && value !== null && highCriticalState !== null) {\n if (value >= highCriticalState) {\n element.fill(ctx.properties.activeCriticalScaleColor);\n } else {\n element.fill(ctx.properties.defaultCriticalScaleColor)\n }\n}", "actions": null }, { "tag": "highWarningScale", - "stateRenderFunction": "function calculateOffset(value, minValue, maxValue) {\n var clampedValue = Math.max(minValue, Math.min(value, maxValue));\n var normalizedValue = (clampedValue - minValue) / (maxValue - minValue);\n var offset = normalizedValue * 653;\n return offset;\n}\n\nvar value = ctx.values.value;\nvar minValue = ctx.properties.minValue;\nvar maxValue = ctx.properties.maxValue;\nvar showHighCriticalScale = ctx.properties.showHighCriticalScale;\nvar showHighWarningScale = ctx.properties.showHighWarningScale;\nvar highWarningState = ctx.values.highWarningState;\nvar highCriticalState = ctx.values.highCriticalState;\nif (showHighWarningScale && highWarningState !== null) {\n element.show();\n var offset = calculateOffset(highWarningState, minValue, maxValue);\n element.height(653-offset);\n} else {\n element.hide();\n}\nif (showHighWarningScale && value !== null) {\n if (!showHighCriticalScale) {\n highCriticalState = ctx.properties.maxValue;\n }\n if (highWarningState !== null && highCriticalState !== null) {\n if (value < highCriticalState && value >= highWarningState) {\n element.fill(ctx.properties.activeWarningScaleColor);\n } else {\n element.fill(ctx.properties.defaultWarningScaleColor);\n }\n }\n}", + "stateRenderFunction": "function calculateOffset(value, minValue, maxValue) {\n var clampedValue = Math.max(minValue, Math.min(value, maxValue));\n var normalizedValue = (clampedValue - minValue) / (maxValue - minValue);\n var offset = normalizedValue * 653;\n return offset;\n}\n\nvar value = ctx.values.value;\nvar minValue = ctx.properties.minValue;\nvar maxValue = ctx.properties.maxValue;\nvar showHighCriticalScale = ctx.properties.showHighCriticalScale;\nvar showHighWarningScale = ctx.properties.showHighWarningScale;\nvar highWarningState = ctx.values.highWarningState;\nvar highCriticalState = ctx.values.highCriticalState;\nif (showHighWarningScale && highWarningState !== null) {\n element.show();\n var offset = calculateOffset(highWarningState, minValue, maxValue);\n element.height(653-offset);\n} else {\n element.hide();\n}\nif (showHighWarningScale && value !== null) {\n if (!showHighCriticalScale) {\n highCriticalState = Number.MAX_SAFE_INTEGER;\n }\n if (highWarningState !== null && highCriticalState !== null) {\n if (value < highCriticalState && value >= highWarningState) {\n element.fill(ctx.properties.activeWarningScaleColor);\n } else {\n element.fill(ctx.properties.defaultWarningScaleColor);\n }\n }\n}", "actions": null }, { @@ -33,12 +33,12 @@ }, { "tag": "lowCriticalScale", - "stateRenderFunction": "function calculateOffset(value, minValue, maxValue) {\n var clampedValue = Math.max(minValue, Math.min(value, maxValue));\n var normalizedValue = (clampedValue - minValue) / (maxValue - minValue);\n var offset = normalizedValue * 653;\n\n return offset;\n}\n\nvar value = ctx.values.value;\nvar minValue = ctx.properties.minValue;\nvar maxValue = ctx.properties.maxValue;\nvar showLowCriticalScale = ctx.properties.showLowCriticalScale;\nvar lowCriticalValue = ctx.values.lowCriticalState;\n\nif (showLowCriticalScale && lowCriticalValue !== null) {\n element.show();\n var offset = calculateOffset(lowCriticalValue, minValue, maxValue);\n element.height(offset);\n} else {\n element.hide();\n}\nif (showLowCriticalScale && value !== null) {\n var lowCriticalScale = ctx.values.lowCriticalState;\n if (value <= lowCriticalScale && value >= ctx.properties.minValue) {\n element.fill(ctx.properties.activeCriticalScaleColor);\n } else {\n element.fill(ctx.properties.defaultCriticalScaleColor)\n }\n}", + "stateRenderFunction": "function calculateOffset(value, minValue, maxValue) {\n var clampedValue = Math.max(minValue, Math.min(value, maxValue));\n var normalizedValue = (clampedValue - minValue) / (maxValue - minValue);\n var offset = normalizedValue * 653;\n\n return offset;\n}\n\nvar value = ctx.values.value;\nvar minValue = ctx.properties.minValue;\nvar maxValue = ctx.properties.maxValue;\nvar showLowCriticalScale = ctx.properties.showLowCriticalScale;\nvar lowCriticalValue = ctx.values.lowCriticalState;\n\nif (showLowCriticalScale && lowCriticalValue !== null) {\n element.show();\n var offset = calculateOffset(lowCriticalValue, minValue, maxValue);\n element.height(offset);\n} else {\n element.hide();\n}\nif (showLowCriticalScale && value !== null) {\n var lowCriticalScale = ctx.values.lowCriticalState;\n if (value <= lowCriticalScale) {\n element.fill(ctx.properties.activeCriticalScaleColor);\n } else {\n element.fill(ctx.properties.defaultCriticalScaleColor)\n }\n}", "actions": null }, { "tag": "lowWarningScale", - "stateRenderFunction": "function calculateOffset(value, minValue, maxValue) {\n var clampedValue = Math.max(minValue, Math.min(value, maxValue));\n var normalizedValue = (clampedValue - minValue) / (maxValue - minValue);\n var offset = normalizedValue * 653;\n\n return offset;\n}\n\nvar value = ctx.values.value;\nvar minValue = ctx.properties.minValue;\nvar maxValue = ctx.properties.maxValue;\nvar showLowWarningScale = ctx.properties.showLowWarningScale;\nvar showLowCriticalScale = ctx.properties.showLowCriticalScale;\nvar lowWarningState = ctx.values.lowWarningState;\nvar lowCriticalState = ctx.values.lowCriticalState;\nif (showLowWarningScale && lowWarningState !== null) {\n element.show();\n var offset = calculateOffset(lowWarningState, minValue, maxValue);\n element.height(offset);\n} else {\n element.hide();\n}\nif (showLowWarningScale && value !== null) {\n if (!showLowCriticalScale) {\n lowCriticalState = ctx.properties.minValue;\n }\n if (lowCriticalState !== null && lowWarningState !== null) {\n if (value > lowCriticalState && value <= lowWarningState) {\n element.fill(ctx.properties.activeWarningScaleColor);\n } else {\n element.fill(ctx.properties.defaultWarningScaleColor);\n }\n }\n}", + "stateRenderFunction": "function calculateOffset(value, minValue, maxValue) {\n var clampedValue = Math.max(minValue, Math.min(value, maxValue));\n var normalizedValue = (clampedValue - minValue) / (maxValue - minValue);\n var offset = normalizedValue * 653;\n\n return offset;\n}\n\nvar value = ctx.values.value;\nvar minValue = ctx.properties.minValue;\nvar maxValue = ctx.properties.maxValue;\nvar showLowWarningScale = ctx.properties.showLowWarningScale;\nvar showLowCriticalScale = ctx.properties.showLowCriticalScale;\nvar lowWarningState = ctx.values.lowWarningState;\nvar lowCriticalState = ctx.values.lowCriticalState;\nif (showLowWarningScale && lowWarningState !== null) {\n element.show();\n var offset = calculateOffset(lowWarningState, minValue, maxValue);\n element.height(offset);\n} else {\n element.hide();\n}\nif (showLowWarningScale && value !== null) {\n if (!showLowCriticalScale) {\n lowCriticalState = Number.MIN_SAFE_INTEGER;\n }\n if (lowCriticalState !== null && lowWarningState !== null) {\n if (value > lowCriticalState && value <= lowWarningState) {\n element.fill(ctx.properties.activeWarningScaleColor);\n } else {\n element.fill(ctx.properties.defaultWarningScaleColor);\n }\n }\n}", "actions": null }, { diff --git a/application/src/main/data/json/system/scada_symbols/simple-horizontal-scale-hp.svg b/application/src/main/data/json/system/scada_symbols/simple-horizontal-scale-hp.svg index e69daae548..7b43164cce 100644 --- a/application/src/main/data/json/system/scada_symbols/simple-horizontal-scale-hp.svg +++ b/application/src/main/data/json/system/scada_symbols/simple-horizontal-scale-hp.svg @@ -18,12 +18,12 @@ }, { "tag": "highCriticalScale", - "stateRenderFunction": "function calculateOffset(value, minValue, maxValue) {\n var clampedValue = Math.max(minValue, Math.min(value, maxValue));\n var normalizedValue = (clampedValue - minValue) / (maxValue - minValue);\n var offset = normalizedValue * 653;\n return offset;\n}\n\nvar minValue = ctx.properties.minValue;\nvar maxValue = ctx.properties.maxValue;\nvar showHighCriticalScale = ctx.properties.showHighCriticalScale;\nvar highCriticalValue = ctx.properties.highCriticalScale;\nvar value = ctx.values.value;\n\nif (showHighCriticalScale) {\n element.show();\n var offset = calculateOffset(highCriticalValue, minValue, maxValue);\n element.width(653-offset);\n} else {\n element.hide();\n}\n\nif (showHighCriticalScale && value !== null) {\n var highCriticalScale = ctx.properties.highCriticalScale;\n if (value >= highCriticalScale && value <= ctx.properties.maxValue) {\n element.fill(ctx.properties.activeCriticalScaleColor);\n } else {\n element.fill(ctx.properties.defaultCriticalScaleColor)\n }\n}", + "stateRenderFunction": "function calculateOffset(value, minValue, maxValue) {\n var clampedValue = Math.max(minValue, Math.min(value, maxValue));\n var normalizedValue = (clampedValue - minValue) / (maxValue - minValue);\n var offset = normalizedValue * 653;\n return offset;\n}\n\nvar minValue = ctx.properties.minValue;\nvar maxValue = ctx.properties.maxValue;\nvar showHighCriticalScale = ctx.properties.showHighCriticalScale;\nvar highCriticalValue = ctx.properties.highCriticalScale;\nvar value = ctx.values.value;\n\nif (showHighCriticalScale) {\n element.show();\n var offset = calculateOffset(highCriticalValue, minValue, maxValue);\n element.width(653-offset);\n} else {\n element.hide();\n}\nif (showHighCriticalScale && value !== null) {\n var highCriticalScale = ctx.properties.highCriticalScale;\n if (value >= highCriticalScale) {\n element.fill(ctx.properties.activeCriticalScaleColor);\n } else {\n element.fill(ctx.properties.defaultCriticalScaleColor)\n }\n}", "actions": null }, { "tag": "highWarningScale", - "stateRenderFunction": "function calculateOffset(value, minValue, maxValue) {\n var clampedValue = Math.max(minValue, Math.min(value, maxValue));\n var normalizedValue = (clampedValue - minValue) / (maxValue - minValue);\n var offset = normalizedValue * 653;\n return offset;\n}\n\nvar minValue = ctx.properties.minValue;\nvar maxValue = ctx.properties.maxValue;\nvar showHighWarningScale = ctx.properties.showHighWarningScale;\nvar showHighCriticalScale = ctx.properties.showHighCriticalScale;\nvar highWarningValue = ctx.properties.highWarningScale;\nvar value = ctx.values.value;\n\nif (showHighWarningScale) {\n element.show();\n var offset = calculateOffset(highWarningValue, minValue, maxValue);\n element.width(653-offset);\n} else {\n element.hide();\n}\n\nif (showHighWarningScale && value !== null) {\n var highCriticalScale = ctx.properties.highCriticalScale;\n if (!showHighCriticalScale) {\n highCriticalScale = ctx.properties.maxValue;\n }\n var highWarningScale = ctx.properties.highWarningScale;\n if (value < highCriticalScale && value >= highWarningScale) {\n element.fill(ctx.properties.activeWarningScaleColor);\n } else {\n element.fill(ctx.properties.defaultWarningScaleColor);\n }\n}", + "stateRenderFunction": "function calculateOffset(value, minValue, maxValue) {\n var clampedValue = Math.max(minValue, Math.min(value, maxValue));\n var normalizedValue = (clampedValue - minValue) / (maxValue - minValue);\n var offset = normalizedValue * 653;\n return offset;\n}\n\nvar minValue = ctx.properties.minValue;\nvar maxValue = ctx.properties.maxValue;\nvar showHighWarningScale = ctx.properties.showHighWarningScale;\nvar showHighCriticalScale = ctx.properties.showHighCriticalScale;\nvar highWarningValue = ctx.properties.highWarningScale;\nvar value = ctx.values.value;\n\nif (showHighWarningScale) {\n element.show();\n var offset = calculateOffset(highWarningValue, minValue, maxValue);\n element.width(653-offset);\n} else {\n element.hide();\n}\n\nif (showHighWarningScale && value !== null) {\n var highCriticalScale = ctx.properties.highCriticalScale;\n if (!showHighCriticalScale) {\n highCriticalScale = Number.MAX_SAFE_INTEGER;\n }\n var highWarningScale = ctx.properties.highWarningScale;\n if (value < highCriticalScale && value >= highWarningScale) {\n element.fill(ctx.properties.activeWarningScaleColor);\n } else {\n element.fill(ctx.properties.defaultWarningScaleColor);\n }\n}", "actions": null }, { @@ -33,12 +33,12 @@ }, { "tag": "lowCriticalScale", - "stateRenderFunction": "function calculateOffset(value, minValue, maxValue) {\n var clampedValue = Math.max(minValue, Math.min(value, maxValue));\n var normalizedValue = (clampedValue - minValue) / (maxValue - minValue);\n var offset = normalizedValue * 653;\n return offset;\n}\n\nvar value = ctx.values.value;\nvar minValue = ctx.properties.minValue;\nvar maxValue = ctx.properties.maxValue;\nvar showLowCriticalScale = ctx.properties.showLowCriticalScale;\nvar lowCriticalScale = ctx.properties.lowCriticalScale;\n\nif (showLowCriticalScale) {\n element.show();\n var offset = calculateOffset(lowCriticalScale, minValue, maxValue);\n var childrenElement = element.children();\n element.width(offset);\n} else {\n element.hide();\n}\n\nif (showLowCriticalScale && value !== null) {\n if (value <= lowCriticalScale && value >= ctx.properties.minValue) {\n element.fill(ctx.properties.activeCriticalScaleColor);\n } else {\n element.fill(ctx.properties.defaultCriticalScaleColor)\n }\n}", + "stateRenderFunction": "function calculateOffset(value, minValue, maxValue) {\n var clampedValue = Math.max(minValue, Math.min(value, maxValue));\n var normalizedValue = (clampedValue - minValue) / (maxValue - minValue);\n var offset = normalizedValue * 653;\n return offset;\n}\n\nvar value = ctx.values.value;\nvar minValue = ctx.properties.minValue;\nvar maxValue = ctx.properties.maxValue;\nvar showLowCriticalScale = ctx.properties.showLowCriticalScale;\nvar lowCriticalScale = ctx.properties.lowCriticalScale;\n\nif (showLowCriticalScale) {\n element.show();\n var offset = calculateOffset(lowCriticalScale, minValue, maxValue);\n var childrenElement = element.children();\n element.width(offset);\n} else {\n element.hide();\n}\n\nif (showLowCriticalScale && value !== null) {\n if (value <= lowCriticalScale) {\n element.fill(ctx.properties.activeCriticalScaleColor);\n } else {\n element.fill(ctx.properties.defaultCriticalScaleColor)\n }\n}", "actions": null }, { "tag": "lowWarningScale", - "stateRenderFunction": "function calculateOffset(value, minValue, maxValue) {\n var clampedValue = Math.max(minValue, Math.min(value, maxValue));\n var normalizedValue = (clampedValue - minValue) / (maxValue - minValue);\n var offset = normalizedValue * 653;\n\n return offset;\n}\n\nvar value = ctx.values.value;\nvar minValue = ctx.properties.minValue;\nvar maxValue = ctx.properties.maxValue;\nvar showLowWarningScale = ctx.properties.showLowWarningScale;\nvar showLowCriticalScale = ctx.properties.showLowCriticalScale;\nvar lowWarningScale = ctx.properties.lowWarningScale;\nif (showLowWarningScale) {\n element.show();\n var offset = calculateOffset(lowWarningScale, minValue, maxValue);\n element.width(offset);\n} else {\n element.hide();\n}\n\nif (showLowWarningScale && value !== null) {\n var lowCriticalScale = ctx.properties.lowCriticalScale;\n if (!showLowCriticalScale) {\n lowCriticalScale = ctx.properties.minValue;\n }\n if (value > lowCriticalScale && value <= lowWarningScale) {\n element.fill(ctx.properties.activeWarningScaleColor);\n } else {\n element.fill(ctx.properties.defaultWarningScaleColor);\n }\n}", + "stateRenderFunction": "function calculateOffset(value, minValue, maxValue) {\n var clampedValue = Math.max(minValue, Math.min(value, maxValue));\n var normalizedValue = (clampedValue - minValue) / (maxValue - minValue);\n var offset = normalizedValue * 653;\n\n return offset;\n}\n\nvar value = ctx.values.value;\nvar minValue = ctx.properties.minValue;\nvar maxValue = ctx.properties.maxValue;\nvar showLowWarningScale = ctx.properties.showLowWarningScale;\nvar showLowCriticalScale = ctx.properties.showLowCriticalScale;\nvar lowWarningScale = ctx.properties.lowWarningScale;\nif (showLowWarningScale) {\n element.show();\n var offset = calculateOffset(lowWarningScale, minValue, maxValue);\n element.width(offset);\n} else {\n element.hide();\n}\n\nif (showLowWarningScale && value !== null) {\n var lowCriticalScale = ctx.properties.lowCriticalScale;\n if (!showLowCriticalScale) {\n lowCriticalScale = Number.MIN_SAFE_INTEGER;\n }\n if (value > lowCriticalScale && value <= lowWarningScale) {\n element.fill(ctx.properties.activeWarningScaleColor);\n } else {\n element.fill(ctx.properties.defaultWarningScaleColor);\n }\n}", "actions": null }, { diff --git a/application/src/main/data/json/system/scada_symbols/simple-vertical-scale-hp.svg b/application/src/main/data/json/system/scada_symbols/simple-vertical-scale-hp.svg index 7f9244eaea..8cceb84a74 100644 --- a/application/src/main/data/json/system/scada_symbols/simple-vertical-scale-hp.svg +++ b/application/src/main/data/json/system/scada_symbols/simple-vertical-scale-hp.svg @@ -18,12 +18,12 @@ }, { "tag": "highCriticalScale", - "stateRenderFunction": "function calculateOffset(value, minValue, maxValue) {\n var clampedValue = Math.max(minValue, Math.min(value, maxValue));\n var normalizedValue = (clampedValue - minValue) / (maxValue - minValue);\n var offset = normalizedValue * 653;\n return offset;\n}\n\nvar value = ctx.values.value;\nvar minValue = ctx.properties.minValue;\nvar maxValue = ctx.properties.maxValue;\nvar showHighCriticalScale = ctx.properties.showHighCriticalScale;\nvar highCriticalScale = ctx.properties.highCriticalScale;\n\nif (showHighCriticalScale) {\n element.show();\n var offset = calculateOffset(highCriticalScale, minValue, maxValue);\n element.height(653-offset);\n} else {\n element.hide();\n}\n\nif (showHighCriticalScale && value !== null) {\n var highCriticalScale = ctx.properties.highCriticalScale;\n if (value >= highCriticalScale && value <= ctx.properties.maxValue) {\n element.fill(ctx.properties.activeCriticalScaleColor);\n } else {\n element.fill(ctx.properties.defaultCriticalScaleColor)\n }\n}", + "stateRenderFunction": "function calculateOffset(value, minValue, maxValue) {\n var clampedValue = Math.max(minValue, Math.min(value, maxValue));\n var normalizedValue = (clampedValue - minValue) / (maxValue - minValue);\n var offset = normalizedValue * 653;\n return offset;\n}\n\nvar value = ctx.values.value;\nvar minValue = ctx.properties.minValue;\nvar maxValue = ctx.properties.maxValue;\nvar showHighCriticalScale = ctx.properties.showHighCriticalScale;\nvar highCriticalScale = ctx.properties.highCriticalScale;\n\nif (showHighCriticalScale) {\n element.show();\n var offset = calculateOffset(highCriticalScale, minValue, maxValue);\n element.height(653-offset);\n} else {\n element.hide();\n}\n\nif (showHighCriticalScale && value !== null) {\n var highCriticalScale = ctx.properties.highCriticalScale;\n if (value >= highCriticalScale) {\n element.fill(ctx.properties.activeCriticalScaleColor);\n } else {\n element.fill(ctx.properties.defaultCriticalScaleColor)\n }\n}", "actions": null }, { "tag": "highWarningScale", - "stateRenderFunction": "function calculateOffset(value, minValue, maxValue) {\n var clampedValue = Math.max(minValue, Math.min(value, maxValue));\n var normalizedValue = (clampedValue - minValue) / (maxValue - minValue);\n var offset = normalizedValue * 653;\n return offset;\n}\n\nvar value = ctx.values.value;\nvar minValue = ctx.properties.minValue;\nvar maxValue = ctx.properties.maxValue;\nvar showHighWarningScale = ctx.properties.showHighWarningScale;\nvar showHighCriticalScale = ctx.properties.showHighCriticalScale;\nvar highWarningValue = ctx.properties.highWarningScale;\nif (showHighWarningScale) {\n element.show();\n var offset = calculateOffset(highWarningValue, minValue, maxValue);\n element.height(653-offset);\n} else {\n element.hide();\n}\nif (showHighWarningScale && value !== null) {\n var highCriticalScale = ctx.properties.highCriticalScale;\n if (!showHighCriticalScale) {\n highCriticalScale = ctx.properties.maxValue;\n }\n var highWarningScale = ctx.properties.highWarningScale;\n if (value < highCriticalScale && value >= highWarningScale) {\n element.fill(ctx.properties.activeWarningScaleColor);\n } else {\n element.fill(ctx.properties.defaultWarningScaleColor);\n }\n}", + "stateRenderFunction": "function calculateOffset(value, minValue, maxValue) {\n var clampedValue = Math.max(minValue, Math.min(value, maxValue));\n var normalizedValue = (clampedValue - minValue) / (maxValue - minValue);\n var offset = normalizedValue * 653;\n return offset;\n}\n\nvar value = ctx.values.value;\nvar minValue = ctx.properties.minValue;\nvar maxValue = ctx.properties.maxValue;\nvar showHighWarningScale = ctx.properties.showHighWarningScale;\nvar showHighCriticalScale = ctx.properties.showHighCriticalScale;\nvar highWarningValue = ctx.properties.highWarningScale;\nif (showHighWarningScale) {\n element.show();\n var offset = calculateOffset(highWarningValue, minValue, maxValue);\n element.height(653-offset);\n} else {\n element.hide();\n}\nif (showHighWarningScale && value !== null) {\n var highCriticalScale = ctx.properties.highCriticalScale;\n if (!showHighCriticalScale) {\n highCriticalScale = Number.MAX_SAFE_INTEGER;\n }\n var highWarningScale = ctx.properties.highWarningScale;\n if (value < highCriticalScale && value >= highWarningScale) {\n element.fill(ctx.properties.activeWarningScaleColor);\n } else {\n element.fill(ctx.properties.defaultWarningScaleColor);\n }\n}", "actions": null }, { @@ -33,12 +33,12 @@ }, { "tag": "lowCriticalScale", - "stateRenderFunction": "function calculateOffset(value, minValue, maxValue) {\n var clampedValue = Math.max(minValue, Math.min(value, maxValue));\n var normalizedValue = (clampedValue - minValue) / (maxValue - minValue);\n var offset = normalizedValue * 653;\n\n return offset;\n}\n\nvar value = ctx.values.value;\nvar minValue = ctx.properties.minValue;\nvar maxValue = ctx.properties.maxValue;\nvar showLowCriticalScale = ctx.properties.showLowCriticalScale;\nvar lowCriticalScale = ctx.properties.lowCriticalScale;\nif (showLowCriticalScale) {\n element.show();\n var offset = calculateOffset(lowCriticalScale, minValue, maxValue);\n element.height(offset);\n} else {\n element.hide();\n}\n\nif (showLowCriticalScale && value !== null) {\n if (value <= lowCriticalScale && value >= ctx.properties.minValue) {\n element.fill(ctx.properties.activeCriticalScaleColor);\n } else {\n element.fill(ctx.properties.defaultCriticalScaleColor)\n }\n}", + "stateRenderFunction": "function calculateOffset(value, minValue, maxValue) {\n var clampedValue = Math.max(minValue, Math.min(value, maxValue));\n var normalizedValue = (clampedValue - minValue) / (maxValue - minValue);\n var offset = normalizedValue * 653;\n\n return offset;\n}\n\nvar value = ctx.values.value;\nvar minValue = ctx.properties.minValue;\nvar maxValue = ctx.properties.maxValue;\nvar showLowCriticalScale = ctx.properties.showLowCriticalScale;\nvar lowCriticalScale = ctx.properties.lowCriticalScale;\nif (showLowCriticalScale) {\n element.show();\n var offset = calculateOffset(lowCriticalScale, minValue, maxValue);\n element.height(offset);\n} else {\n element.hide();\n}\n\nif (showLowCriticalScale && value !== null) {\n if (value <= lowCriticalScale) {\n element.fill(ctx.properties.activeCriticalScaleColor);\n } else {\n element.fill(ctx.properties.defaultCriticalScaleColor)\n }\n}", "actions": null }, { "tag": "lowWarningScale", - "stateRenderFunction": "function calculateOffset(value, minValue, maxValue) {\n var clampedValue = Math.max(minValue, Math.min(value, maxValue));\n var normalizedValue = (clampedValue - minValue) / (maxValue - minValue);\n var offset = normalizedValue * 653;\n\n return offset;\n}\n\nvar value = ctx.values.value;\nvar minValue = ctx.properties.minValue;\nvar maxValue = ctx.properties.maxValue;\nvar showLowWarningScale = ctx.properties.showLowWarningScale;\nvar showLowCriticalScale = ctx.properties.showLowCriticalScale;\nvar lowWarningScale = ctx.properties.lowWarningScale;\nif (showLowWarningScale) {\n element.show();\n var offset = calculateOffset(lowWarningScale, minValue, maxValue);\n element.height(offset);\n} else {\n element.hide();\n}\n\nif (showLowWarningScale && value !== null) {\n var lowCriticalScale = ctx.properties.lowCriticalScale;\n if (!showLowCriticalScale) {\n lowCriticalScale = ctx.properties.minValue;\n }\n if (value > lowCriticalScale && value <= lowWarningScale) {\n element.fill(ctx.properties.activeWarningScaleColor);\n } else {\n element.fill(ctx.properties.defaultWarningScaleColor);\n }\n}", + "stateRenderFunction": "function calculateOffset(value, minValue, maxValue) {\n var clampedValue = Math.max(minValue, Math.min(value, maxValue));\n var normalizedValue = (clampedValue - minValue) / (maxValue - minValue);\n var offset = normalizedValue * 653;\n return offset;\n}\n\nvar value = ctx.values.value;\nvar minValue = ctx.properties.minValue;\nvar maxValue = ctx.properties.maxValue;\nvar showLowWarningScale = ctx.properties.showLowWarningScale;\nvar showLowCriticalScale = ctx.properties.showLowCriticalScale;\nvar lowWarningScale = ctx.properties.lowWarningScale;\nif (showLowWarningScale) {\n element.show();\n var offset = calculateOffset(lowWarningScale, minValue, maxValue);\n element.height(offset);\n} else {\n element.hide();\n}\nif (showLowWarningScale && value !== null) {\n var lowCriticalScale = ctx.properties.lowCriticalScale;\n if (!showLowCriticalScale) {\n lowCriticalScale = Number.MIN_SAFE_INTEGER;\n }\n if (value > lowCriticalScale && value <= lowWarningScale) {\n element.fill(ctx.properties.activeWarningScaleColor);\n } else {\n element.fill(ctx.properties.defaultWarningScaleColor);\n }\n}", "actions": null }, { From 48c8160e1f01cab7de5c0e6a7315bf85805f6ec5 Mon Sep 17 00:00:00 2001 From: Artem Dzhereleiko Date: Fri, 6 Dec 2024 09:54:03 +0200 Subject: [PATCH 03/28] UI: Add no text for resources autocomplete --- .../resource/resource-autocomplete.component.html | 13 +++++++++++-- .../resource/resource-autocomplete.component.ts | 8 +++++++- ui-ngx/src/assets/locale/locale.constant-en_US.json | 4 +++- 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/ui-ngx/src/app/shared/components/resource/resource-autocomplete.component.html b/ui-ngx/src/app/shared/components/resource/resource-autocomplete.component.html index 7d0c9ffb9f..bcc566aeea 100644 --- a/ui-ngx/src/app/shared/components/resource/resource-autocomplete.component.html +++ b/ui-ngx/src/app/shared/components/resource/resource-autocomplete.component.html @@ -41,8 +41,17 @@ - - {{ searchText }} + +
+
+ {{ 'js-func.no-js-module-text' | translate }} +
+ + + {{ translate.get('js-func.no-js-module-matching', {module: searchText}) | async }} + + +
diff --git a/ui-ngx/src/app/shared/components/resource/resource-autocomplete.component.ts b/ui-ngx/src/app/shared/components/resource/resource-autocomplete.component.ts index 0cf13f2052..b87cfe8c4f 100644 --- a/ui-ngx/src/app/shared/components/resource/resource-autocomplete.component.ts +++ b/ui-ngx/src/app/shared/components/resource/resource-autocomplete.component.ts @@ -33,6 +33,7 @@ import { TbResourceId } from '@shared/models/id/tb-resource-id'; import { ResourceService } from '@core/http/resource.service'; import { PageLink } from '@shared/models/page/page-link'; import { MatFormFieldAppearance, SubscriptSizing } from '@angular/material/form-field'; +import { TranslateService } from '@ngx-translate/core'; @Component({ selector: 'tb-resource-autocomplete', @@ -95,7 +96,8 @@ export class ResourceAutocompleteComponent implements ControlValueAccessor, OnIn private propagateChange: (value: any) => void = () => {}; constructor(private fb: FormBuilder, - private resourceService: ResourceService) { + private resourceService: ResourceService, + public translate: TranslateService) { } ngOnInit(): void { @@ -210,6 +212,10 @@ export class ResourceAutocompleteComponent implements ControlValueAccessor, OnIn } } + textIsNotEmpty(text: string): boolean { + return (text && text.length > 0); + } + private fetchResources(searchText?: string): Observable> { this.searchText = searchText; return this.resourceService.getResources(new PageLink(50, 0, searchText), ResourceType.JS_MODULE, this.subType, {ignoreLoading: true}).pipe( 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 c2f45da84f..6b50deb6ab 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -3332,7 +3332,9 @@ "module-no-members": "Module has no exported members", "module-load-error": "Module load error", "source-code": "Source code", - "source-code-load-error": "Source code load error" + "source-code-load-error": "Source code load error", + "no-js-module-text": "No JS module found", + "no-js-module-matching": "No JS module matching '{{module}}' were found." }, "key-val": { "key": "Key", From 97f3288c893e6395a21b0a89033ccf6c99d2553d Mon Sep 17 00:00:00 2001 From: Artem Dzhereleiko Date: Fri, 6 Dec 2024 11:25:06 +0200 Subject: [PATCH 04/28] UI: Fixed hide menu export dashboard after select option --- .../home/components/dashboard-page/dashboard-page.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.component.ts b/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.component.ts index 2e22975f7e..4a213ce263 100644 --- a/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.component.ts +++ b/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.component.ts @@ -874,7 +874,7 @@ export class DashboardPageComponent extends PageComponent implements IDashboardC public exportDashboard($event: Event) { if ($event) { - $event.stopPropagation(); + $event.preventDefault(); } this.importExport.exportDashboard(this.currentDashboardId); } From d56fc4c440edc518979919a74f9b1caeb1bb0e5c Mon Sep 17 00:00:00 2001 From: Vladyslav_Prykhodko Date: Fri, 6 Dec 2024 12:35:14 +0200 Subject: [PATCH 05/28] UI: Fixed mobile center translate, validation and editor --- .../mobile/applications/mobile-app.component.ts | 8 ++++---- .../mobile/bundes/layout/mobile-layout.component.ts | 2 +- .../bundes/layout/mobile-page-item-row.component.ts | 4 ++-- .../pages/mobile/common/editor-panel.component.ts | 12 ++++++++++-- ui-ngx/src/assets/locale/locale.constant-en_US.json | 4 ++-- 5 files changed, 19 insertions(+), 11 deletions(-) diff --git a/ui-ngx/src/app/modules/home/pages/mobile/applications/mobile-app.component.ts b/ui-ngx/src/app/modules/home/pages/mobile/applications/mobile-app.component.ts index 803748c7d5..0d7a9c081c 100644 --- a/ui-ngx/src/app/modules/home/pages/mobile/applications/mobile-app.component.ts +++ b/ui-ngx/src/app/modules/home/pages/mobile/applications/mobile-app.component.ts @@ -76,9 +76,9 @@ export class MobileAppComponent extends EntityComponent { }), storeInfo: this.fb.group({ storeLink: [entity?.storeInfo?.storeLink ? entity.storeInfo.storeLink : '', - Validators.pattern(/^https?:\/\/play\.google\.com\/store\/apps\/details\?id=[a-zA-Z0-9._]+$/)], + Validators.pattern(/^https?:\/\/play\.google\.com\/store\/apps\/details\?id=[a-zA-Z0-9._]+(?:&[a-zA-Z0-9._-]+=[a-zA-Z0-9._%-]*)*$/)], sha256CertFingerprints: [entity?.storeInfo?.sha256CertFingerprints ? entity.storeInfo.sha256CertFingerprints : '', - Validators.pattern(/^[A-Fa-f0-9]{2}(:[A-Fa-f0-9]{2}){1,31}$/)], + Validators.pattern(/^[A-Fa-f0-9]{2}(:[A-Fa-f0-9]{2}){31}$/)], appId: [entity?.storeInfo?.appId ? entity.storeInfo.appId : '', Validators.pattern(/^[A-Z0-9]{10}\.[a-zA-Z0-9]+(\.[a-zA-Z0-9]+)*$/)], }), }); @@ -89,11 +89,11 @@ export class MobileAppComponent extends EntityComponent { if (value === PlatformType.ANDROID) { form.get('storeInfo.sha256CertFingerprints').enable({emitEvent: false}); form.get('storeInfo.appId').disable({emitEvent: false}); - form.get('storeInfo.storeLink').setValidators(Validators.pattern(/^https?:\/\/play\.google\.com\/store\/apps\/details\?id=[a-zA-Z0-9._]+$/)); + form.get('storeInfo.storeLink').setValidators(Validators.pattern(/^https?:\/\/play\.google\.com\/store\/apps\/details\?id=[a-zA-Z0-9._]+(?:&[a-zA-Z0-9._-]+=[a-zA-Z0-9._%-]*)*$/)); } else if (value === PlatformType.IOS) { form.get('storeInfo.sha256CertFingerprints').disable({emitEvent: false}); form.get('storeInfo.appId').enable({emitEvent: false}); - form.get('storeInfo.storeLink').setValidators(Validators.pattern(/^https?:\/\/apps\.apple\.com\/[a-z]{2}\/app\/[\w-]+\/id\d{7,10}$/)); + form.get('storeInfo.storeLink').setValidators(Validators.pattern(/^https?:\/\/apps\.apple\.com\/[a-z]{2}\/app\/[\w-]+\/id\d{7,10}(?:\?[^\s]*)?$/)); } form.get('storeInfo.storeLink').setValue('', {emitEvent: false}); }); diff --git a/ui-ngx/src/app/modules/home/pages/mobile/bundes/layout/mobile-layout.component.ts b/ui-ngx/src/app/modules/home/pages/mobile/bundes/layout/mobile-layout.component.ts index 2b561a4fce..c7dd980378 100644 --- a/ui-ngx/src/app/modules/home/pages/mobile/bundes/layout/mobile-layout.component.ts +++ b/ui-ngx/src/app/modules/home/pages/mobile/bundes/layout/mobile-layout.component.ts @@ -207,7 +207,7 @@ export class MobileLayoutComponent implements ControlValueAccessor, Validator { private updateModel() { if (isDefaultMobilePagesConfig(this.pagesForm.value.pages as MobilePage[])) { - this.propagateChange({pages: []}); + this.propagateChange(null); } else { this.propagateChange(this.pagesForm.value); } diff --git a/ui-ngx/src/app/modules/home/pages/mobile/bundes/layout/mobile-page-item-row.component.ts b/ui-ngx/src/app/modules/home/pages/mobile/bundes/layout/mobile-page-item-row.component.ts index eb9f7a2d63..9a60c87959 100644 --- a/ui-ngx/src/app/modules/home/pages/mobile/bundes/layout/mobile-page-item-row.component.ts +++ b/ui-ngx/src/app/modules/home/pages/mobile/bundes/layout/mobile-page-item-row.component.ts @@ -187,7 +187,7 @@ export class MobilePageItemRowComponent implements ControlValueAccessor, OnInit, } } else { this.isCustomMenuItem = true; - this.mobilePageRowForm.get('label').setValidators([Validators.required]); + this.mobilePageRowForm.get('label').addValidators([Validators.required]); this.mobilePageRowForm.get('label').updateValueAndValidity({emitEvent: false}); } this.updateCleanupState(); @@ -270,7 +270,7 @@ export class MobilePageItemRowComponent implements ControlValueAccessor, OnInit, private updateModel() { this.modelValue.visible = this.mobilePageRowForm.get('visible').value; - const label = this.mobilePageRowForm.get('label').value; + const label = this.mobilePageRowForm.get('label').value.trim(); if (label) { this.modelValue.label = label; } else { diff --git a/ui-ngx/src/app/modules/home/pages/mobile/common/editor-panel.component.ts b/ui-ngx/src/app/modules/home/pages/mobile/common/editor-panel.component.ts index 9b9b282e9d..15dff508c8 100644 --- a/ui-ngx/src/app/modules/home/pages/mobile/common/editor-panel.component.ts +++ b/ui-ngx/src/app/modules/home/pages/mobile/common/editor-panel.component.ts @@ -17,6 +17,7 @@ import { Component, EventEmitter, Input, OnInit, Output, ViewEncapsulation } from '@angular/core'; import { FormBuilder, FormControl } from '@angular/forms'; import { TbPopoverComponent } from '@shared/components/popover.component'; +import { EditorOptions } from 'tinymce'; @Component({ selector: 'tb-release-notes-panel', @@ -43,7 +44,7 @@ export class EditorPanelComponent implements OnInit { editorControl: FormControl; - tinyMceOptions: Record = { + tinyMceOptions: Partial = { base_url: '/assets/tinymce', suffix: '.min', plugins: ['lists'], @@ -55,7 +56,14 @@ export class EditorPanelComponent implements OnInit { autofocus: false, branding: false, promotion: false, - resize: false + resize: false, + setup: (editor) => { + editor.on('PostRender', function() { + const container = editor.getContainer(); + const uiContainer = document.querySelector('.tox.tox-tinymce-aux'); + container.parentNode.appendChild(uiContainer); + }); + } }; constructor(private fb: FormBuilder) { 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 c2f45da84f..491e7136a6 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -3550,7 +3550,7 @@ "tablet-959": "Tablet (max 959px)", "max-element-number": "Max elements number", "page-name": "Page name", - "page-nam-required": "Page name is required.", + "page-name-required": "Page name is required.", "page-type": "Page type", "pages-types": { "dashboard": "Dashboard", @@ -3560,7 +3560,7 @@ "url": "URL", "url-pattern": "Invalid URL", "path": "Path", - "path-pattern": "Path pattern", + "path-pattern": "Invalid path", "custom-page": "Custom page", "edit-page": "Edit page", "edit-custom-page": "Edit custom page", From e563649e98e2c4891ef404f7c1f1e3464b253f62 Mon Sep 17 00:00:00 2001 From: Vladyslav_Prykhodko Date: Fri, 6 Dec 2024 13:09:59 +0200 Subject: [PATCH 06/28] UI: Fixed load background in image map --- .../home/components/widget/lib/maps/providers/image-map.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/maps/providers/image-map.ts b/ui-ngx/src/app/modules/home/components/widget/lib/maps/providers/image-map.ts index 0abcc9f7c8..d91a84d3b2 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/maps/providers/image-map.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/maps/providers/image-map.ts @@ -23,14 +23,14 @@ import { PosFunction, WidgetUnitedMapSettings } from '../map-models'; -import { forkJoin, Observable, of, ReplaySubject, switchMap } from 'rxjs'; +import { combineLatest, Observable, of, ReplaySubject, switchMap } from 'rxjs'; import { catchError } from 'rxjs/operators'; import { calculateNewPointCoordinate, loadImageWithAspect } from '@home/components/widget/lib/maps/common-maps-utils'; import { WidgetContext } from '@home/models/widget-component.models'; import { DataSet, DatasourceType, FormattedData, widgetType } from '@shared/models/widget.models'; import { DataKeyType } from '@shared/models/telemetry/telemetry.models'; import { WidgetSubscriptionOptions } from '@core/api/widget-api.models'; -import { isDefinedAndNotNull, isEmptyStr, isNotEmptyStr, parseFunction, parseTbFunction } from '@core/utils'; +import { isDefinedAndNotNull, isEmptyStr, isNotEmptyStr, parseTbFunction } from '@core/utils'; import { EntityDataPageLink } from '@shared/models/query/query.models'; import { ImagePipe } from '@shared/pipe/image.pipe'; import { CompiledTbFunction } from '@shared/models/js-function.models'; @@ -55,7 +55,7 @@ export class ImageMap extends LeafletMap { mapImage: this.mapImage(options) }; - forkJoin(initData).subscribe(inited => { + combineLatest(initData).subscribe(inited => { this.posFunction = inited.posFunction; const mapImage = inited.mapImage; this.imageUrl = mapImage.imageUrl; From 2a1910792939a6224735f1e45e6c359bc2e57579 Mon Sep 17 00:00:00 2001 From: dashevchenko Date: Fri, 6 Dec 2024 14:43:29 +0200 Subject: [PATCH 07/28] fixed primary key name --- dao/src/main/resources/sql/schema-entities.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dao/src/main/resources/sql/schema-entities.sql b/dao/src/main/resources/sql/schema-entities.sql index f43ea4a5f6..916a5487f8 100644 --- a/dao/src/main/resources/sql/schema-entities.sql +++ b/dao/src/main/resources/sql/schema-entities.sql @@ -896,7 +896,7 @@ CREATE TABLE IF NOT EXISTS queue_stats ( ); CREATE TABLE IF NOT EXISTS qr_code_settings ( - id uuid NOT NULL CONSTRAINT mobile_app_settings_pkey PRIMARY KEY, + id uuid NOT NULL CONSTRAINT qr_code_settings_pkey PRIMARY KEY, created_time bigint NOT NULL, tenant_id uuid NOT NULL, use_default_app boolean, From 534e2349fbc264e941476bfc41ac87c4e8be2117 Mon Sep 17 00:00:00 2001 From: dashevchenko Date: Fri, 6 Dec 2024 14:49:15 +0200 Subject: [PATCH 08/28] updated upgrade script to rename old primary key name --- application/src/main/data/upgrade/basic/schema_update.sql | 1 + 1 file changed, 1 insertion(+) diff --git a/application/src/main/data/upgrade/basic/schema_update.sql b/application/src/main/data/upgrade/basic/schema_update.sql index 9390238139..ced110e65a 100644 --- a/application/src/main/data/upgrade/basic/schema_update.sql +++ b/application/src/main/data/upgrade/basic/schema_update.sql @@ -189,6 +189,7 @@ $$ END IF; END LOOP; ALTER TABLE qr_code_settings RENAME CONSTRAINT mobile_app_settings_tenant_id_unq_key TO qr_code_settings_tenant_id_unq_key; + ALTER TABLE qr_code_settings RENAME CONSTRAINT mobile_app_settings_pkey TO qr_code_settings_pkey; END IF; ALTER TABLE qr_code_settings DROP COLUMN IF EXISTS android_config, DROP COLUMN IF EXISTS ios_config; END; From 8e20d740338f27825a2c2a92a03b93f363b1f5a5 Mon Sep 17 00:00:00 2001 From: kalytka Date: Fri, 6 Dec 2024 16:54:18 +0200 Subject: [PATCH 09/28] Share echarts-widget.models --- ui-ngx/src/app/modules/home/components/public-api.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/ui-ngx/src/app/modules/home/components/public-api.ts b/ui-ngx/src/app/modules/home/components/public-api.ts index 461c106b51..6fa57fb4c4 100644 --- a/ui-ngx/src/app/modules/home/components/public-api.ts +++ b/ui-ngx/src/app/modules/home/components/public-api.ts @@ -19,6 +19,7 @@ export * from './widget/config/basic/basic-widget-config.module'; export * from './widget/lib/settings/common/widget-settings-common.module'; export * from './widget/widget-components.module'; export * from './widget/config/widget-config-components.module'; +export * from './widget/lib/chart/echarts-widget.models'; export * from './widget/config/widget-config.component.models'; export * from './widget/lib/table-widget.models'; From 09bc214bd3faa487e11e9952fde7b21a6c488a4d Mon Sep 17 00:00:00 2001 From: mpetrov Date: Fri, 6 Dec 2024 17:07:15 +0200 Subject: [PATCH 10/28] UI: Debug Settings fixes --- .../app/core/services/item-buffer.service.ts | 2 +- .../debug-settings-button.component.html | 11 +++--- .../debug-settings-button.component.ts | 39 ++++++++++++------- .../debug-settings-panel.component.html | 5 ++- .../debug-settings-panel.component.ts | 7 ++-- .../rulechain/rulechain-page.component.html | 6 +-- .../rulechain/rulechain-page.component.ts | 18 ++++++--- .../pipe/milliseconds-to-time-string.pipe.ts | 15 ++++--- .../assets/locale/locale.constant-ar_AE.json | 1 - .../assets/locale/locale.constant-ca_ES.json | 3 +- .../assets/locale/locale.constant-cs_CZ.json | 3 +- .../assets/locale/locale.constant-da_DK.json | 3 +- .../assets/locale/locale.constant-el_GR.json | 3 +- .../assets/locale/locale.constant-en_US.json | 7 ++-- .../assets/locale/locale.constant-es_ES.json | 1 - .../assets/locale/locale.constant-ka_GE.json | 3 +- .../assets/locale/locale.constant-ko_KR.json | 3 +- .../assets/locale/locale.constant-lt_LT.json | 2 +- .../assets/locale/locale.constant-lv_LV.json | 3 +- .../assets/locale/locale.constant-nl_BE.json | 3 +- .../assets/locale/locale.constant-pl_PL.json | 1 - .../assets/locale/locale.constant-pt_BR.json | 3 +- .../assets/locale/locale.constant-ro_RO.json | 1 - .../assets/locale/locale.constant-sl_SI.json | 3 +- .../assets/locale/locale.constant-tr_TR.json | 3 +- .../assets/locale/locale.constant-uk_UA.json | 3 +- .../assets/locale/locale.constant-zh_CN.json | 1 - .../assets/locale/locale.constant-zh_TW.json | 3 +- 28 files changed, 79 insertions(+), 77 deletions(-) diff --git a/ui-ngx/src/app/core/services/item-buffer.service.ts b/ui-ngx/src/app/core/services/item-buffer.service.ts index c77784c4f5..ff4211961a 100644 --- a/ui-ngx/src/app/core/services/item-buffer.service.ts +++ b/ui-ngx/src/app/core/services/item-buffer.service.ts @@ -305,7 +305,7 @@ export class ItemBufferService { connectors: [], additionalInfo: origNode.additionalInfo, configuration: origNode.configuration, - debugMode: origNode.debugMode, + debugSettings: origNode.debugSettings, x: origNode.x, y: origNode.y, name: origNode.name, diff --git a/ui-ngx/src/app/modules/home/components/debug-settings/debug-settings-button.component.html b/ui-ngx/src/app/modules/home/components/debug-settings/debug-settings-button.component.html index b779ae1e4c..d20fa2e90d 100644 --- a/ui-ngx/src/app/modules/home/components/debug-settings/debug-settings-button.component.html +++ b/ui-ngx/src/app/modules/home/components/debug-settings/debug-settings-button.component.html @@ -23,10 +23,9 @@ [disabled]="disabled" (click)="openDebugStrategyPanel($event, matButton)"> bug_report - common.disabled - debug-config.all - - {{ !allEnabled ? (allEnabledUntil | durationLeft) : ('debug-config.min' | translate: { number: maxDebugModeDurationMinutes }) }} - - debug-config.failures + @if (isDebugAllActive$ | async) { + {{ !allEnabled() ? (allEnabledUntil | durationLeft) : (maxDebugModeDuration | milliSecondsToTimeString: true : true).trim() }} + } @else { + {{ failuresEnabled ? ('debug-config.failures' | translate) : ('common.disabled' | translate) }} + } diff --git a/ui-ngx/src/app/modules/home/components/debug-settings/debug-settings-button.component.ts b/ui-ngx/src/app/modules/home/components/debug-settings/debug-settings-button.component.ts index dafda75c0b..4db01892a2 100644 --- a/ui-ngx/src/app/modules/home/components/debug-settings/debug-settings-button.component.ts +++ b/ui-ngx/src/app/modules/home/components/debug-settings/debug-settings-button.component.ts @@ -14,18 +14,26 @@ /// limitations under the License. /// -import { ChangeDetectionStrategy, Component, forwardRef, Input, Renderer2, ViewContainerRef } from '@angular/core'; +import { + ChangeDetectionStrategy, + Component, + forwardRef, + Input, + Renderer2, + signal, + ViewContainerRef +} from '@angular/core'; import { CommonModule } from '@angular/common'; import { SharedModule } from '@shared/shared.module'; import { DurationLeftPipe } from '@shared/pipe/duration-left.pipe'; import { TbPopoverService } from '@shared/components/popover.service'; import { MatButton } from '@angular/material/button'; import { DebugSettingsPanelComponent } from './debug-settings-panel.component'; -import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; +import { takeUntilDestroyed, toObservable } from '@angular/core/rxjs-interop'; import { of, shareReplay, timer } from 'rxjs'; -import { SECOND } from '@shared/models/time/time.models'; +import { MINUTE, SECOND } from '@shared/models/time/time.models'; import { DebugSettings } from '@shared/models/entity.models'; -import { map, startWith, switchMap, takeWhile } from 'rxjs/operators'; +import { map, switchMap, takeWhile } from 'rxjs/operators'; import { getCurrentAuthState } from '@core/auth/auth.selectors'; import { AppState } from '@core/core.state'; import { Store } from '@ngrx/store'; @@ -60,11 +68,11 @@ export class DebugSettingsButtonComponent implements ControlValueAccessor { }); disabled = false; + allEnabled = signal(false); - isDebugAllActive$ = this.debugSettingsFormGroup.get('allEnabled').valueChanges.pipe( - startWith(null), - switchMap(() => { - if (this.allEnabled) { + isDebugAllActive$ = toObservable(this.allEnabled).pipe( + switchMap((value) => { + if (value) { return of(true); } else { return timer(0, SECOND).pipe( @@ -77,7 +85,7 @@ export class DebugSettingsButtonComponent implements ControlValueAccessor { shareReplay(1) ); - readonly maxDebugModeDurationMinutes = getCurrentAuthState(this.store).maxDebugModeDurationMinutes; + readonly maxDebugModeDuration = getCurrentAuthState(this.store).maxDebugModeDurationMinutes * MINUTE; private propagateChange: (settings: DebugSettings) => void = () => {}; @@ -91,17 +99,17 @@ export class DebugSettingsButtonComponent implements ControlValueAccessor { takeUntilDestroyed() ).subscribe(value => { this.propagateChange(value); - }) + }); + + this.debugSettingsFormGroup.get('allEnabled').valueChanges.pipe( + takeUntilDestroyed() + ).subscribe(value => this.allEnabled.set(value)); } get failuresEnabled(): boolean { return this.debugSettingsFormGroup.get('failuresEnabled').value; } - get allEnabled(): boolean { - return this.debugSettingsFormGroup.get('allEnabled').value; - } - get allEnabledUntil(): number { return this.debugSettingsFormGroup.get('allEnabledUntil').value; } @@ -120,7 +128,7 @@ export class DebugSettingsButtonComponent implements ControlValueAccessor { this.viewContainerRef, DebugSettingsPanelComponent, 'bottom', true, null, { ...debugSettings, - maxDebugModeDurationMinutes: this.maxDebugModeDurationMinutes, + maxDebugModeDuration: this.maxDebugModeDuration, debugLimitsConfiguration: this.debugLimitsConfiguration }, {}, @@ -141,6 +149,7 @@ export class DebugSettingsButtonComponent implements ControlValueAccessor { writeValue(settings: DebugSettings): void { this.debugSettingsFormGroup.patchValue(settings, {emitEvent: false}); + this.allEnabled.set(settings?.allEnabled); this.debugSettingsFormGroup.get('allEnabled').updateValueAndValidity({onlySelf: true}); } diff --git a/ui-ngx/src/app/modules/home/components/debug-settings/debug-settings-panel.component.html b/ui-ngx/src/app/modules/home/components/debug-settings/debug-settings-panel.component.html index 5fe0aa2546..f088fc38ac 100644 --- a/ui-ngx/src/app/modules/home/components/debug-settings/debug-settings-panel.component.html +++ b/ui-ngx/src/app/modules/home/components/debug-settings/debug-settings-panel.component.html @@ -20,7 +20,7 @@
@if (debugLimitsConfiguration) { - {{ 'debug-config.hint.main-limited' | translate: { msg: maxMessagesCount, sec: maxTimeFrameSec } }} + {{ 'debug-config.hint.main-limited' | translate: { msg: maxMessagesCount, time: (maxTimeFrameDuration | milliSecondsToTimeString: true : true).trim() } }} } @else { {{ 'debug-config.hint.main' | translate }} } @@ -35,7 +35,7 @@
- {{ 'debug-config.all-messages' | translate: { time: (isDebugAllActive$ | async) && !allEnabled ? (allEnabledUntil | durationLeft) : ('debug-config.min' | translate: { number: maxDebugModeDurationMinutes }) } }} + {{ 'debug-config.all-messages' | translate: { time: (isDebugAllActive$ | async) && !allEnabled ? (allEnabledUntil | durationLeft) : (maxDebugModeDuration | milliSecondsToTimeString: true : true).trim() } }}
diff --git a/ui-ngx/src/app/modules/home/components/debug-settings/debug-settings-panel.component.ts b/ui-ngx/src/app/modules/home/components/debug-settings/debug-settings-panel.component.ts index a9e237245c..2c98dee6c4 100644 --- a/ui-ngx/src/app/modules/home/components/debug-settings/debug-settings-panel.component.ts +++ b/ui-ngx/src/app/modules/home/components/debug-settings/debug-settings-panel.component.ts @@ -52,14 +52,14 @@ export class DebugSettingsPanelComponent extends PageComponent implements OnInit @Input({ transform: booleanAttribute }) failuresEnabled = false; @Input({ transform: booleanAttribute }) allEnabled = false; @Input() allEnabledUntil = 0; - @Input() maxDebugModeDurationMinutes: number; + @Input() maxDebugModeDuration: number; @Input() debugLimitsConfiguration: string; onFailuresControl = this.fb.control(false); debugAllControl = this.fb.control(false); maxMessagesCount: string; - maxTimeFrameSec: string; + maxTimeFrameDuration: number; initialAllEnabled: boolean; isDebugAllActive$ = this.debugAllControl.valueChanges.pipe( @@ -99,7 +99,7 @@ export class DebugSettingsPanelComponent extends PageComponent implements OnInit ngOnInit(): void { this.maxMessagesCount = this.debugLimitsConfiguration?.split(':')[0]; - this.maxTimeFrameSec = this.debugLimitsConfiguration?.split(':')[1]; + this.maxTimeFrameDuration = parseInt(this.debugLimitsConfiguration?.split(':')[1]) * SECOND; this.onFailuresControl.patchValue(this.failuresEnabled); this.debugAllControl.patchValue(this.allEnabled); this.initialAllEnabled = this.allEnabled || this.allEnabledUntil > new Date().getTime(); @@ -128,6 +128,7 @@ export class DebugSettingsPanelComponent extends PageComponent implements OnInit onReset(): void { this.debugAllControl.patchValue(true); + this.debugAllControl.markAsDirty(); this.allEnabledUntil = 0; this.cd.markForCheck(); } diff --git a/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.component.html b/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.component.html index 5e955dc4b4..7bf85aa215 100644 --- a/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.component.html +++ b/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.component.html @@ -239,10 +239,10 @@ matTooltipPosition="above"> delete - diff --git a/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.component.ts b/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.component.ts index 35b10a27b3..2d440ed28c 100644 --- a/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.component.ts +++ b/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.component.ts @@ -95,6 +95,7 @@ import { ComponentClusteringMode } from '@shared/models/component-descriptor.mod import { MatDrawer } from '@angular/material/sidenav'; import { HttpStatusCode } from '@angular/common/http'; import { TbContextMenuEvent } from '@shared/models/jquery-event.models'; +import { DebugSettings } from '@shared/models/entity.models'; import Timeout = NodeJS.Timeout; @Component({ @@ -1415,17 +1416,20 @@ export class RuleChainPageComponent extends PageComponent this.ruleChainCanvas.modelService.deleteSelected(); } - isDebugModeEnabled(): boolean { - const res = this.ruleChainModel.nodes.find((node) => node.debugMode); + isDebugSettingsEnabled(): boolean { + const res = this.ruleChainModel.nodes.find(({ debugSettings }) => debugSettings && this.isDebugSettingsActive(debugSettings)); return typeof res !== 'undefined'; } - resetDebugModeInAllNodes() { + resetDebugSettingsInAllNodes(): void { let changed = false; this.ruleChainModel.nodes.forEach((node) => { if (node.component.type !== RuleNodeType.INPUT) { - changed = changed || node.debugMode; - node.debugMode = false; + const nodeHasActiveDebugSettings = node.debugSettings && this.isDebugSettingsActive(node.debugSettings); + changed = changed || nodeHasActiveDebugSettings; + if (nodeHasActiveDebugSettings) { + node.debugSettings = { allEnabled: false, failuresEnabled: false, allEnabledUntil: 0 }; + } } }); if (changed) { @@ -1433,6 +1437,10 @@ export class RuleChainPageComponent extends PageComponent } } + private isDebugSettingsActive({ allEnabled = false, failuresEnabled = false, allEnabledUntil = 0 }: DebugSettings): boolean { + return allEnabled || failuresEnabled || allEnabledUntil > new Date().getTime(); + } + validate() { setTimeout(() => { this.isInvalid = false; diff --git a/ui-ngx/src/app/shared/pipe/milliseconds-to-time-string.pipe.ts b/ui-ngx/src/app/shared/pipe/milliseconds-to-time-string.pipe.ts index 853890ee09..d8884992bf 100644 --- a/ui-ngx/src/app/shared/pipe/milliseconds-to-time-string.pipe.ts +++ b/ui-ngx/src/app/shared/pipe/milliseconds-to-time-string.pipe.ts @@ -16,7 +16,7 @@ import { Pipe, PipeTransform } from '@angular/core'; import { TranslateService } from '@ngx-translate/core'; -import { DAY, HOUR, MINUTE, SECOND } from '@shared/models/time/time.models'; +import { DAY, HOUR, MINUTE, SECOND, YEAR } from '@shared/models/time/time.models'; @Pipe({ name: 'milliSecondsToTimeString' @@ -27,19 +27,21 @@ export class MillisecondsToTimeStringPipe implements PipeTransform { } transform(milliSeconds: number, shortFormat = false, onlyFirstDigit = false): string { - const { days, hours, minutes, seconds } = this.extractTimeUnits(milliSeconds); - return this.formatTimeString(days, hours, minutes, seconds, shortFormat, onlyFirstDigit); + const { years, days, hours, minutes, seconds } = this.extractTimeUnits(milliSeconds); + return this.formatTimeString(years, days, hours, minutes, seconds, shortFormat, onlyFirstDigit); } - private extractTimeUnits(milliseconds: number): { days: number; hours: number; minutes: number; seconds: number } { - const days = Math.floor(milliseconds / DAY); + private extractTimeUnits(milliseconds: number): { years: number; days: number; hours: number; minutes: number; seconds: number } { + const years = Math.floor(milliseconds / YEAR); + const days = Math.floor((milliseconds % YEAR) / DAY); const hours = Math.floor((milliseconds % DAY) / HOUR); const minutes = Math.floor((milliseconds % HOUR) / MINUTE); const seconds = Math.floor((milliseconds % MINUTE) / SECOND); - return { days, hours, minutes, seconds }; + return { years, days, hours, minutes, seconds }; } private formatTimeString( + years: number, days: number, hours: number, minutes: number, @@ -48,6 +50,7 @@ export class MillisecondsToTimeStringPipe implements PipeTransform { onlyFirstDigit: boolean ): string { const timeUnits = [ + { value: years, key: 'years', shortKey: 'short.years' }, { value: days, key: 'days', shortKey: 'short.days' }, { value: hours, key: 'hours', shortKey: 'short.hours' }, { value: minutes, key: 'minutes', shortKey: 'short.minutes' }, diff --git a/ui-ngx/src/assets/locale/locale.constant-ar_AE.json b/ui-ngx/src/assets/locale/locale.constant-ar_AE.json index e4c7ddc917..695e1ad441 100644 --- a/ui-ngx/src/assets/locale/locale.constant-ar_AE.json +++ b/ui-ngx/src/assets/locale/locale.constant-ar_AE.json @@ -4602,7 +4602,6 @@ "output": "الإخراج", "test": "اختبار", "help": "مساعدة", - "reset-debug-mode": "إعادة تعيين وضع التصحيح في جميع العقد", "test-with-this-message": "{{test}} مع هذه الرسالة" }, "role": { diff --git a/ui-ngx/src/assets/locale/locale.constant-ca_ES.json b/ui-ngx/src/assets/locale/locale.constant-ca_ES.json index c04c0e12cf..43a644a537 100644 --- a/ui-ngx/src/assets/locale/locale.constant-ca_ES.json +++ b/ui-ngx/src/assets/locale/locale.constant-ca_ES.json @@ -3651,8 +3651,7 @@ "metadata-required": "Les entrades de metadades no poden estar buides.", "output": "Sortida", "test": "Test", - "help": "Ajuda", - "reset-debug-mode": "Restablir el mode de depuració a tots els nodes" + "help": "Ajuda" }, "role": { "role": "Rol", diff --git a/ui-ngx/src/assets/locale/locale.constant-cs_CZ.json b/ui-ngx/src/assets/locale/locale.constant-cs_CZ.json index 67b8b22005..4ae54c4d65 100644 --- a/ui-ngx/src/assets/locale/locale.constant-cs_CZ.json +++ b/ui-ngx/src/assets/locale/locale.constant-cs_CZ.json @@ -2426,8 +2426,7 @@ "metadata-required": "Záznam metadat nemůže být prázdný.", "output": "Výstup", "test": "Test", - "help": "Nápověda", - "reset-debug-mode": "Resetovat režim ladění na všech uzlech" + "help": "Nápověda" }, "timezone": { "timezone": "Časová zóna", diff --git a/ui-ngx/src/assets/locale/locale.constant-da_DK.json b/ui-ngx/src/assets/locale/locale.constant-da_DK.json index 9d08a72085..fbfeddd886 100644 --- a/ui-ngx/src/assets/locale/locale.constant-da_DK.json +++ b/ui-ngx/src/assets/locale/locale.constant-da_DK.json @@ -2642,8 +2642,7 @@ "metadata-required": "Metadataposter må ikke være tomme.", "output": "Output", "test": "Test", - "help": "Hjælp", - "reset-debug-mode": "Nulstil debug-tilstand i alle knuder" + "help": "Hjælp" }, "role": { "role": "Rolle", diff --git a/ui-ngx/src/assets/locale/locale.constant-el_GR.json b/ui-ngx/src/assets/locale/locale.constant-el_GR.json index eea0ea4377..164b5486b9 100644 --- a/ui-ngx/src/assets/locale/locale.constant-el_GR.json +++ b/ui-ngx/src/assets/locale/locale.constant-el_GR.json @@ -1886,8 +1886,7 @@ "metadata-required": "Οι καταχωρίσεις μεταδεδομένων δεν μπορούν να είναι κενές.", "output": "Απόδοση", "test": "Τεστ", - "help": "Βοήθεια", - "reset-debug-mode": "Επαναφορά λειτουργίας εντοπισμού σφαλμάτων σε όλους τους κόμβους" + "help": "Βοήθεια" }, "role": { "role": "Ρόλος", 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 c2f45da84f..1968f96346 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -990,15 +990,13 @@ "type-sms-sent": "SMS sent" }, "debug-config": { - "min": "{{number}} min", "label": "Debug configuration", "on-failure": "Failures only (24/7)", "all-messages": "All messages ({{time}})", "failures": "Failures", - "all": "All", "hint": { "main": "All node debug messages rate limited with:", - "main-limited": "All node debug messages will be rate-limited, with a maximum of {{msg}} messages allowed per {{sec}} seconds.", + "main-limited": "All node debug messages will be rate-limited, with a maximum of {{msg}} messages allowed per {{time}}.", "on-failure": "Save all failure debug events without time limit.", "all-messages": "Save all debug events during time limit." } @@ -4293,7 +4291,7 @@ "output": "Output", "test": "Test", "help": "Help", - "reset-debug-mode": "Reset debug mode in all nodes", + "reset-debug-settings": "Reset debug settings in all nodes", "test-with-this-message": "{{test}} with this message", "queue-hint": "Select a queue for message forwarding to another queue. 'Main' queue is used by default.", "queue-singleton-hint": "Select a queue for message forwarding in multi-instance environments. 'Main' queue is used by default." @@ -4743,6 +4741,7 @@ "sec": "{{ sec }} sec", "sec-short": "{{ sec }}s", "short": { + "years": "{ years, plural, =1 {1 year } other {# years } }", "days": "{ days, plural, =1 {1 day } other {# days } }", "hours": "{ hours, plural, =1 {1 hour } other {# hours } }", "minutes": "{{minutes}} min ", diff --git a/ui-ngx/src/assets/locale/locale.constant-es_ES.json b/ui-ngx/src/assets/locale/locale.constant-es_ES.json index 0cb9528bdd..1122c1d6fa 100644 --- a/ui-ngx/src/assets/locale/locale.constant-es_ES.json +++ b/ui-ngx/src/assets/locale/locale.constant-es_ES.json @@ -3529,7 +3529,6 @@ "output": "Salida", "test": "Test", "help": "Ayuda", - "reset-debug-mode": "Restablecer el modo de depuración en todos los nodos", "test-with-this-message": "{{test}} con este mensaje" }, "timezone": { diff --git a/ui-ngx/src/assets/locale/locale.constant-ka_GE.json b/ui-ngx/src/assets/locale/locale.constant-ka_GE.json index f645cb0f31..ae8ce2b943 100644 --- a/ui-ngx/src/assets/locale/locale.constant-ka_GE.json +++ b/ui-ngx/src/assets/locale/locale.constant-ka_GE.json @@ -1413,8 +1413,7 @@ "metadata-required": "მეტამონაცემები ვერ იქნება ცარიელი", "output": "რეზულტატი", "test": "ტესტი", - "help": "დახმარება", - "reset-debug-mode": "Debug რეჟიმის გათიშვა ყველა ნოდისთვის" + "help": "დახმარება" }, "tenant": { "tenant": "ტენანტი", diff --git a/ui-ngx/src/assets/locale/locale.constant-ko_KR.json b/ui-ngx/src/assets/locale/locale.constant-ko_KR.json index 9235fc9e95..80a2cb0830 100644 --- a/ui-ngx/src/assets/locale/locale.constant-ko_KR.json +++ b/ui-ngx/src/assets/locale/locale.constant-ko_KR.json @@ -1878,8 +1878,7 @@ "metadata-required": "메타데이터 엔트리를 입력하세요.", "output": "출력", "test": "테스트", - "help": "도움말", - "reset-debug-mode": "모든 노드에 대해 디버그 모드 초기화" + "help": "도움말" }, "timezone": { "timezone": "Timezone", diff --git a/ui-ngx/src/assets/locale/locale.constant-lt_LT.json b/ui-ngx/src/assets/locale/locale.constant-lt_LT.json index c856652198..1d2a672326 100644 --- a/ui-ngx/src/assets/locale/locale.constant-lt_LT.json +++ b/ui-ngx/src/assets/locale/locale.constant-lt_LT.json @@ -4504,7 +4504,7 @@ "output": "Output", "test": "Test", "help": "Help", - "reset-debug-mode": "Reset debug mode in all nodes", + "reset-debug-settings": "Reset debug settings in all nodes", "test-with-this-message": "{{test}} with this message" }, "role": { diff --git a/ui-ngx/src/assets/locale/locale.constant-lv_LV.json b/ui-ngx/src/assets/locale/locale.constant-lv_LV.json index 0f5c946063..bba71609ec 100644 --- a/ui-ngx/src/assets/locale/locale.constant-lv_LV.json +++ b/ui-ngx/src/assets/locale/locale.constant-lv_LV.json @@ -1338,8 +1338,7 @@ "metadata-required": "Metadatu ievadi nevar būt tukši.", "output": "Izeja", "test": "Tests", - "help": "Palīdzība", - "reset-debug-mode": "Atiestatīt atkļūdošanu visās nodēs" + "help": "Palīdzība" }, "tenant": { "tenant": "Īrnieks", diff --git a/ui-ngx/src/assets/locale/locale.constant-nl_BE.json b/ui-ngx/src/assets/locale/locale.constant-nl_BE.json index f9fe60f44d..7b99ad9953 100644 --- a/ui-ngx/src/assets/locale/locale.constant-nl_BE.json +++ b/ui-ngx/src/assets/locale/locale.constant-nl_BE.json @@ -4560,8 +4560,7 @@ "metadata-required": "Metagegevensvermeldingen mogen niet leeg zijn.", "output": "Uitvoer", "test": "Test", - "help": "Help", - "reset-debug-mode": "Foutopsporingsmodus resetten in alle rule nodes" + "help": "Help" }, "role": { "role": "Rol", diff --git a/ui-ngx/src/assets/locale/locale.constant-pl_PL.json b/ui-ngx/src/assets/locale/locale.constant-pl_PL.json index 9ab89169c0..b369f061b7 100644 --- a/ui-ngx/src/assets/locale/locale.constant-pl_PL.json +++ b/ui-ngx/src/assets/locale/locale.constant-pl_PL.json @@ -4520,7 +4520,6 @@ "output": "Wyjście", "test": "Test", "help": "Pomoc", - "reset-debug-mode": "Zresetuj tryb debugowania we wszystkich węzłach", "test-with-this-message": "{{test}} with this message", "description": "Opis" }, diff --git a/ui-ngx/src/assets/locale/locale.constant-pt_BR.json b/ui-ngx/src/assets/locale/locale.constant-pt_BR.json index 8b77be4573..bfc616e40b 100644 --- a/ui-ngx/src/assets/locale/locale.constant-pt_BR.json +++ b/ui-ngx/src/assets/locale/locale.constant-pt_BR.json @@ -1554,8 +1554,7 @@ "metadata-required": "As entradas de metadados não podem estar em branco.", "output": "Saída", "test": "Teste", - "help": "Ajuda", - "reset-debug-mode": "Redefinir modo de depuração em todos os nós" + "help": "Ajuda" }, "timezone": { "timezone": "Fuso horário", diff --git a/ui-ngx/src/assets/locale/locale.constant-ro_RO.json b/ui-ngx/src/assets/locale/locale.constant-ro_RO.json index 2eb5bc491a..1054b812a1 100644 --- a/ui-ngx/src/assets/locale/locale.constant-ro_RO.json +++ b/ui-ngx/src/assets/locale/locale.constant-ro_RO.json @@ -1401,7 +1401,6 @@ "output": "Ieşire", "test": "Test", "help": "Ajutor", - "reset-debug-mode": "Dezactivează modul depanare în toate nodurile" }, "tenant": { "tenant": "Locatar", diff --git a/ui-ngx/src/assets/locale/locale.constant-sl_SI.json b/ui-ngx/src/assets/locale/locale.constant-sl_SI.json index ff23223107..668bf8c2c9 100644 --- a/ui-ngx/src/assets/locale/locale.constant-sl_SI.json +++ b/ui-ngx/src/assets/locale/locale.constant-sl_SI.json @@ -1879,8 +1879,7 @@ "metadata-required": "Vnosi metapodatkov ne smejo biti prazni.", "output": "Izdelek", "test": "Test", - "help": "Pomoč", - "reset-debug-mode": "Ponastavi način za odpravljanje napak v vseh vozliščih" + "help": "Pomoč" }, "timezone": { "timezone": "Časovni pas", diff --git a/ui-ngx/src/assets/locale/locale.constant-tr_TR.json b/ui-ngx/src/assets/locale/locale.constant-tr_TR.json index e954e8f2e1..98998ab312 100644 --- a/ui-ngx/src/assets/locale/locale.constant-tr_TR.json +++ b/ui-ngx/src/assets/locale/locale.constant-tr_TR.json @@ -2447,8 +2447,7 @@ "metadata-required": "Meta veri girişleri boş bırakılamaz.", "output": "Çıktı", "test": "Ölçek", - "help": "Yardım et", - "reset-debug-mode": "Tüm düğümlerde hata ayıklama modunu sıfırla" + "help": "Yardım et" }, "timezone": { "timezone": "Saat dilimi", diff --git a/ui-ngx/src/assets/locale/locale.constant-uk_UA.json b/ui-ngx/src/assets/locale/locale.constant-uk_UA.json index e1bf787994..09cf86bc21 100644 --- a/ui-ngx/src/assets/locale/locale.constant-uk_UA.json +++ b/ui-ngx/src/assets/locale/locale.constant-uk_UA.json @@ -1978,8 +1978,7 @@ "metadata-required": "Записи метаданих не можуть бути порожніми.", "output": "Вихід", "test": "Тест", - "help": "Допомога", - "reset-debug-mode": "Вимкнути режим налагодження у всіх правилах" + "help": "Допомога" }, "scheduler": { "scheduler": "Планувальник", diff --git a/ui-ngx/src/assets/locale/locale.constant-zh_CN.json b/ui-ngx/src/assets/locale/locale.constant-zh_CN.json index f0dacca36d..47096fe5f2 100644 --- a/ui-ngx/src/assets/locale/locale.constant-zh_CN.json +++ b/ui-ngx/src/assets/locale/locale.constant-zh_CN.json @@ -4012,7 +4012,6 @@ "output": "输出", "test": "测试", "help": "帮助", - "reset-debug-mode": "重置所有节点中的调试模式", "test-with-this-message": "使用此消息进行{{test}}测试", "queue-hint": "选择一个队列将消息转发到另一个队列,默认情况下使用'Main'队列。", "queue-singleton-hint": "选择一个队列以在多实体中转发消息,默认情况下使用'Main'队列。" diff --git a/ui-ngx/src/assets/locale/locale.constant-zh_TW.json b/ui-ngx/src/assets/locale/locale.constant-zh_TW.json index a100d95fa4..64b4c71f16 100644 --- a/ui-ngx/src/assets/locale/locale.constant-zh_TW.json +++ b/ui-ngx/src/assets/locale/locale.constant-zh_TW.json @@ -2768,8 +2768,7 @@ "metadata-required": "元資料項不能為空。", "output": "輸出", "test": "測試", - "help": "幫助", - "reset-debug-mode": "重置所有節點中的調試模式" + "help": "幫助" }, "timezone": { "timezone": "時區", From 327455305d661baf6257926941f598ecee82a554 Mon Sep 17 00:00:00 2001 From: mpetrov Date: Fri, 6 Dec 2024 17:48:37 +0200 Subject: [PATCH 11/28] UI: Debug Settings fixes refactoring --- .../debug-settings/debug-settings-button.component.html | 4 ++-- .../debug-settings/debug-settings-panel.component.html | 4 ++-- .../home/pages/rulechain/rulechain-page.component.ts | 8 ++++---- .../app/shared/pipe/milliseconds-to-time-string.pipe.ts | 2 +- ui-ngx/src/assets/locale/locale.constant-lt_LT.json | 1 - ui-ngx/src/assets/locale/locale.constant-uk_UA.json | 3 ++- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/debug-settings/debug-settings-button.component.html b/ui-ngx/src/app/modules/home/components/debug-settings/debug-settings-button.component.html index d20fa2e90d..de765556e4 100644 --- a/ui-ngx/src/app/modules/home/components/debug-settings/debug-settings-button.component.html +++ b/ui-ngx/src/app/modules/home/components/debug-settings/debug-settings-button.component.html @@ -24,8 +24,8 @@ (click)="openDebugStrategyPanel($event, matButton)"> bug_report @if (isDebugAllActive$ | async) { - {{ !allEnabled() ? (allEnabledUntil | durationLeft) : (maxDebugModeDuration | milliSecondsToTimeString: true : true).trim() }} + {{ !allEnabled() ? (allEnabledUntil | durationLeft) : (maxDebugModeDuration | milliSecondsToTimeString: true : true) }} } @else { - {{ failuresEnabled ? ('debug-config.failures' | translate) : ('common.disabled' | translate) }} + {{ failuresEnabled ? 'debug-config.failures' : 'common.disabled' | translate }} } diff --git a/ui-ngx/src/app/modules/home/components/debug-settings/debug-settings-panel.component.html b/ui-ngx/src/app/modules/home/components/debug-settings/debug-settings-panel.component.html index f088fc38ac..d47ee69091 100644 --- a/ui-ngx/src/app/modules/home/components/debug-settings/debug-settings-panel.component.html +++ b/ui-ngx/src/app/modules/home/components/debug-settings/debug-settings-panel.component.html @@ -20,7 +20,7 @@
@if (debugLimitsConfiguration) { - {{ 'debug-config.hint.main-limited' | translate: { msg: maxMessagesCount, time: (maxTimeFrameDuration | milliSecondsToTimeString: true : true).trim() } }} + {{ 'debug-config.hint.main-limited' | translate: { msg: maxMessagesCount, time: (maxTimeFrameDuration | milliSecondsToTimeString: true : true) } }} } @else { {{ 'debug-config.hint.main' | translate }} } @@ -35,7 +35,7 @@
- {{ 'debug-config.all-messages' | translate: { time: (isDebugAllActive$ | async) && !allEnabled ? (allEnabledUntil | durationLeft) : (maxDebugModeDuration | milliSecondsToTimeString: true : true).trim() } }} + {{ 'debug-config.all-messages' | translate: { time: (isDebugAllActive$ | async) && !allEnabled ? (allEnabledUntil | durationLeft) : (maxDebugModeDuration | milliSecondsToTimeString: true : true) } }}
diff --git a/ui-ngx/src/app/modules/home/components/debug-settings/debug-settings-button.component.ts b/ui-ngx/src/app/modules/home/components/debug-settings/debug-settings-button.component.ts index 4db01892a2..8617d25de7 100644 --- a/ui-ngx/src/app/modules/home/components/debug-settings/debug-settings-button.component.ts +++ b/ui-ngx/src/app/modules/home/components/debug-settings/debug-settings-button.component.ts @@ -16,6 +16,7 @@ import { ChangeDetectionStrategy, + ChangeDetectorRef, Component, forwardRef, Input, @@ -94,6 +95,7 @@ export class DebugSettingsButtonComponent implements ControlValueAccessor { private store: Store, private viewContainerRef: ViewContainerRef, private fb: FormBuilder, + private cd : ChangeDetectorRef, ) { this.debugSettingsFormGroup.valueChanges.pipe( takeUntilDestroyed() @@ -136,6 +138,7 @@ export class DebugSettingsButtonComponent implements ControlValueAccessor { debugStrategyPopover.tbComponentRef.instance.popover = debugStrategyPopover; debugStrategyPopover.tbComponentRef.instance.onSettingsApplied.subscribe((settings: DebugSettings) => { this.debugSettingsFormGroup.patchValue(settings); + this.cd.markForCheck(); debugStrategyPopover.hide(); }); } From b5dd07153725f35d728c3bd538e3c31927a5ad86 Mon Sep 17 00:00:00 2001 From: kalytka Date: Fri, 6 Dec 2024 17:56:05 +0200 Subject: [PATCH 13/28] Refactoring --- ui-ngx/src/app/modules/home/components/public-api.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui-ngx/src/app/modules/home/components/public-api.ts b/ui-ngx/src/app/modules/home/components/public-api.ts index 6fa57fb4c4..9a320664da 100644 --- a/ui-ngx/src/app/modules/home/components/public-api.ts +++ b/ui-ngx/src/app/modules/home/components/public-api.ts @@ -19,8 +19,8 @@ export * from './widget/config/basic/basic-widget-config.module'; export * from './widget/lib/settings/common/widget-settings-common.module'; export * from './widget/widget-components.module'; export * from './widget/config/widget-config-components.module'; -export * from './widget/lib/chart/echarts-widget.models'; +export * from './widget/lib/chart/echarts-widget.models'; export * from './widget/config/widget-config.component.models'; export * from './widget/lib/table-widget.models'; export * from './widget/lib/flot-widget.models'; From 8e34cfefc89c1fe67cfe54a4e0cf9acbbbb394b2 Mon Sep 17 00:00:00 2001 From: mpetrov Date: Fri, 6 Dec 2024 18:44:21 +0200 Subject: [PATCH 14/28] UI: Added allEnabled = true on rule node copying if debug active --- ui-ngx/src/app/core/services/item-buffer.service.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ui-ngx/src/app/core/services/item-buffer.service.ts b/ui-ngx/src/app/core/services/item-buffer.service.ts index ff4211961a..c43d1ef35b 100644 --- a/ui-ngx/src/app/core/services/item-buffer.service.ts +++ b/ui-ngx/src/app/core/services/item-buffer.service.ts @@ -305,7 +305,11 @@ export class ItemBufferService { connectors: [], additionalInfo: origNode.additionalInfo, configuration: origNode.configuration, - debugSettings: origNode.debugSettings, + debugSettings: { + failuresEnabled: origNode.debugSettings?.failuresEnabled, + allEnabled: origNode.debugSettings?.allEnabled || origNode.debugSettings?.allEnabledUntil > new Date().getTime(), + allEnabledUntil: 0 + }, x: origNode.x, y: origNode.y, name: origNode.name, From 57df0395416e9ff2e5dd225a371f6cbd79aed8fb Mon Sep 17 00:00:00 2001 From: dashevchenko Date: Fri, 6 Dec 2024 19:03:30 +0200 Subject: [PATCH 15/28] fixed upgrade script for disabled android/ios configuration --- .../main/data/upgrade/basic/schema_update.sql | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/application/src/main/data/upgrade/basic/schema_update.sql b/application/src/main/data/upgrade/basic/schema_update.sql index ced110e65a..9aec87af00 100644 --- a/application/src/main/data/upgrade/basic/schema_update.sql +++ b/application/src/main/data/upgrade/basic/schema_update.sql @@ -143,7 +143,7 @@ $$ LOOP generatedBundleId := NULL; -- migrate android config - IF (qrCodeRecord.android_config IS NOT NULL AND qrCodeRecord.android_config::jsonb -> 'appPackage' IS NOT NULL) THEN + IF (qrCodeRecord.android_config::jsonb ->> 'appPackage' IS NOT NULL) THEN androidPkgName := qrCodeRecord.android_config::jsonb ->> 'appPackage'; SELECT id into androidAppId FROM mobile_app WHERE pkg_name = androidPkgName AND platform_type = 'ANDROID'; IF androidAppId IS NULL THEN @@ -154,17 +154,16 @@ $$ generatedBundleId := uuid_generate_v4(); INSERT INTO mobile_app_bundle(id, created_time, tenant_id, title, android_app_id) VALUES (generatedBundleId, (extract(epoch from now()) * 1000), qrCodeRecord.tenant_id, androidPkgName || ' (autogenerated)', androidAppId); - UPDATE qr_code_settings SET mobile_app_bundle_id = generatedBundleId, - android_enabled = (qrCodeRecord.android_config::jsonb ->> 'enabled')::boolean WHERE id = qrCodeRecord.id; + UPDATE qr_code_settings SET mobile_app_bundle_id = generatedBundleId; ELSE UPDATE mobile_app SET store_info = qrCodeRecord.android_config::jsonb - 'appPackage' - 'enabled' WHERE id = androidAppId; - UPDATE qr_code_settings SET mobile_app_bundle_id = (SELECT id FROM mobile_app_bundle WHERE mobile_app_bundle.android_app_id = androidAppId), - android_enabled = (qrCodeRecord.android_config::jsonb ->> 'enabled')::boolean WHERE id = qrCodeRecord.id; + UPDATE qr_code_settings SET mobile_app_bundle_id = (SELECT id FROM mobile_app_bundle WHERE mobile_app_bundle.android_app_id = androidAppId); END IF; END IF; + UPDATE qr_code_settings SET android_enabled = (qrCodeRecord.android_config::jsonb ->> 'enabled')::boolean WHERE id = qrCodeRecord.id; -- migrate ios config - IF (qrCodeRecord.ios_config IS NOT NULL AND qrCodeRecord.ios_config::jsonb -> 'appId' IS NOT NULL) THEN + IF (qrCodeRecord.ios_config::jsonb ->> 'appId' IS NOT NULL) THEN iosPkgName := substring(qrCodeRecord.ios_config::jsonb ->> 'appId', strpos(qrCodeRecord.ios_config::jsonb ->> 'appId', '.') + 1); SELECT id INTO iosAppId FROM mobile_app WHERE pkg_name = iosPkgName AND platform_type = 'IOS'; IF iosAppId IS NULL THEN @@ -176,17 +175,16 @@ $$ generatedBundleId := uuid_generate_v4(); INSERT INTO mobile_app_bundle(id, created_time, tenant_id, title, ios_app_id) VALUES (generatedBundleId, (extract(epoch from now()) * 1000), qrCodeRecord.tenant_id, iosPkgName || ' (autogenerated)', iosAppId); - UPDATE qr_code_settings SET mobile_app_bundle_id = generatedBundleId, - ios_enabled = (qrCodeRecord.ios_config::jsonb ->> 'enabled')::boolean WHERE id = qrCodeRecord.id; + UPDATE qr_code_settings SET mobile_app_bundle_id = generatedBundleId; ELSE UPDATE mobile_app_bundle SET ios_app_id = iosAppId WHERE id = generatedBundleId; END IF; ELSE - UPDATE qr_code_settings SET mobile_app_bundle_id = (SELECT id FROM mobile_app_bundle WHERE mobile_app_bundle.ios_app_id = iosAppId), - ios_enabled = (qrCodeRecord.ios_config::jsonb -> 'enabled')::boolean WHERE id = qrCodeRecord.id; + UPDATE qr_code_settings SET mobile_app_bundle_id = (SELECT id FROM mobile_app_bundle WHERE mobile_app_bundle.ios_app_id = iosAppId); UPDATE mobile_app SET store_info = qrCodeRecord.ios_config::jsonb - 'enabled' WHERE id = iosAppId; END IF; END IF; + UPDATE qr_code_settings SET ios_enabled = (qrCodeRecord.ios_config::jsonb -> 'enabled')::boolean WHERE id = qrCodeRecord.id; END LOOP; ALTER TABLE qr_code_settings RENAME CONSTRAINT mobile_app_settings_tenant_id_unq_key TO qr_code_settings_tenant_id_unq_key; ALTER TABLE qr_code_settings RENAME CONSTRAINT mobile_app_settings_pkey TO qr_code_settings_pkey; From 845f2099965b3d787fe19bfe3656fce9413151e9 Mon Sep 17 00:00:00 2001 From: Artem Dzhereleiko Date: Mon, 9 Dec 2024 10:36:51 +0200 Subject: [PATCH 16/28] UI: Refactoring no text option for extension --- .../resource-autocomplete.component.html | 25 ++++++++++++------- .../resource-autocomplete.component.ts | 2 ++ 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/ui-ngx/src/app/shared/components/resource/resource-autocomplete.component.html b/ui-ngx/src/app/shared/components/resource/resource-autocomplete.component.html index bcc566aeea..04e7a4dbc6 100644 --- a/ui-ngx/src/app/shared/components/resource/resource-autocomplete.component.html +++ b/ui-ngx/src/app/shared/components/resource/resource-autocomplete.component.html @@ -41,17 +41,24 @@ - -
-
- {{ 'js-func.no-js-module-text' | translate }} -
- + + +
+
+ {{ 'js-func.no-js-module-text' | translate }} +
+ {{ translate.get('js-func.no-js-module-matching', {module: searchText}) | async }} - -
-
+
+
+
+ + + + {{ searchText }} + + diff --git a/ui-ngx/src/app/shared/components/resource/resource-autocomplete.component.ts b/ui-ngx/src/app/shared/components/resource/resource-autocomplete.component.ts index b87cfe8c4f..1b5a541368 100644 --- a/ui-ngx/src/app/shared/components/resource/resource-autocomplete.component.ts +++ b/ui-ngx/src/app/shared/components/resource/resource-autocomplete.component.ts @@ -79,6 +79,8 @@ export class ResourceAutocompleteComponent implements ControlValueAccessor, OnIn @Input() subType = ResourceSubType.EXTENSION; + ResourceSubType = ResourceSubType; + resourceFormGroup = this.fb.group({ resource: this.fb.control(null) }); From 7d34e038de53e93e36af1b0bf7270aefb86eb501 Mon Sep 17 00:00:00 2001 From: Artem Dzhereleiko Date: Mon, 9 Dec 2024 10:53:20 +0200 Subject: [PATCH 17/28] UI: translate pipe and truncate --- .../components/resource/resource-autocomplete.component.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui-ngx/src/app/shared/components/resource/resource-autocomplete.component.html b/ui-ngx/src/app/shared/components/resource/resource-autocomplete.component.html index 04e7a4dbc6..513bee2808 100644 --- a/ui-ngx/src/app/shared/components/resource/resource-autocomplete.component.html +++ b/ui-ngx/src/app/shared/components/resource/resource-autocomplete.component.html @@ -49,7 +49,7 @@
- {{ translate.get('js-func.no-js-module-matching', {module: searchText}) | async }} + {{ 'js-func.no-js-module-matching' | translate: {module: searchText | truncate: true: 6: '...'} }}
From 928a34611ae00164a654d67f736671bf71ba0ddf Mon Sep 17 00:00:00 2001 From: Artem Dzhereleiko Date: Mon, 9 Dec 2024 10:57:24 +0200 Subject: [PATCH 18/28] UI: Refactoring --- .../components/resource/resource-autocomplete.component.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/ui-ngx/src/app/shared/components/resource/resource-autocomplete.component.ts b/ui-ngx/src/app/shared/components/resource/resource-autocomplete.component.ts index 1b5a541368..3aab98a394 100644 --- a/ui-ngx/src/app/shared/components/resource/resource-autocomplete.component.ts +++ b/ui-ngx/src/app/shared/components/resource/resource-autocomplete.component.ts @@ -33,7 +33,6 @@ import { TbResourceId } from '@shared/models/id/tb-resource-id'; import { ResourceService } from '@core/http/resource.service'; import { PageLink } from '@shared/models/page/page-link'; import { MatFormFieldAppearance, SubscriptSizing } from '@angular/material/form-field'; -import { TranslateService } from '@ngx-translate/core'; @Component({ selector: 'tb-resource-autocomplete', @@ -98,8 +97,7 @@ export class ResourceAutocompleteComponent implements ControlValueAccessor, OnIn private propagateChange: (value: any) => void = () => {}; constructor(private fb: FormBuilder, - private resourceService: ResourceService, - public translate: TranslateService) { + private resourceService: ResourceService) { } ngOnInit(): void { From 0083d92862d8d6b7ebe01a6993ddb9c8deb690b9 Mon Sep 17 00:00:00 2001 From: Vladyslav_Prykhodko Date: Mon, 9 Dec 2024 11:23:21 +0200 Subject: [PATCH 19/28] UI: Fixed relative urls in send email notification --- .../notification-template-configuration.component.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ui-ngx/src/app/modules/home/pages/notification/template/configuration/notification-template-configuration.component.ts b/ui-ngx/src/app/modules/home/pages/notification/template/configuration/notification-template-configuration.component.ts index 76cc84d905..31f66f5ea2 100644 --- a/ui-ngx/src/app/modules/home/pages/notification/template/configuration/notification-template-configuration.component.ts +++ b/ui-ngx/src/app/modules/home/pages/notification/template/configuration/notification-template-configuration.component.ts @@ -37,6 +37,7 @@ import { Subject } from 'rxjs'; import { deepClone, isDefinedAndNotNull } from '@core/utils'; import { coerceBoolean } from '@shared/decorators/coercion'; import { TranslateService } from '@ngx-translate/core'; +import { EditorOptions } from 'tinymce'; @Component({ selector: 'tb-template-configuration', @@ -81,7 +82,7 @@ export class NotificationTemplateConfigurationComponent implements OnDestroy, Co readonly NotificationDeliveryMethod = NotificationDeliveryMethod; readonly NotificationTemplateTypeTranslateMap = NotificationTemplateTypeTranslateMap; - tinyMceOptions: Record = { + tinyMceOptions: Partial = { base_url: '/assets/tinymce', suffix: '.min', plugins: ['link', 'table', 'image', 'lists', 'code', 'fullscreen'], @@ -93,7 +94,8 @@ export class NotificationTemplateConfigurationComponent implements OnDestroy, Co height: 400, autofocus: false, branding: false, - promotion: false + promotion: false, + relative_urls: false }; private propagateChange = null; From fcb32c29f912e2a62f3a01528c4de6a500b3feb2 Mon Sep 17 00:00:00 2001 From: Andrii Landiak Date: Mon, 9 Dec 2024 15:08:48 +0200 Subject: [PATCH 20/28] Fix migration from postgres to kafka for edge-events --- .../service/edge/rpc/EdgeGrpcService.java | 36 ++++++++++--------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcService.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcService.java index 71387aa542..2e9465fc9d 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcService.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcService.java @@ -413,23 +413,27 @@ public class EdgeGrpcService extends EdgeRpcServiceGrpc.EdgeRpcServiceImplBase i if (Boolean.TRUE.equals(sessionNewEvents.get(edgeId))) { log.trace("[{}][{}] Set session new events flag to false", tenantId, edgeId.getId()); sessionNewEvents.put(edgeId, false); - processEdgeEventMigrationIfNeeded(session, edgeId); session.processHighPriorityEvents(); - Futures.addCallback(session.processEdgeEvents(), new FutureCallback<>() { - @Override - public void onSuccess(Boolean newEventsAdded) { - if (Boolean.TRUE.equals(newEventsAdded)) { - sessionNewEvents.put(edgeId, true); + processEdgeEventMigrationIfNeeded(session, edgeId); + if (Boolean.TRUE.equals(edgeEventsMigrationProcessed.get(edgeId))) { + Futures.addCallback(session.processEdgeEvents(), new FutureCallback<>() { + @Override + public void onSuccess(Boolean newEventsAdded) { + if (Boolean.TRUE.equals(newEventsAdded)) { + sessionNewEvents.put(edgeId, true); + } + scheduleEdgeEventsCheck(session); + } + + @Override + public void onFailure(Throwable t) { + log.warn("[{}] Failed to process edge events for edge [{}]!", tenantId, session.getEdge().getId().getId(), t); + scheduleEdgeEventsCheck(session); } - scheduleEdgeEventsCheck(session); - } - - @Override - public void onFailure(Throwable t) { - log.warn("[{}] Failed to process edge events for edge [{}]!", tenantId, session.getEdge().getId().getId(), t); - scheduleEdgeEventsCheck(session); - } - }, ctx.getGrpcCallbackExecutorService()); + }, ctx.getGrpcCallbackExecutorService()); + } else { + scheduleEdgeEventsCheck(session); + } } else { scheduleEdgeEventsCheck(session); } @@ -457,8 +461,6 @@ public class EdgeGrpcService extends EdgeRpcServiceGrpc.EdgeRpcServiceImplBase i scheduleEdgeEventsCheck(session); } else if (Boolean.FALSE.equals(eventsExist)) { edgeEventsMigrationProcessed.put(edgeId, true); - } else { - scheduleEdgeEventsCheck(session); } } } From d2fdcb289c61455f7a29365980ac020c9da98a1b Mon Sep 17 00:00:00 2001 From: Artem Dzhereleiko Date: Mon, 9 Dec 2024 15:23:21 +0200 Subject: [PATCH 21/28] UI: Fixed dynamic sources for filters list --- .../components/filter/filter-predicate-list.component.html | 4 ++-- .../components/filter/filter-predicate-value.component.html | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/filter/filter-predicate-list.component.html b/ui-ngx/src/app/modules/home/components/filter/filter-predicate-list.component.html index 2e9f12da2b..b5d3489c95 100644 --- a/ui-ngx/src/app/modules/home/components/filter/filter-predicate-list.component.html +++ b/ui-ngx/src/app/modules/home/components/filter/filter-predicate-list.component.html @@ -40,13 +40,13 @@
-
{{ complexOperationTranslations.get(operation) | translate }}
-
+
{{ hintText | translate }}
-
+
From 6e019951cd5ed674d63c20fd6b3ee8cce6b7d58f Mon Sep 17 00:00:00 2001 From: mpetrov Date: Mon, 9 Dec 2024 16:00:43 +0200 Subject: [PATCH 22/28] UI: adjusted audit logs dialog codeblock height --- .../components/audit-log/audit-log-details-dialog.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui-ngx/src/app/modules/home/components/audit-log/audit-log-details-dialog.component.ts b/ui-ngx/src/app/modules/home/components/audit-log/audit-log-details-dialog.component.ts index 881961ed34..de405b0f0d 100644 --- a/ui-ngx/src/app/modules/home/components/audit-log/audit-log-details-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/audit-log/audit-log-details-dialog.component.ts @@ -105,7 +105,7 @@ export class AuditLogDetailsDialogComponent extends DialogComponent 0) { const lines = content.split('\n'); - newHeight = 17 * lines.length + 16; + newHeight = 18 * lines.length + 16; let maxLineLength = 0; lines.forEach((row) => { const line = row.replace(/\t/g, ' ').replace(/\n/g, ''); From d68342d883fe812e327a98960372ae44a4430143 Mon Sep 17 00:00:00 2001 From: Artem Dzhereleiko Date: Mon, 9 Dec 2024 16:44:00 +0200 Subject: [PATCH 23/28] UI: Refactoring inline style --- .../components/filter/filter-predicate-list.component.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/filter/filter-predicate-list.component.html b/ui-ngx/src/app/modules/home/components/filter/filter-predicate-list.component.html index b5d3489c95..439480d5ed 100644 --- a/ui-ngx/src/app/modules/home/components/filter/filter-predicate-list.component.html +++ b/ui-ngx/src/app/modules/home/components/filter/filter-predicate-list.component.html @@ -40,13 +40,13 @@
-
{{ complexOperationTranslations.get(operation) | translate }}
-
+
Date: Mon, 9 Dec 2024 17:03:55 +0200 Subject: [PATCH 24/28] Timewindow: fix applying invalid grouping interval when list of allowed intervals set --- .../src/app/shared/components/time/timeinterval.component.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ui-ngx/src/app/shared/components/time/timeinterval.component.ts b/ui-ngx/src/app/shared/components/time/timeinterval.component.ts index a7229660d5..689e42c747 100644 --- a/ui-ngx/src/app/shared/components/time/timeinterval.component.ts +++ b/ui-ngx/src/app/shared/components/time/timeinterval.component.ts @@ -191,8 +191,7 @@ export class TimeintervalComponent implements OnInit, ControlValueAccessor, OnCh if (typeof this.modelValue !== 'undefined') { const min = this.timeService.boundMinInterval(this.minValue); const max = this.timeService.boundMaxInterval(this.maxValue); - if (this.allowedIntervals?.length || - IntervalMath.numberValue(this.modelValue) >= min && IntervalMath.numberValue(this.modelValue) <= max) { + if (IntervalMath.numberValue(this.modelValue) >= min && IntervalMath.numberValue(this.modelValue) <= max) { const advanced = this.allowedIntervals?.length ? !this.allowedIntervals.includes(this.modelValue) : !this.timeService.matchesExistingInterval(this.minValue, this.maxValue, this.modelValue, From 910e0cabb88c6eacf726d71fdc2c9d914e691e75 Mon Sep 17 00:00:00 2001 From: Artem Dzhereleiko Date: Mon, 9 Dec 2024 17:20:42 +0200 Subject: [PATCH 25/28] UI: Refactoring --- .../components/filter/filter-predicate-list.component.html | 4 ++-- ui-ngx/tailwind.config.js | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/filter/filter-predicate-list.component.html b/ui-ngx/src/app/modules/home/components/filter/filter-predicate-list.component.html index 439480d5ed..93fd973753 100644 --- a/ui-ngx/src/app/modules/home/components/filter/filter-predicate-list.component.html +++ b/ui-ngx/src/app/modules/home/components/filter/filter-predicate-list.component.html @@ -40,13 +40,13 @@
-
{{ complexOperationTranslations.get(operation) | translate }}
-
+
Date: Mon, 9 Dec 2024 17:25:29 +0200 Subject: [PATCH 26/28] UI: Refactoring --- .../home/components/filter/filter-predicate-list.component.html | 2 +- ui-ngx/tailwind.config.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/filter/filter-predicate-list.component.html b/ui-ngx/src/app/modules/home/components/filter/filter-predicate-list.component.html index 93fd973753..7285c41a9d 100644 --- a/ui-ngx/src/app/modules/home/components/filter/filter-predicate-list.component.html +++ b/ui-ngx/src/app/modules/home/components/filter/filter-predicate-list.component.html @@ -46,7 +46,7 @@
{{ complexOperationTranslations.get(operation) | translate }}
-
+
Date: Mon, 9 Dec 2024 17:26:25 +0200 Subject: [PATCH 27/28] UI: Refactoring --- .../home/components/filter/filter-predicate-list.component.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui-ngx/src/app/modules/home/components/filter/filter-predicate-list.component.html b/ui-ngx/src/app/modules/home/components/filter/filter-predicate-list.component.html index 7285c41a9d..fd1cf2ea27 100644 --- a/ui-ngx/src/app/modules/home/components/filter/filter-predicate-list.component.html +++ b/ui-ngx/src/app/modules/home/components/filter/filter-predicate-list.component.html @@ -46,7 +46,7 @@
{{ complexOperationTranslations.get(operation) | translate }}
-
+
Date: Mon, 9 Dec 2024 18:25:14 +0200 Subject: [PATCH 28/28] Update locale.constant-en_US.json --- ui-ngx/src/assets/locale/locale.constant-en_US.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 6b50deb6ab..362df078ab 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -3333,8 +3333,8 @@ "module-load-error": "Module load error", "source-code": "Source code", "source-code-load-error": "Source code load error", - "no-js-module-text": "No JS module found", - "no-js-module-matching": "No JS module matching '{{module}}' were found." + "no-js-module-text": "No JS modules found", + "no-js-module-matching": "No JS modules matching '{{module}}' were found." }, "key-val": { "key": "Key",