From 43624ba380f4a33b1e5abd9a61ef581fa5cb8904 Mon Sep 17 00:00:00 2001 From: Andrii Shvaika Date: Mon, 6 Apr 2026 17:33:11 +0300 Subject: [PATCH] feat(iot-hub): support custom docker-compose template for gateway install Add optional 'dockerCompose' field to GATEWAY step definition pointing to a YAML template in the ZIP. Variables (${mqtt.host}, ${gateway.token}, form values) are resolved after gateway creation. The download button serves the custom template as a Blob download instead of calling the standard backend endpoint. Falls back to the standard API-generated docker-compose.yml when no custom template is provided. --- .../device-install-dialog.component.ts | 31 ++++++++++++++++--- .../models/iot-hub/device-package.models.ts | 1 + 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/iot-hub/device-install-dialog/device-install-dialog.component.ts b/ui-ngx/src/app/modules/home/components/iot-hub/device-install-dialog/device-install-dialog.component.ts index 5ec520d98b..21c8254593 100644 --- a/ui-ngx/src/app/modules/home/components/iot-hub/device-install-dialog/device-install-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/iot-hub/device-install-dialog/device-install-dialog.component.ts @@ -101,6 +101,7 @@ export class TbDeviceInstallDialogComponent extends DialogComponent = {}; entityOutputs = new Map(); transportVars: Record = {}; + gatewayDockerComposeContent: string | null = null; constructor( protected store: Store, @@ -254,9 +255,21 @@ export class TbDeviceInstallDialogComponent extends DialogComponent { btn.addEventListener('click', (e) => { e.preventDefault(); - const gateway = this.entityOutputs.get('gateway'); - if (gateway?.id) { - this.deviceService.downloadGatewayDockerComposeFile(gateway.id).subscribe(); + if (this.gatewayDockerComposeContent) { + // Custom template from ZIP — download as Blob + const blob = new Blob([this.gatewayDockerComposeContent], { type: 'application/x-yaml' }); + const url = URL.createObjectURL(blob); + const link = document.createElement('a'); + link.href = url; + link.download = 'docker-compose.yml'; + link.click(); + URL.revokeObjectURL(url); + } else { + // Standard template — authenticated API call + const gateway = this.entityOutputs.get('gateway'); + if (gateway?.id) { + this.deviceService.downloadGatewayDockerComposeFile(gateway.id).subscribe(); + } } }); }); @@ -502,13 +515,23 @@ export class TbDeviceInstallDialogComponent extends DialogComponent