From 1b34519f2bdd7c870c4cca62907c2db2187672c2 Mon Sep 17 00:00:00 2001 From: Vladyslav_Prykhodko Date: Mon, 30 Sep 2024 10:16:08 +0300 Subject: [PATCH 01/34] Updated unsupported Node.js dependencies from version 16.20.2 to 18.20.4 LTS --- msa/js-executor/pom.xml | 2 +- msa/web-ui/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/msa/js-executor/pom.xml b/msa/js-executor/pom.xml index e123790066..c16cf662ec 100644 --- a/msa/js-executor/pom.xml +++ b/msa/js-executor/pom.xml @@ -71,7 +71,7 @@ install-node-and-yarn - v16.20.2 + v18.20.4 v1.22.17 diff --git a/msa/web-ui/pom.xml b/msa/web-ui/pom.xml index f2e626c7c1..0625dee9e7 100644 --- a/msa/web-ui/pom.xml +++ b/msa/web-ui/pom.xml @@ -80,7 +80,7 @@ install-node-and-yarn - v16.20.2 + v18.20.4 v1.22.17 From 4d2ac77c4adbab62f69fe8e394af4980cf43c032 Mon Sep 17 00:00:00 2001 From: IrynaMatveieva Date: Wed, 16 Oct 2024 10:17:58 +0300 Subject: [PATCH 02/34] fixed upgrade --- .../engine/metadata/TbGetTelemetryNode.java | 37 ++++++++++++++----- .../metadata/TbGetTelemetryNodeTest.java | 32 ++++++++++++++++ 2 files changed, 59 insertions(+), 10 deletions(-) diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTelemetryNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTelemetryNode.java index 2b5190563d..3a6f1dd9c4 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTelemetryNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTelemetryNode.java @@ -52,7 +52,7 @@ import java.util.stream.Collectors; @RuleNode(type = ComponentType.ENRICHMENT, name = "originator telemetry", configClazz = TbGetTelemetryNodeConfiguration.class, - version = 1, + version = 2, nodeDescription = "Adds message originator telemetry for selected time range into message metadata", nodeDetails = "Useful when you need to get telemetry data set from the message originator for a specific time range " + "instead of fetching just the latest telemetry or if you need to get the closest telemetry to the fetch interval start or end. " + @@ -232,21 +232,21 @@ public class TbGetTelemetryNode implements TbNode { public TbPair upgrade(int fromVersion, JsonNode oldConfiguration) throws TbNodeException { boolean hasChanges = false; switch (fromVersion) { - case 0 -> { + case 0: { if (oldConfiguration.hasNonNull("fetchMode")) { String fetchMode = oldConfiguration.get("fetchMode").asText(); switch (fetchMode) { - case "FIRST": + case "FIRST" -> { ((ObjectNode) oldConfiguration).put("orderBy", Direction.ASC.name()); ((ObjectNode) oldConfiguration).put("aggregation", Aggregation.NONE.name()); hasChanges = true; - break; - case "LAST": + } + case "LAST" -> { ((ObjectNode) oldConfiguration).put("orderBy", Direction.DESC.name()); ((ObjectNode) oldConfiguration).put("aggregation", Aggregation.NONE.name()); hasChanges = true; - break; - case "ALL": + } + case "ALL" -> { if (oldConfiguration.has("orderBy") && (oldConfiguration.get("orderBy").isNull() || oldConfiguration.get("orderBy").asText().isEmpty())) { ((ObjectNode) oldConfiguration).put("orderBy", Direction.ASC.name()); @@ -257,16 +257,33 @@ public class TbGetTelemetryNode implements TbNode { ((ObjectNode) oldConfiguration).put("aggregation", Aggregation.NONE.name()); hasChanges = true; } - break; - default: + } + default -> { ((ObjectNode) oldConfiguration).put("fetchMode", FetchMode.LAST.name()); ((ObjectNode) oldConfiguration).put("orderBy", Direction.DESC.name()); ((ObjectNode) oldConfiguration).put("aggregation", Aggregation.NONE.name()); hasChanges = true; - break; + } } } } + case 1: { + if (!oldConfiguration.hasNonNull("limit")) { + ((ObjectNode) oldConfiguration).put("limit", 1000); + hasChanges = true; + } + if (oldConfiguration.has("fetchMode") && oldConfiguration.get("fetchMode").asText().equals("ALL")) { + if (!oldConfiguration.hasNonNull("aggregation")) { + ((ObjectNode) oldConfiguration).put("aggregation", Aggregation.NONE.name()); + hasChanges = true; + } + if (!oldConfiguration.hasNonNull("orderBy")) { + ((ObjectNode) oldConfiguration).put("orderBy", Direction.ASC.name()); + hasChanges = true; + } + } + break; + } } return new TbPair<>(hasChanges, oldConfiguration); } diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetTelemetryNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetTelemetryNodeTest.java index f2d4a41fbc..87f273df93 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetTelemetryNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetTelemetryNodeTest.java @@ -637,6 +637,38 @@ public class TbGetTelemetryNodeTest extends AbstractRuleNodeUpgradeTest { "endInterval": 1, "endIntervalTimeUnit": "MINUTES" } + """), + // config for version 0 (fetchMode is 'ALL' and limit, aggregation and orderBy do not exist) + Arguments.of(0, + """ + { + "latestTsKeyNames": ["key"], + "fetchMode": "ALL", + "useMetadataIntervalPatterns": false, + "startIntervalPattern": "", + "endIntervalPattern": "", + "startInterval": 2, + "startIntervalTimeUnit": "MINUTES", + "endInterval": 1, + "endIntervalTimeUnit": "MINUTES" + } + """, + true, + """ + { + "latestTsKeyNames": ["key"], + "aggregation": "NONE", + "fetchMode": "ALL", + "orderBy": "ASC", + "limit": 1000, + "useMetadataIntervalPatterns": false, + "startIntervalPattern": "", + "endIntervalPattern": "", + "startInterval": 2, + "startIntervalTimeUnit": "MINUTES", + "endInterval": 1, + "endIntervalTimeUnit": "MINUTES" + } """) ); } From 4bd0697ea67ed31b4c52ff5a930f9c76f778c8ac Mon Sep 17 00:00:00 2001 From: mpetrov Date: Thu, 17 Oct 2024 18:34:41 +0300 Subject: [PATCH 03/34] Fixed remote shell request spam on exit --- .../main/data/json/system/widget_types/rpc_remote_shell.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/application/src/main/data/json/system/widget_types/rpc_remote_shell.json b/application/src/main/data/json/system/widget_types/rpc_remote_shell.json index 91d2a64788..47f0472f2d 100644 --- a/application/src/main/data/json/system/widget_types/rpc_remote_shell.json +++ b/application/src/main/data/json/system/widget_types/rpc_remote_shell.json @@ -11,7 +11,7 @@ "resources": [], "templateHtml": "
", "templateCss": ".cmd .cursor.blink {\n -webkit-animation-name: terminal-underline;\n -moz-animation-name: terminal-underline;\n -ms-animation-name: terminal-underline;\n animation-name: terminal-underline;\n}\n.terminal .inverted, .cmd .inverted {\n border-bottom-color: #aaa;\n}\n", - "controllerScript": "var requestTimeout = 500;\nvar commandStatusPollingInterval = 200;\n\nvar welcome = 'Welcome to ThingsBoard RPC remote shell.\\n';\n\nvar terminal, rpcEnabled, simulated, deviceName, cwd;\nvar commandExecuting = false;\n\nself.onInit = function() {\n var subscription = self.ctx.defaultSubscription;\n rpcEnabled = subscription.rpcEnabled;\n if (subscription.targetEntityName && subscription.targetEntityName.length) {\n deviceName = subscription.targetEntityName;\n } else {\n deviceName = 'Simulated';\n simulated = true;\n }\n if (self.ctx.settings.requestTimeout) {\n requestTimeout = self.ctx.settings.requestTimeout;\n }\n\n terminal = $('#device-terminal', self.ctx.$container).terminal(\n function (command) {\n if (command && command.trim().length) {\n try {\n if (simulated) {\n this.echo(command);\n } else {\n sendCommand(this, command);\n }\n } catch(e) {\n this.error(e + '');\n }\n } else {\n this.echo('');\n }\n }, {\n greetings: false,\n enabled: rpcEnabled,\n prompt: rpcEnabled ? currentPrompt : '',\n name: 'shell',\n pauseEvents: false,\n keydown: function (e, term) {\n if ((e.which == 67 || e.which == 68) && e.ctrlKey) { // CTRL+C || CTRL+D\n if (commandExecuting) {\n terminateCommand(term);\n return false;\n }\n }\n },\n onInit: initTerm\n }\n );\n};\n\nfunction initTerm(terminal) {\n terminal.echo(welcome);\n if (!rpcEnabled) {\n terminal.error('Target device is not set!\\n');\n } else {\n terminal.echo('Current target device for RPC terminal: [[b;#fff;]' + deviceName + ']\\n');\n if (!simulated) {\n terminal.pause();\n getTermInfo(terminal, function (remoteTermInfo) {\n if (remoteTermInfo) {\n terminal.echo('Remote platform info:');\n if (remoteTermInfo.platform) {\n terminal.echo('OS: [[b;#fff;]' + remoteTermInfo.platform + ']');\n } else {\n terminal.echo('OS: [[;#f00;]Unknown]');\n }\n if (remoteTermInfo.release) {\n terminal.echo('OS release: [[b;#fff;]' + remoteTermInfo.release + ']');\n } else {\n terminal.echo('OS release: [[;#f00;]Unknown]');\n }\n terminal.echo('\\r');\n } else {\n terminal.echo('[[;#f00;]Unable to get remote platform info.\\nDevice is not responding.]\\n');\n }\n terminal.resume();\n });\n }\n }\n}\n\nfunction currentPrompt(callback) {\n if (cwd) {\n callback('[[b;#2196f3;]' + deviceName + ']: [[b;#8bc34a;]' + cwd + ']> ');\n } else {\n callback('[[b;#8bc34a;]' + deviceName + ']> ');\n }\n}\n\nfunction getTermInfo(terminal, callback) {\n self.ctx.controlApi.sendTwoWayCommand('getTermInfo', null, requestTimeout).subscribe(\n function(response) {\n let termInfo;\n if (typeof response === 'string') {\n try {\n termInfo = JSON.parse(response);\n } catch (e) {\n terminal.error('Error parsing response: ' + e);\n callback(null);\n return;\n }\n } else {\n termInfo = response;\n }\n if (termInfo && termInfo.cwd) {\n cwd = termInfo.cwd;\n }\n if (callback) {\n callback(termInfo);\n }\n },\n function() {\n if (callback) {\n callback(null);\n }\n }\n );\n}\n\nfunction sendCommand(terminal, command) {\n terminal.pause();\n var sendCommandRequest = {\n command: command,\n cwd: cwd\n };\n self.ctx.controlApi.sendTwoWayCommand('sendCommand', sendCommandRequest, requestTimeout).subscribe(\n function (responseBody) {\n if (responseBody && responseBody.ok) {\n commandExecuting = true;\n setTimeout(pollCommandStatus.bind(null, terminal), commandStatusPollingInterval);\n } else {\n var error = responseBody ? responseBody.error : 'Unhandled error.';\n terminal.error(error);\n terminal.resume();\n }\n },\n function () {\n onRpcError(terminal);\n }\n );\n}\n\nfunction terminateCommand(terminal) {\n self.ctx.controlApi.sendTwoWayCommand('terminateCommand', null, requestTimeout).subscribe(\n function (responseBody) {\n if (!responseBody.ok) {\n commandExecuting = false;\n terminal.error(responseBody.error);\n terminal.resume();\n }\n },\n function () {\n onRpcError(terminal);\n }\n );\n}\n\nfunction onRpcError(terminal) {\n var errorText = self.ctx.defaultSubscription.rpcErrorText;\n terminal.error(errorText);\n terminal.resume();\n}\n\nfunction pollCommandStatus(terminal) {\n self.ctx.controlApi.sendTwoWayCommand('getCommandStatus', null, requestTimeout).subscribe(\n function (commandStatusResponse) {\n for (var i = 0; i < commandStatusResponse.data.length; i++) {\n var dataElement = commandStatusResponse.data[i];\n if (dataElement.stdout) {\n terminal.echo(dataElement.stdout);\n }\n if (dataElement.stderr) {\n terminal.error(dataElement.stderr);\n }\n }\n if (commandStatusResponse.done) {\n commandExecuting = false;\n cwd = commandStatusResponse.cwd;\n terminal.resume();\n } else {\n var interval = commandStatusPollingInterval;\n if (!commandStatusResponse.data.length) {\n interval *= 5;\n }\n setTimeout(pollCommandStatus.bind(null, terminal), interval);\n }\n },\n function () {\n commandExecuting = false;\n onRpcError(terminal);\n }\n );\n}\n\nself.onResize = function () {\n if (terminal) {\n terminal.resize(self.ctx.width, self.ctx.height);\n }\n};\n\nself.onDestroy = function() {\n};", + "controllerScript": "var requestTimeout = 500;\nvar commandStatusPollingInterval = 200;\n\nvar welcome = 'Welcome to ThingsBoard RPC remote shell.\\n';\n\nvar terminal, rpcEnabled, simulated, deviceName, cwd;\nvar commandExecuting = false;\n\nself.onInit = function() {\n var subscription = self.ctx.defaultSubscription;\n rpcEnabled = subscription.rpcEnabled;\n if (subscription.targetEntityName && subscription.targetEntityName.length) {\n deviceName = subscription.targetEntityName;\n } else {\n deviceName = 'Simulated';\n simulated = true;\n }\n if (self.ctx.settings.requestTimeout) {\n requestTimeout = self.ctx.settings.requestTimeout;\n }\n\n terminal = $('#device-terminal', self.ctx.$container).terminal(\n function (command) {\n if (command && command.trim().length) {\n try {\n if (command.trim() === 'exit') {\n if (!simulated) {\n self.ctx.controlApi.sendTwoWayCommand('sendCommand', {\n command: 'exit',\n cwd: cwd\n }, requestTimeout).subscribe();\n }\n this.disable();\n return;\n }\n if (simulated) {\n this.echo(command);\n } else {\n sendCommand(this, command);\n }\n } catch(e) {\n this.error(e + '');\n }\n } else {\n this.echo('');\n }\n }, {\n greetings: false,\n enabled: rpcEnabled,\n prompt: rpcEnabled ? currentPrompt : '',\n name: 'shell',\n pauseEvents: false,\n keydown: function (e, term) {\n if ((e.which == 67 || e.which == 68) && e.ctrlKey) { // CTRL+C || CTRL+D\n if (commandExecuting) {\n terminateCommand(term);\n return false;\n }\n }\n },\n onInit: initTerm\n }\n );\n};\n\nfunction initTerm(terminal) {\n terminal.echo(welcome);\n if (!rpcEnabled) {\n terminal.error('Target device is not set!\\n');\n } else {\n terminal.echo('Current target device for RPC terminal: [[b;#fff;]' + deviceName + ']\\n');\n if (!simulated) {\n terminal.pause();\n getTermInfo(terminal, function (remoteTermInfo) {\n if (remoteTermInfo) {\n terminal.echo('Remote platform info:');\n if (remoteTermInfo.platform) {\n terminal.echo('OS: [[b;#fff;]' + remoteTermInfo.platform + ']');\n } else {\n terminal.echo('OS: [[;#f00;]Unknown]');\n }\n if (remoteTermInfo.release) {\n terminal.echo('OS release: [[b;#fff;]' + remoteTermInfo.release + ']');\n } else {\n terminal.echo('OS release: [[;#f00;]Unknown]');\n }\n terminal.echo('\\r');\n } else {\n terminal.echo('[[;#f00;]Unable to get remote platform info.\\nDevice is not responding.]\\n');\n }\n terminal.resume();\n });\n }\n }\n}\n\nfunction currentPrompt(callback) {\n if (cwd) {\n callback('[[b;#2196f3;]' + deviceName + ']: [[b;#8bc34a;]' + cwd + ']> ');\n } else {\n callback('[[b;#8bc34a;]' + deviceName + ']> ');\n }\n}\n\nfunction getTermInfo(terminal, callback) {\n self.ctx.controlApi.sendTwoWayCommand('getTermInfo', null, requestTimeout).subscribe(\n function(response) {\n let termInfo;\n if (typeof response === 'string') {\n try {\n termInfo = JSON.parse(response);\n } catch (e) {\n terminal.error('Error parsing response: ' + e);\n callback(null);\n return;\n }\n } else {\n termInfo = response;\n }\n if (termInfo && termInfo.cwd) {\n cwd = termInfo.cwd;\n }\n if (callback) {\n callback(termInfo);\n }\n },\n function() {\n if (callback) {\n callback(null);\n }\n }\n );\n}\n\nfunction sendCommand(terminal, command) {\n terminal.pause();\n var sendCommandRequest = {\n command: command,\n cwd: cwd\n };\n self.ctx.controlApi.sendTwoWayCommand('sendCommand', sendCommandRequest, requestTimeout).subscribe(\n function (responseBody) {\n if (responseBody && responseBody.ok) {\n commandExecuting = true;\n setTimeout(pollCommandStatus.bind(null, terminal), commandStatusPollingInterval);\n } else {\n var error = responseBody ? responseBody.error : 'Unhandled error.';\n terminal.error(error);\n terminal.resume();\n }\n },\n function () {\n onRpcError(terminal);\n }\n );\n}\n\nfunction terminateCommand(terminal) {\n self.ctx.controlApi.sendTwoWayCommand('terminateCommand', null, requestTimeout).subscribe(\n function (responseBody) {\n if (!responseBody.ok) {\n commandExecuting = false;\n terminal.error(responseBody.error);\n terminal.resume();\n }\n },\n function () {\n onRpcError(terminal);\n }\n );\n}\n\nfunction onRpcError(terminal) {\n var errorText = self.ctx.defaultSubscription.rpcErrorText;\n terminal.error(errorText);\n terminal.resume();\n}\n\nfunction pollCommandStatus(terminal) {\n self.ctx.controlApi.sendTwoWayCommand('getCommandStatus', null, requestTimeout).subscribe(\n function (commandStatusResponse) {\n for (var i = 0; i < commandStatusResponse.data.length; i++) {\n var dataElement = commandStatusResponse.data[i];\n if (dataElement.stdout) {\n terminal.echo(dataElement.stdout);\n }\n if (dataElement.stderr) {\n terminal.error(dataElement.stderr);\n }\n }\n if (commandStatusResponse.done) {\n commandExecuting = false;\n cwd = commandStatusResponse.cwd;\n terminal.resume();\n } else {\n var interval = commandStatusPollingInterval;\n if (!commandStatusResponse.data.length) {\n interval *= 5;\n }\n setTimeout(pollCommandStatus.bind(null, terminal), interval);\n }\n },\n function () {\n commandExecuting = false;\n onRpcError(terminal);\n }\n );\n}\n\nself.onResize = function () {\n if (terminal) {\n terminal.resize(self.ctx.width, self.ctx.height);\n }\n};\n\nself.onDestroy = function() {\n};", "settingsSchema": "", "dataKeySettingsSchema": "{}\n", "settingsDirective": "tb-rpc-shell-widget-settings", From 0d9e8261e0ab7a77afea43784cb209ff0fb92968 Mon Sep 17 00:00:00 2001 From: d2eight Date: Thu, 24 Oct 2024 20:34:26 +0300 Subject: [PATCH 04/34] Adding outline appearance to the country input --- .../shared/components/country-autocomplete.component.html | 2 +- .../app/shared/components/country-autocomplete.component.ts | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/ui-ngx/src/app/shared/components/country-autocomplete.component.html b/ui-ngx/src/app/shared/components/country-autocomplete.component.html index eadf630dcd..c99ac037b2 100644 --- a/ui-ngx/src/app/shared/components/country-autocomplete.component.html +++ b/ui-ngx/src/app/shared/components/country-autocomplete.component.html @@ -15,7 +15,7 @@ limitations under the License. --> - + {{ labelText }} Date: Thu, 31 Oct 2024 16:51:00 +0200 Subject: [PATCH 05/34] Fixed sizing for codeblocks --- .../home/components/event/event-content-dialog.component.ts | 4 ++-- .../lib/home-page/getting-started-widget.component.scss | 2 +- ui-ngx/src/app/shared/components/markdown.component.scss | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/event/event-content-dialog.component.ts b/ui-ngx/src/app/modules/home/components/event/event-content-dialog.component.ts index 65b5be9b75..fb7b026914 100644 --- a/ui-ngx/src/app/modules/home/components/event/event-content-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/event/event-content-dialog.component.ts @@ -139,14 +139,14 @@ export class EventContentDialogComponent extends DialogComponent 0) { const lines = content.split('\n'); - newHeight = 16 * lines.length + 16; + 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 = 8 * maxLineLength + 16; + newWidth = 10 * maxLineLength + 16; } // newHeight = Math.min(400, newHeight); this.renderer.setStyle(editorElement, 'minHeight', newHeight.toString() + 'px'); diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/home-page/getting-started-widget.component.scss b/ui-ngx/src/app/modules/home/components/widget/lib/home-page/getting-started-widget.component.scss index 65eaf66c54..3e34cbdcd9 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/home-page/getting-started-widget.component.scss +++ b/ui-ngx/src/app/modules/home/components/widget/lib/home-page/getting-started-widget.component.scss @@ -118,7 +118,7 @@ padding: 0; pre[class*=language-] { margin: 0; - padding: 9px 38px 9px 16px; + padding: 10px 38px 10px 16px; background: rgba(0, 0, 0, 0.03); border-radius: 6px; border: none; diff --git a/ui-ngx/src/app/shared/components/markdown.component.scss b/ui-ngx/src/app/shared/components/markdown.component.scss index 0c5e310e07..c47a78011b 100644 --- a/ui-ngx/src/app/shared/components/markdown.component.scss +++ b/ui-ngx/src/app/shared/components/markdown.component.scss @@ -370,7 +370,7 @@ } &.line-numbers { - padding-left: 66px; + padding: 10px 16px 10px 66px; & > code { span.line-numbers-rows { From 9ec8617433405f482cb136718249714266b81679 Mon Sep 17 00:00:00 2001 From: mpetrov Date: Thu, 31 Oct 2024 16:51:28 +0200 Subject: [PATCH 06/34] Revert "Fixed sizing for codeblocks" This reverts commit 6d004fe2dc52c69e8f30a9717f5db0aa788898a2. --- .../home/components/event/event-content-dialog.component.ts | 4 ++-- .../lib/home-page/getting-started-widget.component.scss | 2 +- ui-ngx/src/app/shared/components/markdown.component.scss | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/event/event-content-dialog.component.ts b/ui-ngx/src/app/modules/home/components/event/event-content-dialog.component.ts index fb7b026914..65b5be9b75 100644 --- a/ui-ngx/src/app/modules/home/components/event/event-content-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/event/event-content-dialog.component.ts @@ -139,14 +139,14 @@ export class EventContentDialogComponent extends DialogComponent 0) { const lines = content.split('\n'); - newHeight = 18 * lines.length + 16; + newHeight = 16 * 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 = 10 * maxLineLength + 16; + newWidth = 8 * maxLineLength + 16; } // newHeight = Math.min(400, newHeight); this.renderer.setStyle(editorElement, 'minHeight', newHeight.toString() + 'px'); diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/home-page/getting-started-widget.component.scss b/ui-ngx/src/app/modules/home/components/widget/lib/home-page/getting-started-widget.component.scss index 3e34cbdcd9..65eaf66c54 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/home-page/getting-started-widget.component.scss +++ b/ui-ngx/src/app/modules/home/components/widget/lib/home-page/getting-started-widget.component.scss @@ -118,7 +118,7 @@ padding: 0; pre[class*=language-] { margin: 0; - padding: 10px 38px 10px 16px; + padding: 9px 38px 9px 16px; background: rgba(0, 0, 0, 0.03); border-radius: 6px; border: none; diff --git a/ui-ngx/src/app/shared/components/markdown.component.scss b/ui-ngx/src/app/shared/components/markdown.component.scss index c47a78011b..0c5e310e07 100644 --- a/ui-ngx/src/app/shared/components/markdown.component.scss +++ b/ui-ngx/src/app/shared/components/markdown.component.scss @@ -370,7 +370,7 @@ } &.line-numbers { - padding: 10px 16px 10px 66px; + padding-left: 66px; & > code { span.line-numbers-rows { From 9a1c03ac5df3902796a7257fcf68524fae320ee6 Mon Sep 17 00:00:00 2001 From: mpetrov Date: Thu, 31 Oct 2024 18:05:37 +0200 Subject: [PATCH 07/34] Updated autocomplete for AssetService --- .../models/ace/service-completion.models.ts | 102 ++++++++++-------- 1 file changed, 60 insertions(+), 42 deletions(-) diff --git a/ui-ngx/src/app/shared/models/ace/service-completion.models.ts b/ui-ngx/src/app/shared/models/ace/service-completion.models.ts index 5efc428194..709d670e6b 100644 --- a/ui-ngx/src/app/shared/models/ace/service-completion.models.ts +++ b/ui-ngx/src/app/shared/models/ace/service-completion.models.ts @@ -102,6 +102,10 @@ export const customDialogComponentHref = 'Resource info'; +export const bulkImportResultHref = 'Bulk import result'; + +export const bulkImportRequestHref = 'Bulk import request'; + export const pageLinkArg: FunctionArg = { name: 'pageLink', type: 'PageLink', @@ -366,27 +370,6 @@ export const serviceCompletions: TbEditorCompletions = { meta: 'service', type: 'AssetService', children: { - getTenantAssetInfos: { - description: 'Get tenant assets', - meta: 'function', - args: [ - pageLinkArg, - {name: 'type', type: 'string', optional: true, description: 'Asset type'}, - requestConfigArg - ], - return: observablePageDataReturnType(assetInfoHref) - }, - getCustomerAssetInfos: { - description: 'Get customer assets', - meta: 'function', - args: [ - {name: 'customerId', type: 'string', description: 'Id of the customer'}, - pageLinkArg, - {name: 'type', type: 'string', optional: true, description: 'Asset type'}, - requestConfigArg - ], - return: observablePageDataReturnType(assetInfoHref) - }, getAsset: { description: 'Get asset by id', meta: 'function', @@ -414,53 +397,80 @@ export const serviceCompletions: TbEditorCompletions = { ], return: observableReturnType(assetInfoHref) }, - saveAsset: { - description: 'Save asset', + getTenantAssets: { + description: 'Get assets for the tenant, filtered by type if provided', meta: 'function', args: [ - {name: 'asset', type: assetHref, description: 'Asset object to save'}, + pageLinkArg, + { name: 'type', type: 'string', description: 'Optional asset type filter' }, requestConfigArg ], - return: observableReturnType(assetHref) + return: observablePageDataReturnType(assetHref) }, - deleteAsset: { - description: 'Delete asset by id', + getCustomerAssets: { + description: 'Get assets for a specific customer, filtered by type if provided', meta: 'function', args: [ - {name: 'assetId', type: 'string', description: 'Id of the asset'}, + { name: 'customerId', type: 'string', description: 'Customer ID' }, + pageLinkArg, + { name: 'type', type: 'string', description: 'Optional asset type filter' }, requestConfigArg ], - return: observableVoid() + return: observablePageDataReturnType(assetHref) }, - getAssetTypes: { - description: 'Get all available assets types', + getUserAssets: { + description: 'Get assets associated with the user, filtered by type if provided', meta: 'function', args: [ + pageLinkArg, + { name: 'type', type: 'string', description: 'Optional asset type filter' }, requestConfigArg ], - return: observableArrayReturnType('EntitySubtype') + return: observablePageDataReturnType(assetHref) }, - makeAssetPublic: { - description: 'Make asset public (available from public dashboard)', + getAllAssetInfos: { + description: 'Get all asset information with optional customer inclusion', meta: 'function', args: [ - {name: 'assetId', type: 'string', description: 'Id of the asset'}, + { name: 'includeCustomers', type: 'boolean', description: 'Whether to include customers in the result' }, + pageLinkArg, + { name: 'assetProfileId', type: 'string', description: 'Optional asset profile ID' }, requestConfigArg ], - return: observableReturnType(assetHref) + return: observablePageDataReturnType(assetInfoHref) }, - assignAssetToCustomer: { - description: 'Assign asset to specific customer', + getCustomerAssetInfos: { + description: 'Get customer asset information with optional customer inclusion', meta: 'function', args: [ - {name: 'customerId', type: 'string', description: 'Id of the customer'}, - {name: 'assetId', type: 'string', description: 'Id of the asset'}, + { name: 'includeCustomers', type: 'boolean', description: 'Whether to include customers in the result' }, + { name: 'customerId', type: 'string', description: 'Customer ID' }, + pageLinkArg, + { name: 'assetProfileId', type: 'string', description: 'Optional asset profile ID' }, + requestConfigArg + ], + return: observablePageDataReturnType(assetInfoHref) + }, + bulkImportAssets: { + description: 'Bulk import assets with provided entities data', + meta: 'function', + args: [ + { name: 'entitiesData', type: bulkImportRequestHref, description: 'Data for bulk importing assets' }, + requestConfigArg + ], + return: observableReturnType(bulkImportResultHref) + }, + saveAsset: { + description: 'Save asset', + meta: 'function', + args: [ + {name: 'asset', type: assetHref, description: 'Asset object to save'}, requestConfigArg ], return: observableReturnType(assetHref) }, - unassignAssetFromCustomer: { - description: 'Unassign asset from any customer', + deleteAsset: { + description: 'Delete asset by id', meta: 'function', args: [ {name: 'assetId', type: 'string', description: 'Id of the asset'}, @@ -468,6 +478,14 @@ export const serviceCompletions: TbEditorCompletions = { ], return: observableVoid() }, + getAssetTypes: { + description: 'Get all available assets types', + meta: 'function', + args: [ + requestConfigArg + ], + return: observableArrayReturnType('EntitySubtype') + }, findByQuery: { description: 'Find assets by search query', meta: 'function', From bcbd115a19183876ee055df2ad491d86ee344280 Mon Sep 17 00:00:00 2001 From: ViacheslavKlimov Date: Thu, 31 Oct 2024 18:32:38 +0200 Subject: [PATCH 08/34] Queue providers deprecation: update message and yml description --- .../thingsboard/server/service/update/DeprecationService.java | 3 ++- application/src/main/resources/thingsboard.yml | 4 +++- .../server/dao/notification/DefaultNotifications.java | 3 ++- msa/vc-executor/src/main/resources/tb-vc-executor.yml | 4 +++- transport/coap/src/main/resources/tb-coap-transport.yml | 4 +++- transport/http/src/main/resources/tb-http-transport.yml | 4 +++- transport/lwm2m/src/main/resources/tb-lwm2m-transport.yml | 4 +++- transport/mqtt/src/main/resources/tb-mqtt-transport.yml | 4 +++- transport/snmp/src/main/resources/tb-snmp-transport.yml | 4 +++- 9 files changed, 25 insertions(+), 9 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/update/DeprecationService.java b/application/src/main/java/org/thingsboard/server/service/update/DeprecationService.java index ddb8080bcd..d4109ff420 100644 --- a/application/src/main/java/org/thingsboard/server/service/update/DeprecationService.java +++ b/application/src/main/java/org/thingsboard/server/service/update/DeprecationService.java @@ -55,7 +55,8 @@ public class DeprecationService { } } - log.warn("WARNING: {} queue type is deprecated and will be removed in ThingsBoard 4.0. Please migrate to Apache Kafka", queueTypeName); + log.warn("WARNING: Starting with ThingsBoard 4.0, {} will no longer be supported as a message queue for microservices. " + + "Please migrate to Apache Kafka. This change will not impact any rule nodes", queueTypeName); notificationCenter.sendGeneralWebNotification(TenantId.SYS_TENANT_ID, new SystemAdministratorsFilter(), DefaultNotifications.queueTypeDeprecation.toTemplate(), new GeneralNotificationInfo(Map.of( "queueType", queueTypeName diff --git a/application/src/main/resources/thingsboard.yml b/application/src/main/resources/thingsboard.yml index e9c8668958..8ff3bfb10e 100644 --- a/application/src/main/resources/thingsboard.yml +++ b/application/src/main/resources/thingsboard.yml @@ -1439,7 +1439,9 @@ swagger: # Queue configuration parameters queue: - type: "${TB_QUEUE_TYPE:in-memory}" # in-memory or kafka (Apache Kafka) or aws-sqs (AWS SQS) or pubsub (PubSub) or service-bus (Azure Service Bus) or rabbitmq (RabbitMQ) + # in-memory or kafka (Apache Kafka). The following queue types are deprecated and will no longer be supported in ThingsBoard 4.0: + # aws-sqs (AWS SQS), pubsub (PubSub), service-bus (Azure Service Bus), rabbitmq (RabbitMQ) + type: "${TB_QUEUE_TYPE:in-memory}" prefix: "${TB_QUEUE_PREFIX:}" # Global queue prefix. If specified, prefix is added before default topic name: 'prefix.default_topic_name'. Prefix is applied to all topics (and consumer groups for kafka). in_memory: stats: diff --git a/dao/src/main/java/org/thingsboard/server/dao/notification/DefaultNotifications.java b/dao/src/main/java/org/thingsboard/server/dao/notification/DefaultNotifications.java index 65a5763c5a..9b747766c9 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/notification/DefaultNotifications.java +++ b/dao/src/main/java/org/thingsboard/server/dao/notification/DefaultNotifications.java @@ -376,7 +376,8 @@ public class DefaultNotifications { .name("Queue type deprecation") .type(NotificationType.GENERAL) .subject("WARNING: ${queueType} deprecation") - .text("${queueType} queue type is deprecated and will be removed in ThingsBoard 4.0. Please migrate to Apache Kafka") + .text("Starting with ThingsBoard 4.0, ${queueType} will no longer be supported as a message queue for microservices. " + + "Please migrate to Apache Kafka. This change will not impact any rule nodes.") .icon("warning").color(RED_COLOR) .build(); diff --git a/msa/vc-executor/src/main/resources/tb-vc-executor.yml b/msa/vc-executor/src/main/resources/tb-vc-executor.yml index a55a0e73dc..6b79f2d101 100644 --- a/msa/vc-executor/src/main/resources/tb-vc-executor.yml +++ b/msa/vc-executor/src/main/resources/tb-vc-executor.yml @@ -47,7 +47,9 @@ zk: # Queue configuration parameters queue: - type: "${TB_QUEUE_TYPE:kafka}" # in-memory or kafka (Apache Kafka) or aws-sqs (AWS SQS) or pubsub (PubSub) or service-bus (Azure Service Bus) or rabbitmq (RabbitMQ) + # kafka (Apache Kafka). The following queue types are deprecated and will no longer be supported in ThingsBoard 4.0: + # aws-sqs (AWS SQS), pubsub (PubSub), service-bus (Azure Service Bus), rabbitmq (RabbitMQ) + type: "${TB_QUEUE_TYPE:kafka}" prefix: "${TB_QUEUE_PREFIX:}" # Global queue prefix. If specified, prefix is added before default topic name: 'prefix.default_topic_name'. Prefix is applied to all topics (and consumer groups for kafka). in_memory: stats: diff --git a/transport/coap/src/main/resources/tb-coap-transport.yml b/transport/coap/src/main/resources/tb-coap-transport.yml index f2ea0c1685..2c1c0550e1 100644 --- a/transport/coap/src/main/resources/tb-coap-transport.yml +++ b/transport/coap/src/main/resources/tb-coap-transport.yml @@ -232,7 +232,9 @@ coap: # Queue configuration parameters queue: - type: "${TB_QUEUE_TYPE:kafka}" # kafka (Apache Kafka) or aws-sqs (AWS SQS) or pubsub (PubSub) or service-bus (Azure Service Bus) or rabbitmq (RabbitMQ) + # kafka (Apache Kafka). The following queue types are deprecated and will no longer be supported in ThingsBoard 4.0: + # aws-sqs (AWS SQS), pubsub (PubSub), service-bus (Azure Service Bus), rabbitmq (RabbitMQ) + type: "${TB_QUEUE_TYPE:kafka}" prefix: "${TB_QUEUE_PREFIX:}" # Global queue prefix. If specified, prefix is added before default topic name: 'prefix.default_topic_name'. Prefix is applied to all topics (and consumer groups for kafka). kafka: # Kafka Bootstrap Servers diff --git a/transport/http/src/main/resources/tb-http-transport.yml b/transport/http/src/main/resources/tb-http-transport.yml index 527715b8ca..3c28c6ddf6 100644 --- a/transport/http/src/main/resources/tb-http-transport.yml +++ b/transport/http/src/main/resources/tb-http-transport.yml @@ -202,7 +202,9 @@ transport: # Queue configuration parameters queue: - type: "${TB_QUEUE_TYPE:kafka}" # kafka (Apache Kafka) or aws-sqs (AWS SQS) or pubsub (PubSub) or service-bus (Azure Service Bus) or rabbitmq (RabbitMQ) + # kafka (Apache Kafka). The following queue types are deprecated and will no longer be supported in ThingsBoard 4.0: + # aws-sqs (AWS SQS), pubsub (PubSub), service-bus (Azure Service Bus), rabbitmq (RabbitMQ) + type: "${TB_QUEUE_TYPE:kafka}" prefix: "${TB_QUEUE_PREFIX:}" # Global queue prefix. If specified, prefix is added before default topic name: 'prefix.default_topic_name'. Prefix is applied to all topics (and consumer groups for kafka) . kafka: # Kafka Bootstrap Servers diff --git a/transport/lwm2m/src/main/resources/tb-lwm2m-transport.yml b/transport/lwm2m/src/main/resources/tb-lwm2m-transport.yml index bf6a159106..bafe77ee92 100644 --- a/transport/lwm2m/src/main/resources/tb-lwm2m-transport.yml +++ b/transport/lwm2m/src/main/resources/tb-lwm2m-transport.yml @@ -302,7 +302,9 @@ transport: # Queue configuration properties queue: - type: "${TB_QUEUE_TYPE:kafka}" # kafka (Apache Kafka) or aws-sqs (AWS SQS) or pubsub (PubSub) or service-bus (Azure Service Bus) or rabbitmq (RabbitMQ) + # kafka (Apache Kafka). The following queue types are deprecated and will no longer be supported in ThingsBoard 4.0: + # aws-sqs (AWS SQS), pubsub (PubSub), service-bus (Azure Service Bus), rabbitmq (RabbitMQ) + type: "${TB_QUEUE_TYPE:kafka}" prefix: "${TB_QUEUE_PREFIX:}" # Global queue prefix. If specified, prefix is added before default topic name: 'prefix.default_topic_name'. Prefix is applied to all topics (and consumer groups for kafka). kafka: # Kafka Bootstrap Servers diff --git a/transport/mqtt/src/main/resources/tb-mqtt-transport.yml b/transport/mqtt/src/main/resources/tb-mqtt-transport.yml index c9fd10a99d..51a2c173a7 100644 --- a/transport/mqtt/src/main/resources/tb-mqtt-transport.yml +++ b/transport/mqtt/src/main/resources/tb-mqtt-transport.yml @@ -235,7 +235,9 @@ transport: # Queue configuration parameters queue: - type: "${TB_QUEUE_TYPE:kafka}" # kafka (Apache Kafka) or aws-sqs (AWS SQS) or pubsub (PubSub) or service-bus (Azure Service Bus) or rabbitmq (RabbitMQ) + # kafka (Apache Kafka). The following queue types are deprecated and will no longer be supported in ThingsBoard 4.0: + # aws-sqs (AWS SQS), pubsub (PubSub), service-bus (Azure Service Bus), rabbitmq (RabbitMQ) + type: "${TB_QUEUE_TYPE:kafka}" prefix: "${TB_QUEUE_PREFIX:}" # Global queue prefix. If specified, prefix is added before default topic name: 'prefix.default_topic_name'. Prefix is applied to all topics (and consumer groups for kafka). kafka: # Kafka Bootstrap Servers diff --git a/transport/snmp/src/main/resources/tb-snmp-transport.yml b/transport/snmp/src/main/resources/tb-snmp-transport.yml index 85a125b351..df222fe09f 100644 --- a/transport/snmp/src/main/resources/tb-snmp-transport.yml +++ b/transport/snmp/src/main/resources/tb-snmp-transport.yml @@ -181,7 +181,9 @@ transport: # Queue configuration parameters queue: - type: "${TB_QUEUE_TYPE:kafka}" # kafka (Apache Kafka) or aws-sqs (AWS SQS) or pubsub (PubSub) or service-bus (Azure Service Bus) or rabbitmq (RabbitMQ) + # kafka (Apache Kafka). The following queue types are deprecated and will no longer be supported in ThingsBoard 4.0: + # aws-sqs (AWS SQS), pubsub (PubSub), service-bus (Azure Service Bus), rabbitmq (RabbitMQ) + type: "${TB_QUEUE_TYPE:kafka}" prefix: "${TB_QUEUE_PREFIX:}" # Global queue prefix. If specified, prefix is added before default topic name: 'prefix.default_topic_name'. Prefix is applied to all topics (and consumer groups for kafka). kafka: # Kafka Bootstrap Servers From ba171900a9db305a801907f20f5192af7b5d79cc Mon Sep 17 00:00:00 2001 From: mpetrov Date: Fri, 1 Nov 2024 12:32:43 +0200 Subject: [PATCH 09/34] Revert "Updated autocomplete for AssetService" This reverts commit 9a1c03ac5df3902796a7257fcf68524fae320ee6. --- .../models/ace/service-completion.models.ts | 102 ++++++++---------- 1 file changed, 42 insertions(+), 60 deletions(-) diff --git a/ui-ngx/src/app/shared/models/ace/service-completion.models.ts b/ui-ngx/src/app/shared/models/ace/service-completion.models.ts index 709d670e6b..5efc428194 100644 --- a/ui-ngx/src/app/shared/models/ace/service-completion.models.ts +++ b/ui-ngx/src/app/shared/models/ace/service-completion.models.ts @@ -102,10 +102,6 @@ export const customDialogComponentHref = 'Resource info'; -export const bulkImportResultHref = 'Bulk import result'; - -export const bulkImportRequestHref = 'Bulk import request'; - export const pageLinkArg: FunctionArg = { name: 'pageLink', type: 'PageLink', @@ -370,6 +366,27 @@ export const serviceCompletions: TbEditorCompletions = { meta: 'service', type: 'AssetService', children: { + getTenantAssetInfos: { + description: 'Get tenant assets', + meta: 'function', + args: [ + pageLinkArg, + {name: 'type', type: 'string', optional: true, description: 'Asset type'}, + requestConfigArg + ], + return: observablePageDataReturnType(assetInfoHref) + }, + getCustomerAssetInfos: { + description: 'Get customer assets', + meta: 'function', + args: [ + {name: 'customerId', type: 'string', description: 'Id of the customer'}, + pageLinkArg, + {name: 'type', type: 'string', optional: true, description: 'Asset type'}, + requestConfigArg + ], + return: observablePageDataReturnType(assetInfoHref) + }, getAsset: { description: 'Get asset by id', meta: 'function', @@ -397,80 +414,53 @@ export const serviceCompletions: TbEditorCompletions = { ], return: observableReturnType(assetInfoHref) }, - getTenantAssets: { - description: 'Get assets for the tenant, filtered by type if provided', - meta: 'function', - args: [ - pageLinkArg, - { name: 'type', type: 'string', description: 'Optional asset type filter' }, - requestConfigArg - ], - return: observablePageDataReturnType(assetHref) - }, - getCustomerAssets: { - description: 'Get assets for a specific customer, filtered by type if provided', - meta: 'function', - args: [ - { name: 'customerId', type: 'string', description: 'Customer ID' }, - pageLinkArg, - { name: 'type', type: 'string', description: 'Optional asset type filter' }, - requestConfigArg - ], - return: observablePageDataReturnType(assetHref) - }, - getUserAssets: { - description: 'Get assets associated with the user, filtered by type if provided', + saveAsset: { + description: 'Save asset', meta: 'function', args: [ - pageLinkArg, - { name: 'type', type: 'string', description: 'Optional asset type filter' }, + {name: 'asset', type: assetHref, description: 'Asset object to save'}, requestConfigArg ], - return: observablePageDataReturnType(assetHref) + return: observableReturnType(assetHref) }, - getAllAssetInfos: { - description: 'Get all asset information with optional customer inclusion', + deleteAsset: { + description: 'Delete asset by id', meta: 'function', args: [ - { name: 'includeCustomers', type: 'boolean', description: 'Whether to include customers in the result' }, - pageLinkArg, - { name: 'assetProfileId', type: 'string', description: 'Optional asset profile ID' }, + {name: 'assetId', type: 'string', description: 'Id of the asset'}, requestConfigArg ], - return: observablePageDataReturnType(assetInfoHref) + return: observableVoid() }, - getCustomerAssetInfos: { - description: 'Get customer asset information with optional customer inclusion', + getAssetTypes: { + description: 'Get all available assets types', meta: 'function', args: [ - { name: 'includeCustomers', type: 'boolean', description: 'Whether to include customers in the result' }, - { name: 'customerId', type: 'string', description: 'Customer ID' }, - pageLinkArg, - { name: 'assetProfileId', type: 'string', description: 'Optional asset profile ID' }, requestConfigArg ], - return: observablePageDataReturnType(assetInfoHref) + return: observableArrayReturnType('EntitySubtype') }, - bulkImportAssets: { - description: 'Bulk import assets with provided entities data', + makeAssetPublic: { + description: 'Make asset public (available from public dashboard)', meta: 'function', args: [ - { name: 'entitiesData', type: bulkImportRequestHref, description: 'Data for bulk importing assets' }, + {name: 'assetId', type: 'string', description: 'Id of the asset'}, requestConfigArg ], - return: observableReturnType(bulkImportResultHref) + return: observableReturnType(assetHref) }, - saveAsset: { - description: 'Save asset', + assignAssetToCustomer: { + description: 'Assign asset to specific customer', meta: 'function', args: [ - {name: 'asset', type: assetHref, description: 'Asset object to save'}, + {name: 'customerId', type: 'string', description: 'Id of the customer'}, + {name: 'assetId', type: 'string', description: 'Id of the asset'}, requestConfigArg ], return: observableReturnType(assetHref) }, - deleteAsset: { - description: 'Delete asset by id', + unassignAssetFromCustomer: { + description: 'Unassign asset from any customer', meta: 'function', args: [ {name: 'assetId', type: 'string', description: 'Id of the asset'}, @@ -478,14 +468,6 @@ export const serviceCompletions: TbEditorCompletions = { ], return: observableVoid() }, - getAssetTypes: { - description: 'Get all available assets types', - meta: 'function', - args: [ - requestConfigArg - ], - return: observableArrayReturnType('EntitySubtype') - }, findByQuery: { description: 'Find assets by search query', meta: 'function', From fa110b4c613710a40eb6d0370de0193f2d6980bd Mon Sep 17 00:00:00 2001 From: mpetrov Date: Fri, 1 Nov 2024 12:33:15 +0200 Subject: [PATCH 10/34] Updated autocomplete for AssetService refactoring --- .../models/ace/service-completion.models.ts | 65 +++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/ui-ngx/src/app/shared/models/ace/service-completion.models.ts b/ui-ngx/src/app/shared/models/ace/service-completion.models.ts index 5efc428194..17e05427a1 100644 --- a/ui-ngx/src/app/shared/models/ace/service-completion.models.ts +++ b/ui-ngx/src/app/shared/models/ace/service-completion.models.ts @@ -102,6 +102,10 @@ export const customDialogComponentHref = 'Resource info'; +export const bulkImportResultHref = 'Bulk import result'; + +export const bulkImportRequestHref = 'Bulk import request'; + export const pageLinkArg: FunctionArg = { name: 'pageLink', type: 'PageLink', @@ -387,6 +391,67 @@ export const serviceCompletions: TbEditorCompletions = { ], return: observablePageDataReturnType(assetInfoHref) }, + getTenantAssetInfosByAssetProfileId: { + description: 'Get tenant asset infos by asset profile ID', + meta: 'function', + args: [ + pageLinkArg, + { name: 'assetProfileId', type: 'string', optional: true, description: 'ID of the asset profile' }, + requestConfigArg + ], + return: observablePageDataReturnType(assetInfoHref) + }, + getCustomerAssetInfosByAssetProfileId: { + description: 'Get customer asset infos by asset profile ID', + meta: 'function', + args: [ + { name: 'customerId', type: 'string', description: 'ID of the customer' }, + pageLinkArg, + { name: 'assetProfileId', type: 'string', optional: true, description: 'ID of the asset profile' }, + requestConfigArg + ], + return: observablePageDataReturnType(assetInfoHref) + }, + assignAssetToEdge: { + description: 'Assign an asset to an edge', + meta: 'function', + args: [ + { name: 'edgeId', type: 'string', description: 'ID of the edge' }, + { name: 'assetId', type: 'string', description: 'ID of the asset' }, + requestConfigArg + ], + return: observableReturnType(assetHref) + }, + unassignAssetFromEdge: { + description: 'Unassign an asset from an edge', + meta: 'function', + args: [ + { name: 'edgeId', type: 'string', description: 'ID of the edge' }, + { name: 'assetId', type: 'string', description: 'ID of the asset' }, + requestConfigArg + ], + return: observableVoid() + }, + getEdgeAssets: { + description: 'Get assets assigned to an edge', + meta: 'function', + args: [ + { name: 'edgeId', type: 'string', description: 'ID of the edge' }, + pageLinkArg, + { name: 'type', type: 'string', optional: true, description: 'Asset type' }, + requestConfigArg + ], + return: observablePageDataReturnType(assetInfoHref) + }, + bulkImportAssets: { + description: 'Bulk import assets with provided entities data', + meta: 'function', + args: [ + { name: 'entitiesData', type: bulkImportRequestHref, description: 'Data for bulk importing assets' }, + requestConfigArg + ], + return: observableReturnType(bulkImportResultHref) + }, getAsset: { description: 'Get asset by id', meta: 'function', From 37f4dc7cb24e52da0d06209e6ca21a6f7aa99eae Mon Sep 17 00:00:00 2001 From: d2eight Date: Fri, 1 Nov 2024 19:43:31 +0200 Subject: [PATCH 11/34] Fix of the action bug --- .../home/components/widget/widget-container.component.html | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ui-ngx/src/app/modules/home/components/widget/widget-container.component.html b/ui-ngx/src/app/modules/home/components/widget/widget-container.component.html index ed1f089454..f6679d0c94 100644 --- a/ui-ngx/src/app/modules/home/components/widget/widget-container.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/widget-container.component.html @@ -38,6 +38,7 @@ [class]="{'tb-widget-actions-absolute': !(widget.showWidgetTitlePanel && !widgetComponent.widgetContext?.embedTitlePanel && (widget.showTitle||widget.hasAggregation))}" (mousedown)="$event.stopPropagation()">