Browse Source

Merge pull request #14659 from thingsboard/rc

RC
pull/14682/head
Viacheslav Klimov 5 months ago
committed by GitHub
parent
commit
78beec0d75
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 2
      application/pom.xml
  2. 2
      common/actor/pom.xml
  3. 2
      common/cache/pom.xml
  4. 2
      common/cluster-api/pom.xml
  5. 2
      common/coap-server/pom.xml
  6. 2
      common/dao-api/pom.xml
  7. 2
      common/data/pom.xml
  8. 2
      common/discovery-api/pom.xml
  9. 2
      common/edge-api/pom.xml
  10. 2
      common/edqs/pom.xml
  11. 2
      common/message/pom.xml
  12. 2
      common/pom.xml
  13. 2
      common/proto/pom.xml
  14. 2
      common/queue/pom.xml
  15. 2
      common/script/pom.xml
  16. 2
      common/script/remote-js-client/pom.xml
  17. 2
      common/script/script-api/pom.xml
  18. 2
      common/stats/pom.xml
  19. 2
      common/transport/coap/pom.xml
  20. 2
      common/transport/http/pom.xml
  21. 2
      common/transport/lwm2m/pom.xml
  22. 2
      common/transport/mqtt/pom.xml
  23. 2
      common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/TbMqttSslTransportComponent.java
  24. 2
      common/transport/pom.xml
  25. 2
      common/transport/snmp/pom.xml
  26. 2
      common/transport/transport-api/pom.xml
  27. 2
      common/util/pom.xml
  28. 2
      common/version-control/pom.xml
  29. 2
      dao/pom.xml
  30. 2
      edqs/pom.xml
  31. 2
      monitoring/pom.xml
  32. 2
      msa/black-box-tests/pom.xml
  33. 2
      msa/edqs/pom.xml
  34. 2
      msa/js-executor/pom.xml
  35. 2
      msa/monitoring/pom.xml
  36. 2
      msa/pom.xml
  37. 2
      msa/tb-node/pom.xml
  38. 2
      msa/tb/pom.xml
  39. 2
      msa/transport/coap/pom.xml
  40. 2
      msa/transport/http/pom.xml
  41. 2
      msa/transport/lwm2m/pom.xml
  42. 2
      msa/transport/mqtt/pom.xml
  43. 2
      msa/transport/pom.xml
  44. 2
      msa/transport/snmp/pom.xml
  45. 2
      msa/vc-executor-docker/pom.xml
  46. 2
      msa/vc-executor/pom.xml
  47. 2
      msa/web-ui/pom.xml
  48. 4
      netty-mqtt/pom.xml
  49. 2
      pom.xml
  50. 2
      rest-client/pom.xml
  51. 2
      rule-engine/pom.xml
  52. 2
      rule-engine/rule-engine-api/pom.xml
  53. 2
      rule-engine/rule-engine-components/pom.xml
  54. 2
      tools/pom.xml
  55. 2
      transport/coap/pom.xml
  56. 2
      transport/http/pom.xml
  57. 2
      transport/lwm2m/pom.xml
  58. 2
      transport/mqtt/pom.xml
  59. 2
      transport/pom.xml
  60. 2
      transport/snmp/pom.xml
  61. 2
      ui-ngx/pom.xml
  62. 16
      ui-ngx/src/app/core/http/calculated-fields.service.ts
  63. 43
      ui-ngx/src/app/modules/home/components/alarm-rules/alarm-rules-table-config.ts
  64. 4
      ui-ngx/src/app/modules/home/components/alarm-rules/cf-alarm-rule-condition-dialog.component.html
  65. 13
      ui-ngx/src/app/modules/home/components/audit-log/audit-log-details-dialog.component.html
  66. 26
      ui-ngx/src/app/modules/home/components/audit-log/audit-log-details-dialog.component.scss
  67. 99
      ui-ngx/src/app/modules/home/components/audit-log/audit-log-details-dialog.component.ts
  68. 50
      ui-ngx/src/app/modules/home/components/calculated-fields/calculated-fields-table-config.ts
  69. 4
      ui-ngx/src/app/modules/home/components/calculated-fields/components/propagation-configuration/propagation-configuration.component.html
  70. 4
      ui-ngx/src/app/modules/home/components/calculated-fields/components/simple-configuration/simple-configuration.component.html
  71. 4
      ui-ngx/src/app/modules/home/components/event/event-content-dialog.component.html
  72. 23
      ui-ngx/src/app/modules/home/components/event/event-content-dialog.component.scss
  73. 103
      ui-ngx/src/app/modules/home/components/event/event-content-dialog.component.ts
  74. 11
      ui-ngx/src/app/shared/components/entity/entity-subtype-list.component.ts
  75. 1
      ui-ngx/src/app/shared/components/hint-tooltip-icon.component.scss
  76. 88
      ui-ngx/src/app/shared/components/json-object-view.component.ts
  77. 16
      ui-ngx/src/app/shared/import-export/import-dialog-csv.component.ts
  78. 41
      ui-ngx/src/app/shared/models/ace/ace.models.ts
  79. 2
      ui-ngx/src/app/shared/models/calculated-field.models.ts
  80. 26
      ui-ngx/src/assets/locale/locale.constant-en_US.json
  81. 14
      ui-ngx/src/form.scss

2
application/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>4.3.0-SNAPSHOT</version>
<version>4.3.0-RC</version>
<artifactId>thingsboard</artifactId>
</parent>
<artifactId>application</artifactId>

2
common/actor/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>4.3.0-SNAPSHOT</version>
<version>4.3.0-RC</version>
<artifactId>common</artifactId>
</parent>
<groupId>org.thingsboard.common</groupId>

2
common/cache/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>4.3.0-SNAPSHOT</version>
<version>4.3.0-RC</version>
<artifactId>common</artifactId>
</parent>
<groupId>org.thingsboard.common</groupId>

2
common/cluster-api/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>4.3.0-SNAPSHOT</version>
<version>4.3.0-RC</version>
<artifactId>common</artifactId>
</parent>
<groupId>org.thingsboard.common</groupId>

2
common/coap-server/pom.xml

@ -22,7 +22,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>4.3.0-SNAPSHOT</version>
<version>4.3.0-RC</version>
<artifactId>common</artifactId>
</parent>
<groupId>org.thingsboard.common</groupId>

2
common/dao-api/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>4.3.0-SNAPSHOT</version>
<version>4.3.0-RC</version>
<artifactId>common</artifactId>
</parent>
<groupId>org.thingsboard.common</groupId>

2
common/data/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>4.3.0-SNAPSHOT</version>
<version>4.3.0-RC</version>
<artifactId>common</artifactId>
</parent>
<groupId>org.thingsboard.common</groupId>

2
common/discovery-api/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>4.3.0-SNAPSHOT</version>
<version>4.3.0-RC</version>
<artifactId>common</artifactId>
</parent>
<groupId>org.thingsboard.common</groupId>

2
common/edge-api/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>4.3.0-SNAPSHOT</version>
<version>4.3.0-RC</version>
<artifactId>common</artifactId>
</parent>
<groupId>org.thingsboard.common</groupId>

2
common/edqs/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>4.3.0-SNAPSHOT</version>
<version>4.3.0-RC</version>
<artifactId>common</artifactId>
</parent>
<groupId>org.thingsboard.common</groupId>

2
common/message/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>4.3.0-SNAPSHOT</version>
<version>4.3.0-RC</version>
<artifactId>common</artifactId>
</parent>
<groupId>org.thingsboard.common</groupId>

2
common/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>4.3.0-SNAPSHOT</version>
<version>4.3.0-RC</version>
<artifactId>thingsboard</artifactId>
</parent>
<artifactId>common</artifactId>

2
common/proto/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>4.3.0-SNAPSHOT</version>
<version>4.3.0-RC</version>
<artifactId>common</artifactId>
</parent>
<groupId>org.thingsboard.common</groupId>

2
common/queue/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>4.3.0-SNAPSHOT</version>
<version>4.3.0-RC</version>
<artifactId>common</artifactId>
</parent>
<groupId>org.thingsboard.common</groupId>

2
common/script/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>4.3.0-SNAPSHOT</version>
<version>4.3.0-RC</version>
<artifactId>common</artifactId>
</parent>
<groupId>org.thingsboard.common</groupId>

2
common/script/remote-js-client/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard.common</groupId>
<version>4.3.0-SNAPSHOT</version>
<version>4.3.0-RC</version>
<artifactId>script</artifactId>
</parent>
<groupId>org.thingsboard.common.script</groupId>

2
common/script/script-api/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard.common</groupId>
<version>4.3.0-SNAPSHOT</version>
<version>4.3.0-RC</version>
<artifactId>script</artifactId>
</parent>
<groupId>org.thingsboard.common.script</groupId>

2
common/stats/pom.xml

@ -22,7 +22,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>4.3.0-SNAPSHOT</version>
<version>4.3.0-RC</version>
<artifactId>common</artifactId>
</parent>
<groupId>org.thingsboard.common</groupId>

2
common/transport/coap/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard.common</groupId>
<version>4.3.0-SNAPSHOT</version>
<version>4.3.0-RC</version>
<artifactId>transport</artifactId>
</parent>
<groupId>org.thingsboard.common.transport</groupId>

2
common/transport/http/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard.common</groupId>
<version>4.3.0-SNAPSHOT</version>
<version>4.3.0-RC</version>
<artifactId>transport</artifactId>
</parent>
<groupId>org.thingsboard.common.transport</groupId>

2
common/transport/lwm2m/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard.common</groupId>
<version>4.3.0-SNAPSHOT</version>
<version>4.3.0-RC</version>
<artifactId>transport</artifactId>
</parent>
<groupId>org.thingsboard.common.transport</groupId>

2
common/transport/mqtt/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard.common</groupId>
<version>4.3.0-SNAPSHOT</version>
<version>4.3.0-RC</version>
<artifactId>transport</artifactId>
</parent>
<groupId>org.thingsboard.common.transport</groupId>

2
common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/TbMqttSslTransportComponent.java

@ -27,5 +27,5 @@ import java.lang.annotation.RetentionPolicy;
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@ConditionalOnExpression("'${service.type:null}'=='tb-transport' || ('${service.type:null}'=='monolith' && '${transport.api_enabled:true}'=='true' && '${transport.mqtt.enabled:true}'=='true' && '${transport.mqtt.ssl.enabled:false}'=='true')")
@ConditionalOnExpression("'${transport.mqtt.ssl.enabled:false}'=='true' && ('${service.type:null}'=='tb-transport' || ('${service.type:null}'=='monolith' && '${transport.api_enabled:true}'=='true' && '${transport.mqtt.enabled:true}'=='true'))")
public @interface TbMqttSslTransportComponent {}

2
common/transport/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>4.3.0-SNAPSHOT</version>
<version>4.3.0-RC</version>
<artifactId>common</artifactId>
</parent>
<groupId>org.thingsboard.common</groupId>

2
common/transport/snmp/pom.xml

@ -21,7 +21,7 @@
<parent>
<groupId>org.thingsboard.common</groupId>
<version>4.3.0-SNAPSHOT</version>
<version>4.3.0-RC</version>
<artifactId>transport</artifactId>
</parent>

2
common/transport/transport-api/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard.common</groupId>
<version>4.3.0-SNAPSHOT</version>
<version>4.3.0-RC</version>
<artifactId>transport</artifactId>
</parent>
<groupId>org.thingsboard.common.transport</groupId>

2
common/util/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>4.3.0-SNAPSHOT</version>
<version>4.3.0-RC</version>
<artifactId>common</artifactId>
</parent>
<groupId>org.thingsboard.common</groupId>

2
common/version-control/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>4.3.0-SNAPSHOT</version>
<version>4.3.0-RC</version>
<artifactId>common</artifactId>
</parent>
<groupId>org.thingsboard.common</groupId>

2
dao/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>4.3.0-SNAPSHOT</version>
<version>4.3.0-RC</version>
<artifactId>thingsboard</artifactId>
</parent>
<artifactId>dao</artifactId>

2
edqs/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>4.3.0-SNAPSHOT</version>
<version>4.3.0-RC</version>
<artifactId>thingsboard</artifactId>
</parent>
<artifactId>edqs</artifactId>

2
monitoring/pom.xml

@ -21,7 +21,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>4.3.0-SNAPSHOT</version>
<version>4.3.0-RC</version>
<artifactId>thingsboard</artifactId>
</parent>

2
msa/black-box-tests/pom.xml

@ -21,7 +21,7 @@
<parent>
<groupId>org.thingsboard</groupId>
<version>4.3.0-SNAPSHOT</version>
<version>4.3.0-RC</version>
<artifactId>msa</artifactId>
</parent>
<groupId>org.thingsboard.msa</groupId>

2
msa/edqs/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>4.3.0-SNAPSHOT</version>
<version>4.3.0-RC</version>
<artifactId>msa</artifactId>
</parent>
<groupId>org.thingsboard.msa</groupId>

2
msa/js-executor/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>4.3.0-SNAPSHOT</version>
<version>4.3.0-RC</version>
<artifactId>msa</artifactId>
</parent>
<groupId>org.thingsboard.msa</groupId>

2
msa/monitoring/pom.xml

@ -22,7 +22,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>4.3.0-SNAPSHOT</version>
<version>4.3.0-RC</version>
<artifactId>msa</artifactId>
</parent>

2
msa/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>4.3.0-SNAPSHOT</version>
<version>4.3.0-RC</version>
<artifactId>thingsboard</artifactId>
</parent>
<artifactId>msa</artifactId>

2
msa/tb-node/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>4.3.0-SNAPSHOT</version>
<version>4.3.0-RC</version>
<artifactId>msa</artifactId>
</parent>
<groupId>org.thingsboard.msa</groupId>

2
msa/tb/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>4.3.0-SNAPSHOT</version>
<version>4.3.0-RC</version>
<artifactId>msa</artifactId>
</parent>
<groupId>org.thingsboard.msa</groupId>

2
msa/transport/coap/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard.msa</groupId>
<version>4.3.0-SNAPSHOT</version>
<version>4.3.0-RC</version>
<artifactId>transport</artifactId>
</parent>
<groupId>org.thingsboard.msa.transport</groupId>

2
msa/transport/http/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard.msa</groupId>
<version>4.3.0-SNAPSHOT</version>
<version>4.3.0-RC</version>
<artifactId>transport</artifactId>
</parent>
<groupId>org.thingsboard.msa.transport</groupId>

2
msa/transport/lwm2m/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard.msa</groupId>
<version>4.3.0-SNAPSHOT</version>
<version>4.3.0-RC</version>
<artifactId>transport</artifactId>
</parent>
<groupId>org.thingsboard.msa.transport</groupId>

2
msa/transport/mqtt/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard.msa</groupId>
<version>4.3.0-SNAPSHOT</version>
<version>4.3.0-RC</version>
<artifactId>transport</artifactId>
</parent>
<groupId>org.thingsboard.msa.transport</groupId>

2
msa/transport/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>4.3.0-SNAPSHOT</version>
<version>4.3.0-RC</version>
<artifactId>msa</artifactId>
</parent>
<groupId>org.thingsboard.msa</groupId>

2
msa/transport/snmp/pom.xml

@ -21,7 +21,7 @@
<parent>
<groupId>org.thingsboard.msa</groupId>
<artifactId>transport</artifactId>
<version>4.3.0-SNAPSHOT</version>
<version>4.3.0-RC</version>
</parent>
<groupId>org.thingsboard.msa.transport</groupId>

2
msa/vc-executor-docker/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>4.3.0-SNAPSHOT</version>
<version>4.3.0-RC</version>
<artifactId>msa</artifactId>
</parent>
<groupId>org.thingsboard.msa</groupId>

2
msa/vc-executor/pom.xml

@ -21,7 +21,7 @@
<parent>
<groupId>org.thingsboard</groupId>
<version>4.3.0-SNAPSHOT</version>
<version>4.3.0-RC</version>
<artifactId>msa</artifactId>
</parent>
<groupId>org.thingsboard.msa</groupId>

2
msa/web-ui/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>4.3.0-SNAPSHOT</version>
<version>4.3.0-RC</version>
<artifactId>msa</artifactId>
</parent>
<groupId>org.thingsboard.msa</groupId>

4
netty-mqtt/pom.xml

@ -19,11 +19,11 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>4.3.0-SNAPSHOT</version>
<version>4.3.0-RC</version>
<artifactId>thingsboard</artifactId>
</parent>
<artifactId>netty-mqtt</artifactId>
<version>4.3.0-SNAPSHOT</version>
<version>4.3.0-RC</version>
<packaging>jar</packaging>
<name>Netty MQTT Client</name>

2
pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>org.thingsboard</groupId>
<artifactId>thingsboard</artifactId>
<version>4.3.0-SNAPSHOT</version>
<version>4.3.0-RC</version>
<packaging>pom</packaging>
<name>Thingsboard</name>

2
rest-client/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>4.3.0-SNAPSHOT</version>
<version>4.3.0-RC</version>
<artifactId>thingsboard</artifactId>
</parent>
<artifactId>rest-client</artifactId>

2
rule-engine/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>4.3.0-SNAPSHOT</version>
<version>4.3.0-RC</version>
<artifactId>thingsboard</artifactId>
</parent>
<artifactId>rule-engine</artifactId>

2
rule-engine/rule-engine-api/pom.xml

@ -22,7 +22,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>4.3.0-SNAPSHOT</version>
<version>4.3.0-RC</version>
<artifactId>rule-engine</artifactId>
</parent>
<groupId>org.thingsboard.rule-engine</groupId>

2
rule-engine/rule-engine-components/pom.xml

@ -22,7 +22,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>4.3.0-SNAPSHOT</version>
<version>4.3.0-RC</version>
<artifactId>rule-engine</artifactId>
</parent>
<groupId>org.thingsboard.rule-engine</groupId>

2
tools/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>4.3.0-SNAPSHOT</version>
<version>4.3.0-RC</version>
<artifactId>thingsboard</artifactId>
</parent>
<artifactId>tools</artifactId>

2
transport/coap/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>4.3.0-SNAPSHOT</version>
<version>4.3.0-RC</version>
<artifactId>transport</artifactId>
</parent>
<groupId>org.thingsboard.transport</groupId>

2
transport/http/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>4.3.0-SNAPSHOT</version>
<version>4.3.0-RC</version>
<artifactId>transport</artifactId>
</parent>
<groupId>org.thingsboard.transport</groupId>

2
transport/lwm2m/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>4.3.0-SNAPSHOT</version>
<version>4.3.0-RC</version>
<artifactId>transport</artifactId>
</parent>
<groupId>org.thingsboard.transport</groupId>

2
transport/mqtt/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>4.3.0-SNAPSHOT</version>
<version>4.3.0-RC</version>
<artifactId>transport</artifactId>
</parent>
<groupId>org.thingsboard.transport</groupId>

2
transport/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>4.3.0-SNAPSHOT</version>
<version>4.3.0-RC</version>
<artifactId>thingsboard</artifactId>
</parent>
<artifactId>transport</artifactId>

2
transport/snmp/pom.xml

@ -21,7 +21,7 @@
<parent>
<groupId>org.thingsboard</groupId>
<version>4.3.0-SNAPSHOT</version>
<version>4.3.0-RC</version>
<artifactId>transport</artifactId>
</parent>

2
ui-ngx/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>4.3.0-SNAPSHOT</version>
<version>4.3.0-RC</version>
<artifactId>thingsboard</artifactId>
</parent>
<groupId>org.thingsboard</groupId>

16
ui-ngx/src/app/core/http/calculated-fields.service.ts

@ -15,17 +15,13 @@
///
import { Injectable } from '@angular/core';
import {
createDefaultHttpOptions,
defaultHttpOptionsFromConfig,
defaultHttpOptionsFromParams,
RequestConfig
} from './http-utils';
import { defaultHttpOptionsFromConfig, defaultHttpOptionsFromParams, RequestConfig } from './http-utils';
import { Observable } from 'rxjs';
import { HttpClient } from '@angular/common/http';
import { PageData } from '@shared/models/page/page-data';
import {
CalculatedField,
CalculatedFieldInfo,
CalculatedFieldsQuery,
CalculatedFieldTestScriptInputParams,
CalculatedFieldType
@ -56,11 +52,11 @@ export class CalculatedFieldsService {
return this.http.delete<boolean>(`/api/calculatedField/${calculatedFieldId}`, defaultHttpOptionsFromConfig(config));
}
public getCalculatedFieldsFilter(pageLink: PageLink, query: CalculatedFieldsQuery, config?: RequestConfig): Observable<PageData<CalculatedField>> {
return this.http.get<PageData<CalculatedField>>(`/api/calculatedFields${pageLink.toQuery()}`, defaultHttpOptionsFromParams(query, config));
public getCalculatedFields(pageLink: PageLink, query: CalculatedFieldsQuery, config?: RequestConfig): Observable<PageData<CalculatedFieldInfo>> {
return this.http.get<PageData<CalculatedFieldInfo>>(`/api/calculatedFields${pageLink.toQuery()}`, defaultHttpOptionsFromParams(query, config));
}
public getCalculatedFields({ entityType, id }: EntityId, pageLink: PageLink, type?: CalculatedFieldType, config?: RequestConfig): Observable<PageData<CalculatedField>> {
public getCalculatedFieldsByEntityId({ entityType, id }: EntityId, pageLink: PageLink, type?: CalculatedFieldType, config?: RequestConfig): Observable<PageData<CalculatedField>> {
return this.http.get<PageData<CalculatedField>>(`/api/${entityType}/${id}/calculatedFields${pageLink.toQuery()}`, defaultHttpOptionsFromParams({type} , config));
}
@ -72,7 +68,7 @@ export class CalculatedFieldsService {
return this.http.get<CalculatedFieldEventBody>(`/api/calculatedField/${id}/debug`, defaultHttpOptionsFromConfig(config));
}
public getAlarmRuleNames(pageLink: PageLink, type: CalculatedFieldType, config?: RequestConfig): Observable<PageData<string>> {
public getCalculatedFieldNames(pageLink: PageLink, type: CalculatedFieldType, config?: RequestConfig): Observable<PageData<string>> {
return this.http.get<PageData<string>>(`/api/calculatedFields/names${pageLink.toQuery()}`, defaultHttpOptionsFromParams({type}, config));
}
}

43
ui-ngx/src/app/modules/home/components/alarm-rules/alarm-rules-table-config.ts

@ -43,6 +43,7 @@ import {
CalculatedField,
CalculatedFieldAlarmRule,
CalculatedFieldEventArguments,
CalculatedFieldInfo,
CalculatedFieldsQuery,
CalculatedFieldType,
getCalculatedFieldArgumentsEditorCompleter,
@ -67,12 +68,14 @@ import {
CalculatedFieldTestScriptDialogData
} from "@home/components/calculated-fields/components/test-dialog/calculated-field-script-test-dialog.component";
export class AlarmRulesTableConfig extends EntityTableConfig<any> {
type AlarmRuleTableEntity = CalculatedField | CalculatedFieldInfo;
export class AlarmRulesTableConfig extends EntityTableConfig<AlarmRuleTableEntity> {
readonly tenantId = getCurrentAuthUser(this.store).tenantId;
additionalDebugActionConfig = {
title: this.translate.instant('action.see-debug-events'),
action: (calculatedField: CalculatedField) => this.openDebugEventsDialog.call(this, calculatedField),
action: (calculatedField: AlarmRuleTableEntity) => this.openDebugEventsDialog.call(this, calculatedField),
};
alarmRuleFilterConfig: CalculatedFieldsQuery;
@ -81,11 +84,11 @@ export class AlarmRulesTableConfig extends EntityTableConfig<any> {
private translate: TranslateService,
private dialog: MatDialog,
private datePipe: DatePipe,
public entityId: EntityId = null,
private entityId: EntityId = null,
private store: Store<AppState>,
private destroyRef: DestroyRef,
private renderer: Renderer2,
public entityName: string,
private entityName: string,
private ownerId: EntityId = null,
private importExportService: ImportExportService,
private entityDebugSettingsService: EntityDebugSettingsService,
@ -118,7 +121,7 @@ export class AlarmRulesTableConfig extends EntityTableConfig<any> {
this.entitiesFetchFunction = (pageLink: PageLink) => this.fetchCalculatedFields(pageLink);
this.addEntity = this.getCalculatedAlarmDialog.bind(this);
this.deleteEntityTitle = (field: CalculatedField) => this.translate.instant('alarm-rule.delete-title', {title: field.name});
this.deleteEntityTitle = (field) => this.translate.instant('alarm-rule.delete-title', {title: field.name});
this.deleteEntityContent = () => this.translate.instant('alarm-rule.delete-text');
this.deleteEntitiesTitle = count => this.translate.instant('alarm-rule.delete-multiple-title', {count});
this.deleteEntitiesContent = () => this.translate.instant('alarm-rule.delete-multiple-text');
@ -143,10 +146,10 @@ export class AlarmRulesTableConfig extends EntityTableConfig<any> {
this.columns.push(new EntityTableColumn<CalculatedFieldAlarmRule>('name', 'alarm-rule.alarm-type', '33%',
entity => this.utilsService.customTranslation(entity.name, entity.name)));
if (this.pageMode) {
this.columns.push(new EntityTableColumn<CalculatedFieldAlarmRule>('entityType', 'entity.entity-type', '10%',
this.columns.push(new EntityTableColumn<CalculatedFieldInfo>('entityType', 'entity.entity-type', '10%',
entity => this.translate.instant(entityTypeTranslations.get(entity.entityId.entityType).type)));
this.columns.push(new EntityLinkTableColumn<CalculatedFieldAlarmRule>('entityName', 'entity.entity', '33%',
entity => this.utilsService.customTranslation(entity['entityName'], entity['entityName']),
this.columns.push(new EntityLinkTableColumn<CalculatedFieldInfo>('entityName', 'entity.entity', '33%',
entity => this.utilsService.customTranslation(entity.entityName, entity.entityName),
entity => getEntityDetailsPageURL(entity.entityId?.id, entity.entityId?.entityType as EntityType), false));
}
this.columns.push(new EntityTableColumn<CalculatedFieldAlarmRule>('createRule', 'alarm-rule.severities', this.pageMode ? '23%' : '67%',
@ -193,13 +196,13 @@ export class AlarmRulesTableConfig extends EntityTableConfig<any> {
);
}
fetchCalculatedFields(pageLink: PageLink): Observable<PageData<CalculatedField>> {
fetchCalculatedFields(pageLink: PageLink): Observable<PageData<AlarmRuleTableEntity>> {
return this.pageMode ?
this.calculatedFieldsService.getCalculatedFieldsFilter(pageLink, {types: [CalculatedFieldType.ALARM], ...this.alarmRuleFilterConfig}) :
this.calculatedFieldsService.getCalculatedFields(this.entityId, pageLink, CalculatedFieldType.ALARM);
this.calculatedFieldsService.getCalculatedFields(pageLink, {types: [CalculatedFieldType.ALARM], ...this.alarmRuleFilterConfig}) :
this.calculatedFieldsService.getCalculatedFieldsByEntityId(this.entityId, pageLink, CalculatedFieldType.ALARM);
}
onOpenDebugConfig($event: Event, calculatedField: CalculatedField): void {
onOpenDebugConfig($event: Event, calculatedField: AlarmRuleTableEntity): void {
$event?.stopPropagation();
const { debugSettings = {}, id } = calculatedField;
const additionalActionConfig = {
@ -224,7 +227,7 @@ export class AlarmRulesTableConfig extends EntityTableConfig<any> {
}, $event.target as Element);
}
private editCalculatedField($event: Event, calculatedField: CalculatedField, isDirty = false): void {
private editCalculatedField($event: Event, calculatedField: AlarmRuleTableEntity, isDirty = false): void {
$event?.stopPropagation();
this.getCalculatedAlarmDialog(calculatedField, 'action.apply', isDirty)
.subscribe((res) => {
@ -234,11 +237,12 @@ export class AlarmRulesTableConfig extends EntityTableConfig<any> {
});
}
private copyCalculatedField($event: Event, calculatedField: CalculatedField, isDirty = false): void {
private copyCalculatedField($event: Event, calculatedField: AlarmRuleTableEntity, isDirty = false): void {
$event?.stopPropagation();
const copyCalculatedAlarmRule = deepClone(calculatedField);
if (this.pageMode) {
copyCalculatedAlarmRule.entityId = null;
delete (copyCalculatedAlarmRule as CalculatedFieldInfo).entityName;
}
delete copyCalculatedAlarmRule.id;
this.getCalculatedAlarmDialog(copyCalculatedAlarmRule, 'action.apply', isDirty)
@ -249,8 +253,9 @@ export class AlarmRulesTableConfig extends EntityTableConfig<any> {
});
}
private getCalculatedAlarmDialog(value?: CalculatedField, buttonTitle = 'action.add', isDirty = false): Observable<CalculatedField> {
private getCalculatedAlarmDialog(value?: AlarmRuleTableEntity, buttonTitle = 'action.add', isDirty = false): Observable<CalculatedField> {
const entityId = this.entityId || value?.entityId;
const entityName = this.entityName || (value as CalculatedFieldInfo)?.entityName;
return this.dialog.open<AlarmRuleDialogComponent, AlarmRuleDialogData, CalculatedField>(AlarmRuleDialogComponent, {
disableClose: true,
panelClass: ['tb-dialog', 'tb-fullscreen-dialog'],
@ -258,8 +263,8 @@ export class AlarmRulesTableConfig extends EntityTableConfig<any> {
value,
buttonTitle,
entityId,
entityName,
tenantId: this.tenantId,
entityName: this.entityName,
ownerId: this.ownerId ?? {entityType: EntityType.TENANT, id: this.tenantId},
additionalDebugActionConfig: this.additionalDebugActionConfig,
isDirty,
@ -271,7 +276,7 @@ export class AlarmRulesTableConfig extends EntityTableConfig<any> {
.pipe(filter(Boolean));
}
private openDebugEventsDialog($event: Event, calculatedField: CalculatedField): void {
private openDebugEventsDialog($event: Event, calculatedField: AlarmRuleTableEntity): void {
$event?.stopPropagation();
this.dialog.open<EventsDialogComponent, EventsDialogData, null>(EventsDialogComponent, {
disableClose: true,
@ -290,7 +295,7 @@ export class AlarmRulesTableConfig extends EntityTableConfig<any> {
.subscribe();
}
private exportAlarmRule($event: Event, calculatedField: CalculatedField): void {
private exportAlarmRule($event: Event, calculatedField: AlarmRuleTableEntity): void {
$event?.stopPropagation();
this.importExportService.exportCalculatedField(calculatedField.id.id);
}
@ -343,7 +348,7 @@ export class AlarmRulesTableConfig extends EntityTableConfig<any> {
).subscribe(() => this.updateData());
}
private getTestScriptDialog(calculatedField: CalculatedField, expression: string, argumentsObj?: CalculatedFieldEventArguments, openCalculatedFieldEdit = true): Observable<string> {
private getTestScriptDialog(calculatedField: AlarmRuleTableEntity, expression: string, argumentsObj?: CalculatedFieldEventArguments, openCalculatedFieldEdit = true): Observable<string> {
if (calculatedField.type === CalculatedFieldType.ALARM) {
const resultArguments = Object.keys(calculatedField.configuration.arguments).reduce((acc, key) => {
const type = calculatedField.configuration.arguments[key].refEntityKey.type;

4
ui-ngx/src/app/modules/home/components/alarm-rules/cf-alarm-rule-condition-dialog.component.html

@ -55,9 +55,7 @@
</div>
} @else {
<div class="tb-form-panel no-gap stroked">
<div class="tb-form-panel-title tb-required">
{{ 'alarm-rule.script' | translate }}
</div>
<div class="tb-form-panel-title tb-required">{{ 'alarm-rule.script' | translate }}</div>
<tb-js-func formControlName="expression"
functionName="expression"
class="tb-alarm-rule-script"

13
ui-ngx/src/app/modules/home/components/audit-log/audit-log-details-dialog.component.html

@ -24,13 +24,14 @@
<mat-icon class="material-icons">close</mat-icon>
</button>
</mat-toolbar>
<div mat-dialog-content class="flex flex-col">
<label translate class="tb-title no-padding">audit-log.action-data</label>
<div #actionDataEditor class="tb-audit-log-action-data">
<div mat-dialog-content class="flex flex-col gap-8" style="padding:16px;">
<div class="flex max-h-fit min-h-0 flex-1 flex-col">
<span translate class="tb-form-panel-hint">audit-log.action-data</span>
<div #actionDataEditor class="tb-audit-log size-full min-h-12 max-w-full"></div>
</div>
<span style="min-height: 30px;"></span>
<label [class.!hidden]="!displayFailureDetails" translate class="tb-title no-padding">audit-log.failure-details</label>
<div #failureDetailsEditor [class.!hidden]="!displayFailureDetails" class="tb-audit-log-failure-details">
<div class="flex max-h-fit min-h-0 flex-1 flex-col" [class.!hidden]="!displayFailureDetails">
<span translate class="tb-form-panel-hint">audit-log.failure-details</span>
<div #failureDetailsEditor class="tb-audit-log size-full min-h-12 max-w-full"></div>
</div>
</div>
<div mat-dialog-actions class="flex items-center justify-end">

26
ui-ngx/src/app/modules/home/components/audit-log/audit-log-details-dialog.component.scss

@ -13,13 +13,27 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
@import '../../../../../scss/constants';
:host {
.tb-audit-log-action-data,
.tb-audit-log-failure-details {
width: 100%;
min-width: 400px;
height: 100%;
min-height: 50px;
display: grid;
height: 100%;
max-width: 100%;
max-height: 100vh;
grid-template-rows: min-content minmax(auto, 1fr) min-content;
@media #{$mat-gt-xs} {
.mat-mdc-dialog-content {
max-height: 80vh;
}
}
.tb-audit-log {
min-width: max(400px, 100%);
border: 1px solid #c0c0c0;
@media #{$mat-xs} {
min-width: 100%;
}
}
}

99
ui-ngx/src/app/modules/home/components/audit-log/audit-log-details-dialog.component.ts

@ -22,7 +22,11 @@ import { ActionStatus, AuditLog } from '@shared/models/audit-log.models';
import { Ace } from 'ace-builds';
import { DialogComponent } from '@shared/components/dialog.component';
import { Router } from '@angular/router';
import { getAce } from '@shared/models/ace/ace.models';
import { getAce, updateEditorSize } from '@shared/models/ace/ace.models';
import { Observable, of } from 'rxjs';
import { isObject } from '@core/utils';
import { ContentType, contentTypesMap } from '@shared/models/constants';
import { beautifyJs } from '@shared/models/beautify.models';
export interface AuditLogDetailsDialogData {
auditLog: AuditLog;
@ -41,11 +45,10 @@ export class AuditLogDetailsDialogComponent extends DialogComponent<AuditLogDeta
@ViewChild('failureDetailsEditor', {static: true})
failureDetailsEditorElmRef: ElementRef;
auditLog: AuditLog;
displayFailureDetails: boolean;
actionData: string;
actionFailureDetails: string;
aceEditors: Ace.Editor[] = [];
private auditLog: AuditLog;
private aceEditors: Ace.Editor[] = [];
constructor(protected store: Store<AppState>,
protected router: Router,
@ -58,12 +61,10 @@ export class AuditLogDetailsDialogComponent extends DialogComponent<AuditLogDeta
ngOnInit(): void {
this.auditLog = this.data.auditLog;
this.displayFailureDetails = this.auditLog.actionStatus === ActionStatus.FAILURE;
this.actionData = this.auditLog.actionData ? JSON.stringify(this.auditLog.actionData, null, 2) : '';
this.actionFailureDetails = this.auditLog.actionFailureDetails;
this.createEditor(this.actionDataEditorElmRef, this.actionData);
this.createEditor(this.actionDataEditorElmRef, this.auditLog.actionData);
if (this.displayFailureDetails) {
this.createEditor(this.failureDetailsEditorElmRef, this.actionFailureDetails);
this.createEditor(this.failureDetailsEditorElmRef, this.auditLog.actionFailureDetails);
}
}
@ -72,53 +73,43 @@ export class AuditLogDetailsDialogComponent extends DialogComponent<AuditLogDeta
super.ngOnDestroy();
}
createEditor(editorElementRef: ElementRef, content: string): void {
createEditor(editorElementRef: ElementRef, content: string | object): void {
const editorElement = editorElementRef.nativeElement;
let editorOptions: Partial<Ace.EditorOptions> = {
mode: 'ace/mode/java',
theme: 'ace/theme/github',
showGutter: false,
showPrintMargin: false,
readOnly: true
};
const advancedOptions = {
enableSnippets: false,
enableBasicAutocompletion: false,
enableLiveAutocompletion: false
};
editorOptions = {...editorOptions, ...advancedOptions};
getAce().subscribe(
(ace) => {
const editor = ace.edit(editorElement, editorOptions);
this.aceEditors.push(editor);
editor.session.setUseWrapMode(false);
editor.setValue(content, -1);
this.updateEditorSize(editorElement, content, editor);
}
);
}
updateEditorSize(editorElement: any, content: string, editor: Ace.Editor) {
let newHeight = 200;
let newWidth = 600;
if (content && content.length > 0) {
const lines = content.split('\n');
newHeight = 18 * lines.length + 16;
let maxLineLength = 0;
lines.forEach((row) => {
const line = row.replace(/\t/g, ' ').replace(/\n/g, '');
const lineLength = line.length;
maxLineLength = Math.max(maxLineLength, lineLength);
});
newWidth = 9 * maxLineLength + 16;
let mode = 'java';
let content$: Observable<string> = null;
let contentType = ContentType.TEXT;
if (content && isObject(content)) {
contentType = ContentType.JSON;
mode = contentTypesMap.get(contentType).code;
content$ = beautifyJs(JSON.stringify(content), {indent_size: 2});
}
if (!content$) {
content$ = of(content as string);
}
// newHeight = Math.min(400, newHeight);
this.renderer.setStyle(editorElement, 'minHeight', newHeight.toString() + 'px');
this.renderer.setStyle(editorElement, 'height', newHeight.toString() + 'px');
this.renderer.setStyle(editorElement, 'width', newWidth.toString() + 'px');
editor.resize();
content$.subscribe((processedContent) => {
const isJSON = contentType === ContentType.JSON
const editorOptions: Partial<Ace.EditorOptions> = {
mode: `ace/mode/${mode}`,
theme: 'ace/theme/github',
showGutter: isJSON,
showFoldWidgets: true,
foldStyle: 'markbeginend',
showPrintMargin: false,
readOnly: true,
enableSnippets: false,
enableBasicAutocompletion: false,
enableLiveAutocompletion: false,
};
getAce().subscribe(
(ace) => {
const editor = ace.edit(editorElement, editorOptions);
this.aceEditors.push(editor);
editor.session.setUseWrapMode(false);
editor.setValue(processedContent, -1);
updateEditorSize(editorElement, processedContent, editor, this.renderer, {showGutter: isJSON});
}
)
});
}
}

50
ui-ngx/src/app/modules/home/components/calculated-fields/calculated-fields-table-config.ts

@ -40,8 +40,8 @@ import {
ArgumentEntityType,
ArgumentType,
CalculatedField,
CalculatedFieldAlarmRule,
CalculatedFieldEventArguments,
CalculatedFieldInfo,
CalculatedFieldScriptConfiguration,
CalculatedFieldsQuery,
CalculatedFieldType,
@ -68,12 +68,14 @@ import {
CalculatedFieldsHeaderComponent
} from '@home/components/calculated-fields/table-header/calculated-fields-header.component';
export class CalculatedFieldsTableConfig extends EntityTableConfig<CalculatedField> {
type CalculatedFieldsTableEntity = CalculatedField | CalculatedFieldInfo;
export class CalculatedFieldsTableConfig extends EntityTableConfig<CalculatedFieldsTableEntity> {
readonly tenantId = getCurrentAuthUser(this.store).tenantId;
additionalDebugActionConfig = {
title: this.translate.instant('action.see-debug-events'),
action: (calculatedField: CalculatedField) => this.openDebugEventsDialog.call(this, null, calculatedField),
action: (calculatedField: CalculatedFieldsTableEntity) => this.openDebugEventsDialog.call(this, null, calculatedField),
};
calculatedFieldFilterConfig: CalculatedFieldsQuery;
@ -82,11 +84,11 @@ export class CalculatedFieldsTableConfig extends EntityTableConfig<CalculatedFie
private translate: TranslateService,
private dialog: MatDialog,
private datePipe: DatePipe,
public entityId: EntityId = null,
private entityId: EntityId = null,
private store: Store<AppState>,
private destroyRef: DestroyRef,
private renderer: Renderer2,
public entityName: string,
private entityName: string,
private ownerId: EntityId = null,
private importExportService: ImportExportService,
private entityDebugSettingsService: EntityDebugSettingsService,
@ -110,7 +112,7 @@ export class CalculatedFieldsTableConfig extends EntityTableConfig<CalculatedFie
this.entitiesFetchFunction = (pageLink: PageLink) => this.fetchCalculatedFields(pageLink);
this.addEntity = this.getCalculatedFieldDialog.bind(this);
this.deleteEntityTitle = (field: CalculatedField) => this.translate.instant('calculated-fields.delete-title', {title: field.name});
this.deleteEntityTitle = (field) => this.translate.instant('calculated-fields.delete-title', {title: field.name});
this.deleteEntityContent = () => this.translate.instant('calculated-fields.delete-text');
this.deleteEntitiesTitle = count => this.translate.instant('calculated-fields.delete-multiple-title', {count});
this.deleteEntitiesContent = () => this.translate.instant('calculated-fields.delete-multiple-text');
@ -136,10 +138,10 @@ export class CalculatedFieldsTableConfig extends EntityTableConfig<CalculatedFie
this.columns.push(new EntityTableColumn<CalculatedField>('name', 'common.name', this.pageMode ? '33%' : '60%',
entity => this.utilsService.customTranslation(entity.name, entity.name)));
if (this.pageMode) {
this.columns.push(new EntityTableColumn<CalculatedFieldAlarmRule>('entityType', 'entity.entity-type', '10%',
this.columns.push(new EntityTableColumn<CalculatedFieldInfo>('entityType', 'entity.entity-type', '10%',
entity => this.translate.instant(entityTypeTranslations.get(entity.entityId.entityType).type)));
this.columns.push(new EntityLinkTableColumn<CalculatedFieldAlarmRule>('entityName', 'entity.entity', '33%',
entity => this.utilsService.customTranslation(entity['entityName'], entity['entityName']),
this.columns.push(new EntityLinkTableColumn<CalculatedFieldInfo>('entityName', 'entity.entity', '33%',
entity => this.utilsService.customTranslation(entity.entityName, entity.entityName),
entity => getEntityDetailsPageURL(entity.entityId?.id, entity.entityId?.entityType as EntityType), false));
}
this.columns.push(new EntityTableColumn<CalculatedField>('type', 'common.type', this.pageMode ? '23%' : '40%', entity => this.translate.instant(CalculatedFieldTypeTranslations.get(entity.type).name), () => ({whiteSpace: 'nowrap' })));
@ -180,13 +182,13 @@ export class CalculatedFieldsTableConfig extends EntityTableConfig<CalculatedFie
);
}
fetchCalculatedFields(pageLink: PageLink): Observable<PageData<CalculatedField>> {
fetchCalculatedFields(pageLink: PageLink): Observable<PageData<CalculatedFieldsTableEntity>> {
return this.pageMode ?
this.calculatedFieldsService.getCalculatedFieldsFilter(pageLink, this.calculatedFieldFilterConfig):
this.calculatedFieldsService.getCalculatedFields(this.entityId, pageLink);
this.calculatedFieldsService.getCalculatedFields(pageLink, this.calculatedFieldFilterConfig):
this.calculatedFieldsService.getCalculatedFieldsByEntityId(this.entityId, pageLink);
}
onOpenDebugConfig($event: Event, calculatedField: CalculatedField): void {
onOpenDebugConfig($event: Event, calculatedField: CalculatedFieldsTableEntity): void {
$event?.stopPropagation();
const { debugSettings = {}, id } = calculatedField;
const additionalActionConfig = {
@ -210,7 +212,7 @@ export class CalculatedFieldsTableConfig extends EntityTableConfig<CalculatedFie
}, $event.target as Element);
}
private editCalculatedField($event: Event, calculatedField: CalculatedField, isDirty = false): void {
private editCalculatedField($event: Event, calculatedField: CalculatedFieldsTableEntity, isDirty = false): void {
$event?.stopPropagation();
this.getCalculatedFieldDialog(calculatedField, 'action.apply', isDirty)
.subscribe((res) => {
@ -220,8 +222,9 @@ export class CalculatedFieldsTableConfig extends EntityTableConfig<CalculatedFie
});
}
private getCalculatedFieldDialog(value?: CalculatedField, buttonTitle = 'action.add', isDirty = false): Observable<CalculatedField> {
private getCalculatedFieldDialog(value?: CalculatedFieldsTableEntity, buttonTitle = 'action.add', isDirty = false): Observable<CalculatedField> {
const entityId = this.entityId || value?.entityId;
const entityName = this.entityName || (value as CalculatedFieldInfo)?.entityName;
return this.dialog.open<CalculatedFieldDialogComponent, CalculatedFieldDialogData, CalculatedField>(CalculatedFieldDialogComponent, {
disableClose: true,
panelClass: ['tb-dialog', 'tb-fullscreen-dialog'],
@ -229,8 +232,8 @@ export class CalculatedFieldsTableConfig extends EntityTableConfig<CalculatedFie
value,
buttonTitle,
entityId,
entityName,
tenantId: this.tenantId,
entityName: this.entityName,
ownerId: this.ownerId,
additionalDebugActionConfig: this.additionalDebugActionConfig,
getTestScriptDialogFn: this.getTestScriptDialog.bind(this),
@ -242,7 +245,7 @@ export class CalculatedFieldsTableConfig extends EntityTableConfig<CalculatedFie
.pipe(filter(Boolean));
}
private openDebugEventsDialog($event: Event, calculatedField: CalculatedField): void {
private openDebugEventsDialog($event: Event, calculatedField: CalculatedFieldsTableEntity): void {
$event?.stopPropagation();
const debugActionEnabledFn = (event: DebugEvent) => {
return (calculatedField.type === CalculatedFieldType.SCRIPT ||
@ -274,19 +277,20 @@ export class CalculatedFieldsTableConfig extends EntityTableConfig<CalculatedFie
.subscribe();
}
private exportCalculatedField($event: Event, calculatedField: CalculatedField): void {
private exportCalculatedField($event: Event, calculatedField: CalculatedFieldsTableEntity): void {
$event?.stopPropagation();
this.importExportService.exportCalculatedField(calculatedField.id.id);
}
private copyCalculatedField($event: Event, calculatedField: CalculatedField): void {
$event?.stopPropagation();
const copyCalculatedAlarmRule = deepClone(calculatedField);
const copyCalculatedField = deepClone(calculatedField);
if (this.pageMode) {
copyCalculatedAlarmRule.entityId = null;
copyCalculatedField.entityId = null;
delete (copyCalculatedField as CalculatedFieldInfo).entityName;
}
delete copyCalculatedAlarmRule.id;
this.getCalculatedFieldDialog(copyCalculatedAlarmRule, 'action.apply', false)
delete copyCalculatedField.id;
this.getCalculatedFieldDialog(copyCalculatedField, 'action.apply', false)
.subscribe((res) => {
if (res) {
this.updateData();
@ -350,7 +354,7 @@ export class CalculatedFieldsTableConfig extends EntityTableConfig<CalculatedFie
).subscribe(() => this.updateData());
}
private getTestScriptDialog(calculatedField: CalculatedField, argumentsObj?: CalculatedFieldEventArguments, openCalculatedFieldEdit = true, expression?: string): Observable<string> {
private getTestScriptDialog(calculatedField: CalculatedFieldsTableEntity, argumentsObj?: CalculatedFieldEventArguments, openCalculatedFieldEdit = true, expression?: string): Observable<string> {
if (
calculatedField.type === CalculatedFieldType.SCRIPT ||
calculatedField.type === CalculatedFieldType.RELATED_ENTITIES_AGGREGATION ||

4
ui-ngx/src/app/modules/home/components/calculated-fields/components/propagation-configuration/propagation-configuration.component.html

@ -59,9 +59,7 @@
[isScript]="this.propagateConfiguration.get('applyExpressionToResolvedArguments').value"/>
</div>
<div class="tb-form-panel no-gap" [class.!hidden]="!this.propagateConfiguration.get('applyExpressionToResolvedArguments').value">
<div class="tb-form-panel-title tb-required">
{{ 'calculated-fields.script' | translate }}
</div>
<div class="tb-form-panel-title tb-required">{{ 'calculated-fields.script' | translate }}</div>
<div>
<tb-js-func required
formControlName="expression"

4
ui-ngx/src/app/modules/home/components/calculated-fields/components/simple-configuration/simple-configuration.component.html

@ -27,9 +27,7 @@
[isScript]="isScript" />
</div>
<div class="tb-form-panel no-gap">
<div class="tb-form-panel-title tb-required">
{{ (isScript ? 'calculated-fields.type.script' : 'calculated-fields.expression') | translate }}
</div>
<div class="tb-form-panel-title tb-required">{{ (isScript ? 'calculated-fields.type.script' : 'calculated-fields.expression') | translate }}</div>
<mat-form-field class="mt-3" appearance="outline" subscriptSizing="dynamic" [class.hidden]="isScript">
<input matInput formControlName="expressionSIMPLE" maxlength="255" [placeholder]="'(temperature - 32) / 1.8'"
required>

4
ui-ngx/src/app/modules/home/components/event/event-content-dialog.component.html

@ -24,8 +24,8 @@
<mat-icon class="material-icons">close</mat-icon>
</button>
</mat-toolbar>
<div mat-dialog-content class="flex flex-col">
<div #eventContentEditor class="tb-event-content">
<div mat-dialog-content class="flex flex-col" style="padding:16px;">
<div #eventContentEditor class="tb-event-content size-full min-h-12 max-w-full" [class.border]="showBorder">
</div>
</div>
<div mat-dialog-actions class="flex flex-row">

23
ui-ngx/src/app/modules/home/components/event/event-content-dialog.component.scss

@ -13,11 +13,28 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
@import '../../../../../scss/constants';
:host {
display: grid;
height: 100%;
max-width: 100%;
max-height: 100vh;
grid-template-rows: min-content minmax(auto, 1fr) min-content;
@media #{$mat-gt-xs} {
.mat-mdc-dialog-content {
max-height: 80vh;
}
}
.tb-event-content {
width: 100%;
min-width: 400px;
height: 100%;
min-height: 50px;
&.border {
border: 1px solid #c0c0c0;
}
@media #{$mat-xs} {
min-width: 100%;
}
}
}

103
ui-ngx/src/app/modules/home/components/event/event-content-dialog.component.ts

@ -23,7 +23,7 @@ import { Ace } from 'ace-builds';
import { DialogComponent } from '@shared/components/dialog.component';
import { Router } from '@angular/router';
import { ContentType, contentTypesMap } from '@shared/models/constants';
import { getAce } from '@shared/models/ace/ace.models';
import { getAce, updateEditorSize } from '@shared/models/ace/ace.models';
import { Observable } from 'rxjs/internal/Observable';
import { beautifyJs } from '@shared/models/beautify.models';
import { of } from 'rxjs';
@ -40,40 +40,38 @@ export interface EventContentDialogData {
templateUrl: './event-content-dialog.component.html',
styleUrls: ['./event-content-dialog.component.scss']
})
export class EventContentDialogComponent extends DialogComponent<EventContentDialogData> implements OnInit, OnDestroy {
export class EventContentDialogComponent extends DialogComponent<EventContentDialogComponent> implements OnInit, OnDestroy {
@ViewChild('eventContentEditor', {static: true})
eventContentEditorElmRef: ElementRef;
content: string;
title: string;
contentType: ContentType;
aceEditor: Ace.Editor;
showBorder = false;
private contentType: ContentType;
private aceEditor: Ace.Editor;
constructor(protected store: Store<AppState>,
protected router: Router,
@Inject(MAT_DIALOG_DATA) public data: EventContentDialogData,
public dialogRef: MatDialogRef<EventContentDialogComponent>,
protected dialogRef: MatDialogRef<EventContentDialogComponent>,
private renderer: Renderer2) {
super(store, router, dialogRef);
}
ngOnInit(): void {
this.content = this.data.content;
this.title = this.data.title;
this.contentType = this.data.contentType;
this.createEditor(this.eventContentEditorElmRef, this.content);
this.createEditor(this.eventContentEditorElmRef, this.data.content);
}
ngOnDestroy(): void {
if (this.aceEditor) {
this.aceEditor.destroy();
}
this.aceEditor?.destroy();
super.ngOnDestroy();
}
isJson(str) {
private isJson(str: string) {
try {
return isLiteralObject(JSON.parse(str));
} catch (e) {
@ -81,78 +79,53 @@ export class EventContentDialogComponent extends DialogComponent<EventContentDia
}
}
createEditor(editorElementRef: ElementRef, content: string) {
private createEditor(editorElementRef: ElementRef, content: string) {
const editorElement = editorElementRef.nativeElement;
let mode = 'java';
let content$: Observable<string> = null;
if (this.contentType) {
mode = contentTypesMap.get(this.contentType).code;
if (this.contentType === ContentType.JSON && content) {
content$ = beautifyJs(content, {indent_size: 4});
content$ = beautifyJs(content, {indent_size: 2});
} else if (this.contentType === ContentType.BINARY && content) {
try {
const decodedData = base64toString(content);
if (this.isJson(decodedData)) {
mode = 'json';
content$ = beautifyJs(decodedData, {indent_size: 4});
content$ = beautifyJs(decodedData, {indent_size: 2});
} else {
content$ = of(decodedData);
}
} catch (e) {}
} catch (e) {/**/}
}
}
if (!content$) {
content$ = of(content);
}
content$.subscribe(
(processedContent) => {
let editorOptions: Partial<Ace.EditorOptions> = {
mode: `ace/mode/${mode}`,
theme: 'ace/theme/github',
showGutter: false,
showPrintMargin: false,
readOnly: true
};
const advancedOptions = {
enableSnippets: false,
enableBasicAutocompletion: false,
enableLiveAutocompletion: false
};
editorOptions = {...editorOptions, ...advancedOptions};
getAce().subscribe(
(ace) => {
this.aceEditor = ace.edit(editorElement, editorOptions);
this.aceEditor.session.setUseWrapMode(false);
this.aceEditor.setValue(processedContent, -1);
this.updateEditorSize(editorElement, processedContent, this.aceEditor);
}
);
}
);
}
updateEditorSize(editorElement: any, content: string, editor: Ace.Editor) {
let newHeight = 400;
let newWidth = 600;
if (content && content.length > 0) {
const lines = content.split('\n');
newHeight = 17 * lines.length + 16;
let maxLineLength = 0;
lines.forEach((row) => {
const line = row.replace(/\t/g, ' ').replace(/\n/g, '');
const lineLength = line.length;
maxLineLength = Math.max(maxLineLength, lineLength);
});
newWidth = 9 * maxLineLength + 16;
}
// newHeight = Math.min(400, newHeight);
this.renderer.setStyle(editorElement, 'minHeight', newHeight.toString() + 'px');
this.renderer.setStyle(editorElement, 'height', newHeight.toString() + 'px');
this.renderer.setStyle(editorElement, 'width', newWidth.toString() + 'px');
editor.resize();
content$.subscribe((processedContent) => {
const isJSON = mode === 'json' && processedContent !== '{}';
this.showBorder = isJSON;
const editorOptions: Partial<Ace.EditorOptions> = {
mode: `ace/mode/${mode}`,
theme: 'ace/theme/github',
showGutter: isJSON,
showFoldWidgets: true,
foldStyle: 'markbeginend',
showPrintMargin: false,
readOnly: true,
enableSnippets: false,
enableBasicAutocompletion: false,
enableLiveAutocompletion: false,
};
getAce().subscribe(
(ace) => {
this.aceEditor = ace.edit(editorElement, editorOptions);
this.aceEditor.session.setUseWrapMode(false);
this.aceEditor.setValue(processedContent, -1);
updateEditorSize(editorElement, processedContent, this.aceEditor, this.renderer, {showGutter: isJSON});
}
)
});
}
}

11
ui-ngx/src/app/shared/components/entity/entity-subtype-list.component.ts

@ -14,7 +14,7 @@
/// limitations under the License.
///
import { AfterViewInit, Component, ElementRef, forwardRef, Input, OnDestroy, OnInit, ViewChild } from '@angular/core';
import { Component, ElementRef, forwardRef, Input, OnDestroy, OnInit, ViewChild } from '@angular/core';
import { ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR, Validators } from '@angular/forms';
import { Observable, ReplaySubject, Subscription, throwError } from 'rxjs';
import { debounceTime, map, mergeMap, share } from 'rxjs/operators';
@ -46,7 +46,7 @@ import { CalculatedFieldsService } from "@core/http/calculated-fields.service";
}
]
})
export class EntitySubTypeListComponent implements ControlValueAccessor, OnInit, AfterViewInit, OnDestroy {
export class EntitySubTypeListComponent implements ControlValueAccessor, OnInit, OnDestroy {
entitySubtypeListFormGroup: FormGroup;
@ -119,7 +119,7 @@ export class EntitySubTypeListComponent implements ControlValueAccessor, OnInit,
private dirty = false;
private propagateChange = (v: any) => { };
private propagateChange = (_v: any) => { };
private hasPageDataEntitySubTypes = new Set<EntityType>([
EntityType.ALARM,
@ -225,9 +225,6 @@ export class EntitySubTypeListComponent implements ControlValueAccessor, OnInit,
);
}
ngAfterViewInit(): void {
}
ngOnDestroy(): void {
if (this.broadcastSubscription) {
this.broadcastSubscription.unsubscribe();
@ -335,7 +332,7 @@ export class EntitySubTypeListComponent implements ControlValueAccessor, OnInit,
subTypesPagesObservable = this.alarmService.getAlarmTypes(pageLink, {ignoreLoading: true});
break;
case EntityType.CALCULATED_FIELD:
subTypesCfPagesObservable = this.calculatedFieldsService.getAlarmRuleNames(pageLink, CalculatedFieldType.ALARM, {ignoreLoading: true});
subTypesCfPagesObservable = this.calculatedFieldsService.getCalculatedFieldNames(pageLink, CalculatedFieldType.ALARM, {ignoreLoading: true});
}
if (subTypesPagesObservable) {
this.entitySubtypes = subTypesPagesObservable.pipe(

1
ui-ngx/src/app/shared/components/hint-tooltip-icon.component.scss

@ -17,7 +17,6 @@
display: flex;
flex-direction: row;
align-items: center;
gap: 4px;
}
:host {

88
ui-ngx/src/app/shared/components/json-object-view.component.ts

@ -15,14 +15,11 @@
///
import { Component, ElementRef, forwardRef, Input, OnDestroy, OnInit, Renderer2, ViewChild } from '@angular/core';
import { NG_VALUE_ACCESSOR } from '@angular/forms';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
import { Ace } from 'ace-builds';
import { coerceBooleanProperty } from '@angular/cdk/coercion';
import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state';
import { RafService } from '@core/services/raf.service';
import { isDefinedAndNotNull, isUndefined } from '@core/utils';
import { getAce } from '@shared/models/ace/ace.models';
import { getAce, updateEditorSize } from '@shared/models/ace/ace.models';
import { coerceBoolean } from '@shared/decorators/coercion';
@Component({
selector: 'tb-json-object-view',
@ -36,7 +33,7 @@ import { getAce } from '@shared/models/ace/ace.models';
}
]
})
export class JsonObjectViewComponent implements OnInit, OnDestroy {
export class JsonObjectViewComponent implements OnInit, OnDestroy, ControlValueAccessor {
@ViewChild('jsonViewer', {static: true})
jsonViewerElmRef: ElementRef;
@ -55,96 +52,54 @@ export class JsonObjectViewComponent implements OnInit, OnDestroy {
@Input() sort: (key: string, value: any) => any;
private widthValue: boolean;
get autoWidth(): boolean {
return this.widthValue;
}
@Input()
set autoWidth(value: boolean) {
this.widthValue = coerceBooleanProperty(value);
}
private heigthValue: boolean;
get autoHeight(): boolean {
return this.heigthValue;
}
@coerceBoolean()
autoWidth: boolean
@Input()
set autoHeight(value: boolean) {
this.heigthValue = coerceBooleanProperty(value);
}
@coerceBoolean()
autoHeight: boolean
constructor(public elementRef: ElementRef,
protected store: Store<AppState>,
private raf: RafService,
private renderer: Renderer2) {
constructor(private renderer: Renderer2) {
}
ngOnInit(): void {
this.viewerElement = this.jsonViewerElmRef.nativeElement;
let editorOptions: Partial<Ace.EditorOptions> = {
const editorOptions: Partial<Ace.EditorOptions> = {
mode: 'ace/mode/java',
theme: 'ace/theme/github',
showGutter: false,
showPrintMargin: false,
readOnly: true
};
const advancedOptions = {
readOnly: true,
enableSnippets: false,
enableBasicAutocompletion: false,
enableLiveAutocompletion: false
};
editorOptions = {...editorOptions, ...advancedOptions};
getAce().subscribe(
(ace) => {
this.jsonViewer = ace.edit(this.viewerElement, editorOptions);
this.jsonViewer.session.setUseWrapMode(false);
this.jsonViewer.setValue(this.contentValue ? this.contentValue : '', -1);
if (this.contentValue && (this.widthValue || this.heigthValue)) {
this.updateEditorSize(this.viewerElement, this.contentValue, this.jsonViewer);
if (this.contentValue && (this.autoWidth || this.autoHeight)) {
updateEditorSize(this.viewerElement, this.contentValue, this.jsonViewer, this.renderer, {
ignoreHeight: !this.autoHeight,
ignoreWidth: !this.autoWidth
});
}
}
);
}
ngOnDestroy(): void {
if (this.jsonViewer) {
this.jsonViewer.destroy();
}
this.jsonViewer?.destroy();
}
updateEditorSize(editorElement: any, content: string, editor: Ace.Editor) {
let newHeight = 200;
let newWidth = 600;
if (content && content.length > 0) {
const lines = content.split('\n');
newHeight = 17 * lines.length + 17;
let maxLineLength = 0;
lines.forEach((row) => {
const line = row.replace(/\t/g, ' ').replace(/\n/g, '');
const lineLength = line.length;
maxLineLength = Math.max(maxLineLength, lineLength);
});
newWidth = 8 * maxLineLength + 16;
}
if (this.heigthValue) {
this.renderer.setStyle(editorElement, 'height', newHeight.toString() + 'px');
}
if (this.widthValue) {
this.renderer.setStyle(editorElement, 'width', newWidth.toString() + 'px');
}
editor.resize();
}
registerOnChange(fn: any): void {
this.propagateChange = fn;
}
registerOnTouched(fn: any): void {
registerOnTouched(_fn: any): void {
}
writeValue(value: any): void {
@ -162,8 +117,11 @@ export class JsonObjectViewComponent implements OnInit, OnDestroy {
}
if (this.jsonViewer) {
this.jsonViewer.setValue(this.contentValue ? this.contentValue : '', -1);
if (this.contentValue && (this.widthValue || this.heigthValue)) {
this.updateEditorSize(this.viewerElement, this.contentValue, this.jsonViewer);
if (this.contentValue && (this.autoWidth || this.autoHeight)) {
updateEditorSize(this.viewerElement, this.contentValue, this.jsonViewer, this.renderer, {
ignoreHeight: !this.autoHeight,
ignoreWidth: !this.autoWidth
});
}
}
}

16
ui-ngx/src/app/shared/import-export/import-dialog-csv.component.ts

@ -39,7 +39,7 @@ import {
import { ImportExportService } from '@shared/import-export/import-export.service';
import { TableColumnsAssignmentComponent } from '@shared/import-export/table-columns-assignment.component';
import { Ace } from 'ace-builds';
import { getAce } from '@shared/models/ace/ace.models';
import { getAce, updateEditorSize } from '@shared/models/ace/ace.models';
export interface ImportDialogCsvData {
entityType: EntityType;
@ -283,21 +283,9 @@ export class ImportDialogCsvComponent extends DialogComponent<ImportDialogCsvCom
this.aceEditor = ace.edit(editorElement, editorOptions);
this.aceEditor.session.setUseWrapMode(false);
this.aceEditor.setValue(content, -1);
this.updateEditorSize(editorElement, content, this.aceEditor);
updateEditorSize(editorElement, content, this.aceEditor, this.renderer, {setMinHeight: true, ignoreWidth: true});
}
);
}
private updateEditorSize(editorElement: any, content: string, editor: Ace.Editor) {
let newHeight = 200;
if (content && content.length > 0) {
const lines = content.split('\n');
newHeight = 16 * lines.length + 24;
}
const minHeight = Math.min(200, newHeight);
this.renderer.setStyle(editorElement, 'minHeight', minHeight.toString() + 'px');
this.renderer.setStyle(editorElement, 'height', newHeight.toString() + 'px');
editor.resize();
}
}

41
ui-ngx/src/app/shared/models/ace/ace.models.ts

@ -19,6 +19,7 @@ import { Observable } from 'rxjs/internal/Observable';
import { forkJoin, from, of } from 'rxjs';
import { map, mergeMap, tap } from 'rxjs/operators';
import { unwrapModule } from '@core/utils';
import { Renderer2 } from '@angular/core';
let aceDependenciesLoaded = false;
let aceModule: any;
@ -98,6 +99,46 @@ export function getAceDiff(): Observable<any> {
}
}
export function updateEditorSize(editorElement: any, content: string, editor: Ace.Editor, renderer: Renderer2, options?: {
showGutter?: boolean,
ignoreHeight?: boolean,
ignoreWidth?: boolean,
setMinHeight?: boolean
}): void {
let newHeight = 200;
let newWidth = 600;
if (content && content.length > 0) {
if (editor.renderer.lineHeight <= 0) {
editor.renderer.updateFull(true);
}
const lines = content.split('\n');
newHeight = editor.renderer.lineHeight * lines.length + 16;
let maxLineLength = 0;
lines.forEach((row) => {
const line = row.replace(/\t/g, ' ').replace(/\n/g, '');
const lineLength = line.length;
maxLineLength = Math.max(maxLineLength, lineLength);
});
if (options?.showGutter) {
maxLineLength += lines.length.toString().length;
}
newWidth = 10 * maxLineLength + 16;
if (options?.showGutter) {
newWidth += 32;
}
}
if (!options.ignoreHeight) {
renderer.setStyle(editorElement, 'height', newHeight.toString() + 'px');
}
if (options.setMinHeight) {
renderer.setStyle(editorElement, 'minHeight', newHeight.toString() + 'px');
}
if (!options.ignoreWidth) {
renderer.setStyle(editorElement, 'width', newWidth.toString() + 'px');
}
editor.resize();
}
export class Range implements Ace.Range {
public start: Ace.Point;

2
ui-ngx/src/app/shared/models/calculated-field.models.ts

@ -79,6 +79,8 @@ export type CalculatedField =
| CalculatedFieldRelatedEntityAggregation
| CalculatedFieldAlarmRule;
export type CalculatedFieldInfo = CalculatedField & {entityName: string};
export enum CalculatedFieldType {
SIMPLE = 'SIMPLE',
SCRIPT = 'SCRIPT',

26
ui-ngx/src/assets/locale/locale.constant-en_US.json

@ -1108,9 +1108,9 @@
"geofencing" : "Geofencing",
"propagation": "Propagation",
"related-entities-aggregation": "Related entities aggregation",
"related-entities-aggregation-hint": "Aggregation of data from related entities",
"related-entities-aggregation-hint": "Aggregation of data from related entities.",
"time-series-data-aggregation": "Time series data aggregation",
"time-series-data-aggregation-hint": "Aggregation of historical data from a current entity"
"time-series-data-aggregation-hint": "Aggregation of historical data from a current entity."
},
"arguments": "Arguments",
"decimals-by-default": "Decimals by default",
@ -1287,9 +1287,9 @@
},
"aggregate-interval-type": "Aggregate interval type",
"aggregate-interval-value": "Aggregate interval value",
"aggregate-interval-value-required": "Aggregate interval value is required",
"aggregate-interval-value-min": "Aggregate interval value should be at least { sec, plural, =0 {0 second} =1 {1 second} other {# seconds} }",
"aggregate-interval-value-step-multiple-of": "Aggregate interval value must be a divisor or multiple of 1 day",
"aggregate-interval-value-required": "Aggregate interval value is required.",
"aggregate-interval-value-min": "Aggregate interval value should be at least { sec, plural, =0 {0 second} =1 {1 second} other {# seconds} }.",
"aggregate-interval-value-step-multiple-of": "Aggregate interval value must be a divisor or multiple of 1 day.",
"aggregate-period": {
"hour": "Hour",
"day": "Day",
@ -1301,23 +1301,23 @@
"custom": "Custom"
},
"aggregate-period-hint-offset": "Your aggregation interval will be: {{ interval }}",
"aggregate-period-hint-offset-and-so-on": "Your aggregation interval will be: {{ interval }} and so on",
"aggregate-period-hint-offset-and-so-on": "Your aggregation interval will be: {{ interval }} and so on.",
"entity-aggregation": {
"argument-hint": "Data will be fetched from current entity",
"argument-hint": "Data will be fetched from current entity.",
"argument-setting-hint": "Latest telemetry is the only available argument type for this calculated field.",
"aggregation-interval": "Aggregation interval",
"aggregation-interval-hint": "Defines how often to perform aggregation. Example: every 1 hour aggregates data at 00:00, 01:00, 02:00, etc.",
"apply-offset": "Apply offset to aggregation interval",
"apply-offset-hint": "Defines how much to shift the start of each aggregation period (e.g., +10 minutes - 00:10, 01:10).",
"offset-value": "Offset value",
"offset-value-required": "Offset value is required",
"offset-value-min": "Offset value must be a positive integer",
"offset-value-max": "Offset value should be less than the aggregate interval value",
"offset-value-required": "Offset value is required.",
"offset-value-min": "Offset value must be a positive integer.",
"offset-value-max": "Offset value should be less than the aggregate interval value.",
"wait-delay": "Apply await timeout for delayed telemetry",
"wait-delay-hint": "Defines how long to wait for delayed telemetry after the interval ends. If such telemetry arrives, the result for that interval will be recalculated.",
"duration": "Duration",
"duration-required": "Duration is required",
"duration-min": "Duration should be at least 1 minute",
"duration-required": "Duration is required.",
"duration-min": "Duration should be at least 1 minute.",
"duration-hint": "How long to wait for delayed data after the interval ends.",
"produce-intermediate-result": "Produce intermediate result",
"produce-intermediate-result-hint": "Calculates metrics during the current interval to produce an intermediate result. Updates occur no more often than once every {{ time }}."
@ -1488,7 +1488,7 @@
"alarm-rule-additional-info-hint": "Hint: use <code><span style=\"color: #000;\">$&#123;</span>Argument name<span style=\"color: #000;\">&#125;</span></code> to substitute values of the arguments that are used in alarm rule condition.",
"alarm-rule-additional-info-icon-hint": "Use Argument name to substitute values of the arguments that are used in alarm rule condition.",
"alarm-rule-mobile-dashboard": "Mobile dashboard",
"alarm-rule-mobile-dashboard-hint": "Used by mobile application as an alarm details dashboard",
"alarm-rule-mobile-dashboard-hint": "Used by mobile application as an alarm details dashboard.",
"alarm-rule-no-mobile-dashboard": "No dashboard selected",
"alarm-rule-condition": "Alarm rule condition",
"enter-alarm-rule-condition-prompt": "Add condition",

14
ui-ngx/src/form.scss

@ -178,10 +178,11 @@
}
&.tb-required::after {
font-size: 13px;
color: rgba(0, 0, 0, .54);
font-size: inherit;
color: inherit;
vertical-align: top;
content: " *";
content: "*";
margin-left: 1px;
}
}
.tb-form-panel-hint {
@ -298,10 +299,11 @@
margin: 8px 0;
}
.tb-required::after {
font-size: 13px;
color: rgba(0, 0, 0, .54);
font-size: inherit;
color: inherit;
vertical-align: top;
content: " *";
content: "*";
margin-left: 1px;
}
}

Loading…
Cancel
Save