From 449296a6040d6782454cb214345b9a035a6c0863 Mon Sep 17 00:00:00 2001 From: Igor Kulikov Date: Tue, 31 Oct 2023 10:30:55 +0200 Subject: [PATCH] Implement widgets bundles ordering. --- .../main/data/upgrade/3.6.0/schema_update.sql | 3 ++ .../WidgetsBundleMsgConstructor.java | 3 ++ .../common/data/widget/WidgetsBundle.java | 6 +++ common/edge-api/src/main/proto/edge.proto | 3 +- .../server/dao/model/ModelConstants.java | 1 + .../dao/model/sql/WidgetsBundleEntity.java | 5 ++ .../sql/widget/WidgetsBundleRepository.java | 3 +- .../main/resources/sql/schema-entities.sql | 1 + .../sql/widget/JpaWidgetsBundleDaoTest.java | 54 +++++++++++++------ .../widget/widgets-bundle.component.html | 4 ++ .../pages/widget/widgets-bundle.component.ts | 6 ++- .../app/shared/models/widgets-bundle.model.ts | 1 + .../assets/locale/locale.constant-en_US.json | 1 + 13 files changed, 70 insertions(+), 21 deletions(-) diff --git a/application/src/main/data/upgrade/3.6.0/schema_update.sql b/application/src/main/data/upgrade/3.6.0/schema_update.sql index 0361a5db65..b0a64268ef 100644 --- a/application/src/main/data/upgrade/3.6.0/schema_update.sql +++ b/application/src/main/data/upgrade/3.6.0/schema_update.sql @@ -17,6 +17,9 @@ ALTER TABLE widget_type ADD COLUMN IF NOT EXISTS tags text[]; +ALTER TABLE widgets_bundle + ADD COLUMN IF NOT EXISTS widgets_bundle_order int; + ALTER TABLE api_usage_state ADD COLUMN IF NOT EXISTS tbel_exec varchar(32); UPDATE api_usage_state SET tbel_exec = js_exec WHERE tbel_exec IS NULL; diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/WidgetsBundleMsgConstructor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/WidgetsBundleMsgConstructor.java index bed83c8832..5b615ca9f8 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/WidgetsBundleMsgConstructor.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/WidgetsBundleMsgConstructor.java @@ -45,6 +45,9 @@ public class WidgetsBundleMsgConstructor { if (widgetsBundle.getDescription() != null) { builder.setDescription(widgetsBundle.getDescription()); } + if (widgetsBundle.getOrder() != null) { + builder.setOrder(widgetsBundle.getOrder()); + } if (widgetsBundle.getTenantId().equals(TenantId.SYS_TENANT_ID)) { builder.setIsSystem(true); } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/widget/WidgetsBundle.java b/common/data/src/main/java/org/thingsboard/server/common/data/widget/WidgetsBundle.java index 3655eace53..9096207abe 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/widget/WidgetsBundle.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/widget/WidgetsBundle.java @@ -70,6 +70,11 @@ public class WidgetsBundle extends BaseData implements HasName, @ApiModelProperty(position = 7, value = "Description", accessMode = ApiModelProperty.AccessMode.READ_ONLY) private String description; + @Getter + @Setter + @ApiModelProperty(position = 8, value = "Order", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + private Integer order; + @Getter @Setter private WidgetsBundleId externalId; @@ -89,6 +94,7 @@ public class WidgetsBundle extends BaseData implements HasName, this.title = widgetsBundle.getTitle(); this.image = widgetsBundle.getImage(); this.description = widgetsBundle.getDescription(); + this.order = widgetsBundle.getOrder(); this.externalId = widgetsBundle.getExternalId(); } diff --git a/common/edge-api/src/main/proto/edge.proto b/common/edge-api/src/main/proto/edge.proto index bc0170b24b..29a82446a5 100644 --- a/common/edge-api/src/main/proto/edge.proto +++ b/common/edge-api/src/main/proto/edge.proto @@ -361,7 +361,8 @@ message WidgetsBundleUpdateMsg { optional bytes image = 6; bool isSystem = 7; optional string description = 8; - optional string widgets = 9; + optional int32 order = 9; + optional string widgets = 10; } message WidgetTypeUpdateMsg { diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java b/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java index 527cbb8957..10dc226e7a 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java @@ -302,6 +302,7 @@ public class ModelConstants { public static final String WIDGETS_BUNDLE_TITLE_PROPERTY = TITLE_PROPERTY; public static final String WIDGETS_BUNDLE_IMAGE_PROPERTY = "image"; public static final String WIDGETS_BUNDLE_DESCRIPTION = "description"; + public static final String WIDGETS_BUNDLE_ORDER = "widgets_bundle_order"; /** * Widget_type constants. diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/WidgetsBundleEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/WidgetsBundleEntity.java index fedfa1471d..baa1140803 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/WidgetsBundleEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/WidgetsBundleEntity.java @@ -50,6 +50,9 @@ public final class WidgetsBundleEntity extends BaseSqlEntity { @Column(name = ModelConstants.WIDGETS_BUNDLE_DESCRIPTION) private String description; + @Column(name = ModelConstants.WIDGETS_BUNDLE_ORDER) + private Integer order; + @Column(name = ModelConstants.EXTERNAL_ID_PROPERTY) private UUID externalId; @@ -69,6 +72,7 @@ public final class WidgetsBundleEntity extends BaseSqlEntity { this.title = widgetsBundle.getTitle(); this.image = widgetsBundle.getImage(); this.description = widgetsBundle.getDescription(); + this.order = widgetsBundle.getOrder(); if (widgetsBundle.getExternalId() != null) { this.externalId = widgetsBundle.getExternalId().getId(); } @@ -85,6 +89,7 @@ public final class WidgetsBundleEntity extends BaseSqlEntity { widgetsBundle.setTitle(title); widgetsBundle.setImage(image); widgetsBundle.setDescription(description); + widgetsBundle.setOrder(order); if (externalId != null) { widgetsBundle.setExternalId(new WidgetsBundleId(externalId)); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/widget/WidgetsBundleRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/widget/WidgetsBundleRepository.java index 08b0a00383..9db39aab8f 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/widget/WidgetsBundleRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/widget/WidgetsBundleRepository.java @@ -105,7 +105,8 @@ public interface WidgetsBundleRepository extends JpaRepository(); } + @Test + public void testOrderInFindAllWidgetsBundlesByTenantIdFullSearch() { + UUID tenantId1 = Uuids.timeBased(); + for (int i = 0; i < 10; i++) { + createWidgetsBundle(TenantId.fromUUID(tenantId1), "WB1_" + i, "WB1_" + (10-i), i % 2 == 1 ? null : (int)(Math.random() * 1000)); + createWidgetsBundle(TenantId.SYS_TENANT_ID, "WB_SYS_" + i, "WB_SYS_" + (10-i), i % 2 == 0 ? null : (int)(Math.random() * 1000)); + } + widgetsBundles = widgetsBundleDao.find(TenantId.SYS_TENANT_ID).stream().sorted((o1, o2) -> { + int result = 0; + if (o1.getOrder() != null && o2.getOrder() != null) { + result = o1.getOrder() - o2.getOrder(); + } else if (o1.getOrder() == null && o2.getOrder() != null) { + result = 1; + } else if (o1.getOrder() != null) { + result = -1; + } + if (result == 0) { + result = o1.getTitle().compareTo(o2.getTitle()); + } + return result; + }).collect(Collectors.toList());; + assertEquals(20, widgetsBundles.size()); + PageLink pageLink = new PageLink(100, 0, "", new SortOrder("title")); + PageData widgetsBundlesData = widgetsBundleDao.findAllTenantWidgetsBundlesByTenantId(tenantId1, true, pageLink); + assertEquals(20, widgetsBundlesData.getData().size()); + assertEquals(widgetsBundles, widgetsBundlesData.getData()); + } + @Test public void testSearchTextNotFound() { UUID tenantId = Uuids.timeBased(); @@ -372,32 +397,27 @@ public class JpaWidgetsBundleDaoTest extends AbstractJpaDaoTest { private void createWidgetBundles(int count, UUID tenantId, String prefix) { for (int i = 0; i < count; i++) { - WidgetsBundle widgetsBundle = new WidgetsBundle(); - widgetsBundle.setAlias(prefix + i); - widgetsBundle.setTitle(prefix + i); - widgetsBundle.setId(new WidgetsBundleId(Uuids.timeBased())); - widgetsBundle.setTenantId(TenantId.fromUUID(tenantId)); - widgetsBundleDao.save(TenantId.SYS_TENANT_ID, widgetsBundle); + createWidgetsBundle(TenantId.fromUUID(tenantId), prefix + i, prefix + i, null); } } private void createSystemWidgetBundles(int count, String prefix) { for (int i = 0; i < count; i++) { - WidgetsBundle widgetsBundle = new WidgetsBundle(); - widgetsBundle.setAlias(prefix + i); - widgetsBundle.setTitle(prefix + i); - widgetsBundle.setTenantId(TenantId.SYS_TENANT_ID); - widgetsBundle.setId(new WidgetsBundleId(Uuids.timeBased())); - widgetsBundleDao.save(TenantId.SYS_TENANT_ID, widgetsBundle); + createWidgetsBundle(TenantId.SYS_TENANT_ID, prefix + i, prefix + i, null); } } private WidgetsBundle createSystemWidgetBundle(String alias, String title) { + return createWidgetsBundle(TenantId.SYS_TENANT_ID, alias, title, null); + } + + private WidgetsBundle createWidgetsBundle(TenantId tenantId, String alias, String title, Integer order) { WidgetsBundle widgetsBundle = new WidgetsBundle(); widgetsBundle.setAlias(alias); widgetsBundle.setTitle(title); - widgetsBundle.setTenantId(TenantId.SYS_TENANT_ID); + widgetsBundle.setTenantId(tenantId); widgetsBundle.setId(new WidgetsBundleId(Uuids.timeBased())); + widgetsBundle.setOrder(order); return widgetsBundleDao.save(TenantId.SYS_TENANT_ID, widgetsBundle); } diff --git a/ui-ngx/src/app/modules/home/pages/widget/widgets-bundle.component.html b/ui-ngx/src/app/modules/home/pages/widget/widgets-bundle.component.html index bfc61fb98c..fcebcc1e6c 100644 --- a/ui-ngx/src/app/modules/home/pages/widget/widgets-bundle.component.html +++ b/ui-ngx/src/app/modules/home/pages/widget/widgets-bundle.component.html @@ -58,6 +58,10 @@ {{descriptionInput.value?.length || 0}}/1024 + + widgets-bundle.order + + diff --git a/ui-ngx/src/app/modules/home/pages/widget/widgets-bundle.component.ts b/ui-ngx/src/app/modules/home/pages/widget/widgets-bundle.component.ts index f7634e5c53..be34b38161 100644 --- a/ui-ngx/src/app/modules/home/pages/widget/widgets-bundle.component.ts +++ b/ui-ngx/src/app/modules/home/pages/widget/widgets-bundle.component.ts @@ -50,7 +50,8 @@ export class WidgetsBundleComponent extends EntityComponent { { title: [entity ? entity.title : '', [Validators.required, Validators.maxLength(255)]], image: [entity ? entity.image : ''], - description: [entity ? entity.description : '', Validators.maxLength(1024)] + description: [entity ? entity.description : '', Validators.maxLength(1024)], + order: [entity ? entity.order : null] } ); } @@ -59,7 +60,8 @@ export class WidgetsBundleComponent extends EntityComponent { this.entityForm.patchValue({ title: entity.title, image: entity.image, - description: entity.description + description: entity.description, + order: entity.order }); } } diff --git a/ui-ngx/src/app/shared/models/widgets-bundle.model.ts b/ui-ngx/src/app/shared/models/widgets-bundle.model.ts index c7eb999221..476c6ee029 100644 --- a/ui-ngx/src/app/shared/models/widgets-bundle.model.ts +++ b/ui-ngx/src/app/shared/models/widgets-bundle.model.ts @@ -24,4 +24,5 @@ export interface WidgetsBundle extends BaseData, ExportableEnti title: string; image: string; description: string; + order: number; } 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 fbd324666d..252e5e7296 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -4911,6 +4911,7 @@ "title-max-length": "Title should be less than 256", "description": "Description", "image-preview": "Image preview", + "order": "Order", "add-widgets-bundle-text": "Add new widgets bundle", "no-widgets-bundles-text": "No widgets bundles found", "empty": "Widgets bundle is empty",