Browse Source

feat(iot-hub): replace gateway download bar with inline markdown button

Instead of a fixed download bar above markdown, the creator writes
${gateway.downloadButton} anywhere in their markdown. It resolves to
an HTML button with data-action attribute. After markdown renders,
onMarkdownReady() attaches a click handler that calls the authenticated
DeviceService.downloadGatewayDockerComposeFile().

Usage in post-install.md:
  ${gateway.downloadButton}
pull/15508/head
Andrii Shvaika 6 months ago
parent
commit
f347c88eab
  1. 14
      ui-ngx/src/app/modules/home/components/iot-hub/device-install-dialog/device-install-dialog.component.html
  2. 34
      ui-ngx/src/app/modules/home/components/iot-hub/device-install-dialog/device-install-dialog.component.scss
  3. 25
      ui-ngx/src/app/modules/home/components/iot-hub/device-install-dialog/device-install-dialog.component.ts

14
ui-ngx/src/app/modules/home/components/iot-hub/device-install-dialog/device-install-dialog.component.html

@ -76,18 +76,10 @@
@switch (ws.type) { @switch (ws.type) {
@case ('instruction') { @case ('instruction') {
<div class="tb-device-install-instruction"> <div class="tb-device-install-instruction" #instructionContainer>
@if (gatewayDockerComposeAvailable) {
<div class="tb-gateway-download-bar">
<span>{{ 'iot-hub.device-install-gateway-docker-compose' | translate }}</span>
<button mat-stroked-button color="primary" (click)="downloadGatewayDockerCompose()">
<mat-icon>download</mat-icon>
{{ 'action.download' | translate }}
</button>
</div>
}
<tb-markdown [data]="ws.markdown" <tb-markdown [data]="ws.markdown"
[usePlainMarkdown]="true"> [usePlainMarkdown]="true"
(ready)="onMarkdownReady(instructionContainer)">
</tb-markdown> </tb-markdown>
</div> </div>
} }

34
ui-ngx/src/app/modules/home/components/iot-hub/device-install-dialog/device-install-dialog.component.scss

@ -123,22 +123,6 @@
min-height: 120px; min-height: 120px;
} }
// Gateway download bar
.tb-gateway-download-bar {
display: flex;
align-items: center;
justify-content: space-between;
padding: 12px 16px;
margin-bottom: 16px;
background: #e3f2fd;
border-radius: 8px;
span {
font-size: 14px;
color: rgba(0, 0, 0, 0.87);
}
}
// Instruction view // Instruction view
.tb-device-install-instruction { .tb-device-install-instruction {
::ng-deep tb-markdown { ::ng-deep tb-markdown {
@ -151,6 +135,24 @@
margin-top: 0; margin-top: 0;
} }
} }
.tb-download-btn {
display: inline-flex;
align-items: center;
gap: 4px;
padding: 6px 16px;
border: 1px solid #305680;
border-radius: 4px;
color: #305680;
font-size: 14px;
font-weight: 500;
text-decoration: none;
cursor: pointer;
&:hover {
background: rgba(48, 86, 128, 0.08);
}
}
} }
} }

25
ui-ngx/src/app/modules/home/components/iot-hub/device-install-dialog/device-install-dialog.component.ts

@ -240,16 +240,17 @@ export class TbDeviceInstallDialogComponent extends DialogComponent<TbDeviceInst
} }
} }
get gatewayDockerComposeAvailable(): boolean { onMarkdownReady(container: HTMLElement): void {
const gateway = this.entityOutputs.get('gateway'); const buttons = container.querySelectorAll('[data-action="download-gateway-docker-compose"]');
return !!gateway?.dockerComposeUrl; buttons.forEach(btn => {
} btn.addEventListener('click', (e) => {
e.preventDefault();
downloadGatewayDockerCompose(): void { const gateway = this.entityOutputs.get('gateway');
const gateway = this.entityOutputs.get('gateway'); if (gateway?.id) {
if (gateway?.id) { this.deviceService.downloadGatewayDockerComposeFile(gateway.id).subscribe();
this.deviceService.downloadGatewayDockerComposeFile(gateway.id).subscribe(); }
} });
});
} }
getPatternErrorMessage(field: FormFieldDefinition): string { getPatternErrorMessage(field: FormFieldDefinition): string {
@ -266,6 +267,10 @@ export class TbDeviceInstallDialogComponent extends DialogComponent<TbDeviceInst
if (key in this.transportVars) { if (key in this.transportVars) {
return this.transportVars[key]; return this.transportVars[key];
} }
// Special action placeholders
if (key === 'gateway.downloadButton') {
return '<a href="#" data-action="download-gateway-docker-compose" class="tb-download-btn">⬇ Download docker-compose.yml</a>';
}
const dotIdx = key.indexOf('.'); const dotIdx = key.indexOf('.');
if (dotIdx > 0) { if (dotIdx > 0) {
const alias = key.substring(0, dotIdx); const alias = key.substring(0, dotIdx);

Loading…
Cancel
Save