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