From 9788a87ca38db8d7233520dcdb87bfa5e1158936 Mon Sep 17 00:00:00 2001 From: ViacheslavKlimov Date: Wed, 4 Oct 2023 16:54:19 +0300 Subject: [PATCH 1/2] Fix notification requests deletion test; drop all notifications after test --- .../service/notification/AbstractNotificationApiTest.java | 4 ++++ .../server/service/notification/NotificationApiTest.java | 5 +++-- .../server/service/notification/NotificationRuleApiTest.java | 4 +--- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/application/src/test/java/org/thingsboard/server/service/notification/AbstractNotificationApiTest.java b/application/src/test/java/org/thingsboard/server/service/notification/AbstractNotificationApiTest.java index 104b5afef4..27a0eed1a4 100644 --- a/application/src/test/java/org/thingsboard/server/service/notification/AbstractNotificationApiTest.java +++ b/application/src/test/java/org/thingsboard/server/service/notification/AbstractNotificationApiTest.java @@ -61,6 +61,7 @@ import org.thingsboard.server.dao.notification.NotificationRequestService; import org.thingsboard.server.dao.notification.NotificationRuleService; import org.thingsboard.server.dao.notification.NotificationTargetService; import org.thingsboard.server.dao.notification.NotificationTemplateService; +import org.thingsboard.server.dao.sqlts.insert.sql.SqlPartitioningRepository; import java.net.URISyntaxException; import java.util.Arrays; @@ -90,6 +91,8 @@ public abstract class AbstractNotificationApiTest extends AbstractControllerTest protected NotificationTargetService notificationTargetService; @Autowired protected NotificationRequestService notificationRequestService; + @Autowired + protected SqlPartitioningRepository partitioningRepository; public static final String DEFAULT_NOTIFICATION_SUBJECT = "Just a test"; public static final NotificationType DEFAULT_NOTIFICATION_TYPE = NotificationType.GENERAL; @@ -100,6 +103,7 @@ public abstract class AbstractNotificationApiTest extends AbstractControllerTest notificationRuleService.deleteNotificationRulesByTenantId(TenantId.SYS_TENANT_ID); notificationTemplateService.deleteNotificationTemplatesByTenantId(TenantId.SYS_TENANT_ID); notificationTargetService.deleteNotificationTargetsByTenantId(TenantId.SYS_TENANT_ID); + partitioningRepository.dropPartitionsBefore("notification", Long.MAX_VALUE, 1); } protected NotificationTarget createNotificationTarget(UserId... usersIds) { diff --git a/application/src/test/java/org/thingsboard/server/service/notification/NotificationApiTest.java b/application/src/test/java/org/thingsboard/server/service/notification/NotificationApiTest.java index 21d29833b9..26be4e9bd3 100644 --- a/application/src/test/java/org/thingsboard/server/service/notification/NotificationApiTest.java +++ b/application/src/test/java/org/thingsboard/server/service/notification/NotificationApiTest.java @@ -286,18 +286,19 @@ public class NotificationApiTest extends AbstractNotificationApiTest { @Test public void whenTenantIsDeleted_thenDeleteNotificationRequests() throws Exception { createDifferentTenant(); + TenantId tenantId = differentTenantId; NotificationTarget target = createNotificationTarget(savedDifferentTenantUser.getId()); int notificationsCount = 20; for (int i = 0; i < notificationsCount; i++) { NotificationRequest request = submitNotificationRequest(target.getId(), "Test " + i, NotificationDeliveryMethod.WEB); awaitNotificationRequest(request.getId()); } - List requests = notificationRequestService.findNotificationRequestsByTenantIdAndOriginatorType(differentTenantId, EntityType.USER, new PageLink(100)).getData(); + List requests = notificationRequestService.findNotificationRequestsByTenantIdAndOriginatorType(tenantId, EntityType.USER, new PageLink(100)).getData(); assertThat(requests).size().isEqualTo(notificationsCount); deleteDifferentTenant(); - assertThat(notificationRequestService.findNotificationRequestsByTenantIdAndOriginatorType(differentTenantId, EntityType.USER, new PageLink(1)).getTotalElements()) + assertThat(notificationRequestService.findNotificationRequestsByTenantIdAndOriginatorType(tenantId, EntityType.USER, new PageLink(1)).getTotalElements()) .isZero(); } diff --git a/application/src/test/java/org/thingsboard/server/service/notification/NotificationRuleApiTest.java b/application/src/test/java/org/thingsboard/server/service/notification/NotificationRuleApiTest.java index d08b1a121b..0a2854a28d 100644 --- a/application/src/test/java/org/thingsboard/server/service/notification/NotificationRuleApiTest.java +++ b/application/src/test/java/org/thingsboard/server/service/notification/NotificationRuleApiTest.java @@ -456,9 +456,7 @@ public class NotificationRuleApiTest extends AbstractNotificationApiTest { loginSysAdmin(); notifications = await().atMost(30, TimeUnit.SECONDS) - .until(() -> getMyNotifications(true, 10).stream() - .filter(notification -> notification.getType() == NotificationType.RATE_LIMITS) - .collect(Collectors.toList()), list -> list.size() == 1); + .until(() -> getMyNotifications(true, 10), list -> list.size() == 1); assertThat(notifications).allSatisfy(notification -> { assertThat(notification.getSubject()).isEqualTo("Rate limits exceeded for tenant " + TEST_TENANT_NAME); }); From 2492b81d3403d5de852c2eba7e0c93522db9ce78 Mon Sep 17 00:00:00 2001 From: Igor Kulikov Date: Thu, 5 Oct 2023 17:52:49 +0300 Subject: [PATCH 2/2] UI: Wind speed and direction widget. --- .../widget_bundles/weather_widgets.json | 13 + .../wind_speed_and_direction.json | 29 ++ .../DefaultSystemDataLoaderService.java | 1 + .../sql/widget/WidgetTypeInfoRepository.java | 2 +- ui-ngx/package.json | 1 + ui-ngx/src/app/core/utils.ts | 4 +- .../basic/basic-widget-config.module.ts | 12 +- .../basic/common/data-key-row.component.html | 37 +- .../basic/common/data-key-row.component.scss | 25 ++ .../basic/common/data-key-row.component.ts | 138 +++++--- .../common/data-keys-panel.component.html | 9 + .../basic/common/data-keys-panel.component.ts | 17 - ...peed-direction-basic-config.component.html | 213 +++++++++++ ...-speed-direction-basic-config.component.ts | 291 +++++++++++++++ .../battery-level-widget.component.html | 4 +- .../battery-level-widget.component.scss | 214 ++++++----- .../battery-level-widget.component.ts | 6 +- ...d-direction-widget-settings.component.html | 102 ++++++ ...eed-direction-widget-settings.component.ts | 139 ++++++++ .../lib/settings/widget-settings.module.ts | 12 +- ...wind-speed-direction-widget.component.html | 25 ++ ...wind-speed-direction-widget.component.scss | 49 +++ .../wind-speed-direction-widget.component.ts | 333 ++++++++++++++++++ .../wind-speed-direction-widget.models.ts | 108 ++++++ .../widget/widget-components.module.ts | 9 +- .../shared/models/widget-settings.models.ts | 41 +++ .../assets/locale/locale.constant-en_US.json | 21 ++ .../wind-speed-direction/advanced-layout.svg | 187 ++++++++++ .../wind-speed-direction/default-layout.svg | 167 +++++++++ .../simplified-layout.svg | 153 ++++++++ ui-ngx/src/form.scss | 12 +- ui-ngx/yarn.lock | 5 + 32 files changed, 2167 insertions(+), 212 deletions(-) create mode 100644 application/src/main/data/json/system/widget_bundles/weather_widgets.json create mode 100644 application/src/main/data/json/system/widget_types/wind_speed_and_direction.json create mode 100644 ui-ngx/src/app/modules/home/components/widget/config/basic/weather/wind-speed-direction-basic-config.component.html create mode 100644 ui-ngx/src/app/modules/home/components/widget/config/basic/weather/wind-speed-direction-basic-config.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/widget/lib/settings/weather/wind-speed-direction-widget-settings.component.html create mode 100644 ui-ngx/src/app/modules/home/components/widget/lib/settings/weather/wind-speed-direction-widget-settings.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/widget/lib/weather/wind-speed-direction-widget.component.html create mode 100644 ui-ngx/src/app/modules/home/components/widget/lib/weather/wind-speed-direction-widget.component.scss create mode 100644 ui-ngx/src/app/modules/home/components/widget/lib/weather/wind-speed-direction-widget.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/widget/lib/weather/wind-speed-direction-widget.models.ts create mode 100644 ui-ngx/src/assets/widget/wind-speed-direction/advanced-layout.svg create mode 100644 ui-ngx/src/assets/widget/wind-speed-direction/default-layout.svg create mode 100644 ui-ngx/src/assets/widget/wind-speed-direction/simplified-layout.svg diff --git a/application/src/main/data/json/system/widget_bundles/weather_widgets.json b/application/src/main/data/json/system/widget_bundles/weather_widgets.json new file mode 100644 index 0000000000..a38c139cf0 --- /dev/null +++ b/application/src/main/data/json/system/widget_bundles/weather_widgets.json @@ -0,0 +1,13 @@ +{ + "widgetsBundle": { + "alias": "weather_widgets", + "title": "Weather widgets", + "image": null, + "description": null, + "externalId": null, + "name": "Weather widgets" + }, + "widgetTypeFqns": [ + "wind_speed_and_direction" + ] +} \ No newline at end of file diff --git a/application/src/main/data/json/system/widget_types/wind_speed_and_direction.json b/application/src/main/data/json/system/widget_types/wind_speed_and_direction.json new file mode 100644 index 0000000000..1c4f7ecb7c --- /dev/null +++ b/application/src/main/data/json/system/widget_types/wind_speed_and_direction.json @@ -0,0 +1,29 @@ +{ + "fqn": "wind_speed_and_direction", + "name": "Wind speed and direction", + "deprecated": false, + "image": "data:image/png;base64,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", + "description": "Displays the latest values of the wind speed and direction.", + "descriptor": { + "type": "latest", + "sizeX": 3, + "sizeY": 3, + "resources": [], + "templateHtml": "\n", + "templateCss": "", + "controllerScript": "self.onInit = function() {\n self.ctx.$scope.windSpeedDirectionWidget.onInit();\n};\n\nself.onDataUpdated = function() {\n self.ctx.$scope.windSpeedDirectionWidget.onDataUpdated();\n};\n\nself.typeParameters = function() {\n return {\n maxDatasources: 1,\n maxDataKeys: 2,\n singleEntity: true,\n previewWidth: '270px',\n previewHeight: '270px',\n embedTitlePanel: true\n };\n};\n\nself.actionSources = function() {\n return {\n 'cardClick': {\n name: 'widget-action.card-click',\n multiple: false\n }\n };\n}\n\nself.onDestroy = function() {\n};\n", + "settingsSchema": "", + "dataKeySettingsSchema": "", + "settingsDirective": "tb-wind-speed-direction-widget-settings", + "hasBasicMode": true, + "basicModeDirective": "tb-wind-speed-direction-basic-config", + "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"windDirection\",\"color\":\"#4caf50\",\"settings\":{},\"_hash\":0.7227918773301678,\"funcBody\":\"if (prevValue === 0) {\\n prevValue = Math.random() * 360;\\n}\\nvar value = prevValue + Math.random() * 20 - 10;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 360) {\\n\\tvalue = 360;\\n}\\nreturn value;\",\"aggregationType\":null,\"units\":null,\"decimals\":null,\"usePostProcessing\":null,\"postFuncBody\":null},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"centerValue\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.2392660816082064,\"funcBody\":\"var value = prevValue + Math.random() * 7;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 30) {\\n\\tvalue = 0;\\n}\\nreturn value;\",\"aggregationType\":null,\"units\":\"m/s\",\"decimals\":1,\"usePostProcessing\":null,\"postFuncBody\":null}],\"alarmFilterConfig\":{\"statusList\":[\"ACTIVE\"]}}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":false,\"backgroundColor\":\"rgba(0, 0, 0, 0)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"layout\":\"default\",\"centerValueFont\":{\"family\":\"Roboto\",\"size\":24,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"500\",\"lineHeight\":\"32px\"},\"centerValueColor\":{\"type\":\"constant\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"colorFunction\":\"var temperature = value;\\nif (typeof temperature !== undefined) {\\n var percent = (temperature + 60)/120 * 100;\\n return tinycolor.mix('blue', 'red', percent).toHexString();\\n}\\nreturn 'blue';\"},\"ticksColor\":\"rgba(0, 0, 0, 0.12)\",\"directionalNamesElseDegrees\":true,\"majorTicksFont\":{\"family\":\"Roboto\",\"size\":14,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"500\",\"lineHeight\":\"20px\"},\"majorTicksColor\":\"rgba(158, 158, 158, 1)\",\"minorTicksFont\":{\"family\":\"Roboto\",\"size\":14,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"500\",\"lineHeight\":\"20px\"},\"minorTicksColor\":\"rgba(0, 0, 0, 0.12)\",\"arrowColor\":\"rgba(0, 0, 0, 0.87)\",\"background\":{\"type\":\"color\",\"color\":\"#fff\",\"overlay\":{\"enabled\":false,\"color\":\"rgba(255,255,255,0.72)\",\"blur\":3}}},\"title\":\"Wind speed and direction\",\"dropShadow\":true,\"enableFullscreen\":false,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"units\":\"\",\"decimals\":0,\"useDashboardTimewindow\":true,\"showLegend\":false,\"widgetStyle\":{},\"actions\":{\"headerButton\":[]},\"configMode\":\"basic\",\"displayTimewindow\":true,\"margin\":\"0px\",\"borderRadius\":\"0px\",\"widgetCss\":\"\",\"pageSize\":1024,\"noDataDisplayMessage\":\"\",\"showTitleIcon\":false,\"titleTooltip\":\"\",\"titleFont\":{\"size\":16,\"sizeUnit\":\"px\",\"family\":\"Roboto\",\"weight\":\"500\",\"style\":\"normal\",\"lineHeight\":\"24px\"},\"titleIcon\":\"air\",\"iconColor\":\"rgba(0, 0, 0, 0.87)\",\"iconSize\":\"24px\",\"timewindowStyle\":{\"showIcon\":true,\"iconSize\":\"14px\",\"icon\":\"query_builder\",\"iconPosition\":\"left\",\"font\":{\"size\":12,\"sizeUnit\":\"px\",\"family\":null,\"weight\":null,\"style\":null,\"lineHeight\":\"1\"},\"color\":null},\"titleColor\":\"rgba(0, 0, 0, 0.87)\"}" + }, + "externalId": null, + "tags": [ + "wind", + "weather", + "compass", + "degrees" + ] +} \ No newline at end of file diff --git a/application/src/main/java/org/thingsboard/server/service/install/DefaultSystemDataLoaderService.java b/application/src/main/java/org/thingsboard/server/service/install/DefaultSystemDataLoaderService.java index 29dcd601a1..a40913a281 100644 --- a/application/src/main/java/org/thingsboard/server/service/install/DefaultSystemDataLoaderService.java +++ b/application/src/main/java/org/thingsboard/server/service/install/DefaultSystemDataLoaderService.java @@ -532,6 +532,7 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService { this.deleteSystemWidgetBundle("html_widgets"); this.deleteSystemWidgetBundle("tables"); this.deleteSystemWidgetBundle("count_widgets"); + this.deleteSystemWidgetBundle("weather_widgets"); installScripts.loadSystemWidgets(); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/widget/WidgetTypeInfoRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/widget/WidgetTypeInfoRepository.java index 27f4ef918f..f3f3bf5139 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/widget/WidgetTypeInfoRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/widget/WidgetTypeInfoRepository.java @@ -37,7 +37,7 @@ public interface WidgetTypeInfoRepository extends JpaRepository { - if (dataKey.label === label) { + if (dataKey?.label === label) { i++; label = name + ' ' + i; matches = true; @@ -777,7 +777,7 @@ export function genNextLabel(name: string, datasources: Datasource[]): string { } if (datasource.latestDataKeys) { datasource.latestDataKeys.forEach((dataKey) => { - if (dataKey.label === label) { + if (dataKey?.label === label) { i++; label = name + ' ' + i; matches = true; diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/basic-widget-config.module.ts b/ui-ngx/src/app/modules/home/components/widget/config/basic/basic-widget-config.module.ts index 41115904b3..3cc2eddb7d 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/basic-widget-config.module.ts +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/basic-widget-config.module.ts @@ -58,6 +58,9 @@ import { import { BatteryLevelBasicConfigComponent } from '@home/components/widget/config/basic/indicator/battery-level-basic-config.component'; +import { + WindSpeedDirectionBasicConfigComponent +} from '@home/components/widget/config/basic/weather/wind-speed-direction-basic-config.component'; @NgModule({ declarations: [ @@ -75,7 +78,8 @@ import { DataKeysPanelComponent, AlarmCountBasicConfigComponent, EntityCountBasicConfigComponent, - BatteryLevelBasicConfigComponent + BatteryLevelBasicConfigComponent, + WindSpeedDirectionBasicConfigComponent ], imports: [ CommonModule, @@ -97,7 +101,8 @@ import { DataKeysPanelComponent, AlarmCountBasicConfigComponent, EntityCountBasicConfigComponent, - BatteryLevelBasicConfigComponent + BatteryLevelBasicConfigComponent, + WindSpeedDirectionBasicConfigComponent ] }) export class BasicWidgetConfigModule { @@ -113,5 +118,6 @@ export const basicWidgetConfigComponentsMap: {[key: string]: Type -
+
{{ 'datakey.timeseries' | translate }} @@ -23,8 +23,8 @@ - - +
@@ -67,8 +67,8 @@ #keyInput [formControl]="keyFormControl" matAutocompleteOrigin - [fxHide]="!!modelValue.type" - [readonly]="!!modelValue.type" + [fxHide]="!!modelValue?.type" + [readonly]="!!modelValue?.type" #origin="matAutocompleteOrigin" [matAutocompleteConnectedTo]="origin" (focusin)="onKeyInputFocus()" @@ -139,7 +139,7 @@ - +
@@ -147,25 +147,28 @@ formControlName="color">
-
+
-
+
+
widget-config.decimals-suffix
-
- +
+
+ +