Browse Source

Move action buttons from footer to info section in item detail dialog

- Footer now only has Close button
- Info section shows state-based actions matching design:
  - Not installed: Install button (filled primary)
  - Installed (same version): "Installed v1.0.0" badge + "Open details" link
    + Remove button (stroked warn)
  - Update available: Installed badge + Open details link + Update button
    (filled primary) + Remove button (stroked warn)
- Solution templates: Solution instructions + Go to main dashboard links
- CF/RC/Devices: same pattern without image preview
- Green installed badge with check icon, links with open_in_new icon
pull/15508/head
Igor Kulikov 6 months ago
parent
commit
3dbd99fd9e
  1. 106
      ui-ngx/src/app/modules/home/pages/iot-hub/iot-hub-item-detail-dialog.component.html
  2. 58
      ui-ngx/src/app/modules/home/pages/iot-hub/iot-hub-item-detail-dialog.component.scss
  3. 1
      ui-ngx/src/assets/locale/locale.constant-en_US.json

106
ui-ngx/src/app/modules/home/pages/iot-hub/iot-hub-item-detail-dialog.component.html

@ -52,9 +52,21 @@
<div class="dlg-body">
<!-- Main content -->
<div class="dlg-main">
@if (item.type === ItemType.CALCULATED_FIELD || item.type === ItemType.RULE_CHAIN) {
<!-- CF/RC: description + author only (no image) -->
@if (item.type === ItemType.CALCULATED_FIELD || item.type === ItemType.RULE_CHAIN || item.type === ItemType.DEVICE) {
<!-- CF/RC/Device: description + author (no image) -->
<div class="dlg-info">
@if (isInstalled()) {
<div class="dlg-info-status-row">
<span class="dlg-installed-badge">
<mat-icon>check</mat-icon>
{{ 'iot-hub.installed' | translate }} v{{ installedItem.version }}
</span>
<a class="dlg-info-link" (click)="openEntityDetails()">
<mat-icon>open_in_new</mat-icon>
{{ 'iot-hub.open-item-type-details' | translate:{ type: getTypeLabel() } }}
</a>
</div>
}
@if (item.description) {
<div class="dlg-description">
<tb-markdown [data]="item.description"></tb-markdown>
@ -64,6 +76,24 @@
<tb-icon>person</tb-icon>
<span>{{ item.creatorDisplayName }}</span>
</div>
<div class="dlg-info-actions">
@if (!isInstalled()) {
<button mat-flat-button color="primary" (click)="install()">
{{ 'iot-hub.install' | translate }}
</button>
} @else if (hasUpdate()) {
<button mat-flat-button color="primary" (click)="updateItem()">
{{ 'iot-hub.update' | translate }}
</button>
}
@if (isInstalled()) {
<span class="dlg-info-actions-spacer"></span>
<button mat-stroked-button color="warn" (click)="deleteItem()">
<mat-icon>delete</mat-icon>
{{ 'iot-hub.remove' | translate }}
</button>
}
</div>
</div>
} @else {
<!-- Widget/Dashboard/Solution: image + description side by side -->
@ -114,6 +144,29 @@
}
</div>
<div class="dlg-info">
<!-- Installed status + links row -->
@if (isInstalled()) {
<div class="dlg-info-status-row">
<span class="dlg-installed-badge">
<mat-icon>check</mat-icon>
{{ 'iot-hub.installed' | translate }} v{{ installedItem.version }}
</span>
@if (isSameVersion() && item.type === ItemType.SOLUTION_TEMPLATE) {
<a class="dlg-info-link" (click)="openSolutionInstructions()">
<mat-icon>info_outline</mat-icon>
{{ 'iot-hub.solution-instructions' | translate }}
</a>
}
<a class="dlg-info-link" (click)="openEntityDetails()">
<mat-icon>open_in_new</mat-icon>
@if (item.type === ItemType.SOLUTION_TEMPLATE) {
{{ 'iot-hub.goto-main-dashboard' | translate }}
} @else {
{{ 'iot-hub.open-item-type-details' | translate:{ type: getTypeLabel() } }}
}
</a>
</div>
}
@if (item.description) {
<div class="dlg-description">
<tb-markdown [data]="item.description"></tb-markdown>
@ -123,6 +176,25 @@
<tb-icon>person</tb-icon>
<span>{{ item.creatorDisplayName }}</span>
</div>
<!-- Action buttons -->
<div class="dlg-info-actions">
@if (!isInstalled()) {
<button mat-flat-button color="primary" (click)="install()">
{{ 'iot-hub.install' | translate }}
</button>
} @else if (hasUpdate()) {
<button mat-flat-button color="primary" (click)="updateItem()">
{{ 'iot-hub.update' | translate }}
</button>
}
@if (isInstalled()) {
<span class="dlg-info-actions-spacer"></span>
<button mat-stroked-button color="warn" (click)="deleteItem()">
<mat-icon>delete</mat-icon>
{{ 'iot-hub.remove' | translate }}
</button>
}
</div>
</div>
</div>
}
@ -182,37 +254,7 @@
<!-- Footer -->
<div class="dlg-footer">
@if (isInstalled()) {
<button mat-stroked-button color="warn" (click)="deleteItem()">
<mat-icon>delete</mat-icon>
{{ 'action.delete' | translate }}
</button>
}
@if (isSameVersion() && item.type === ItemType.SOLUTION_TEMPLATE) {
<button mat-button (click)="openSolutionInstructions()">
{{ 'iot-hub.solution-instructions' | translate }}
</button>
}
<span class="dlg-footer-spacer"></span>
<button mat-button (click)="close()">{{ 'action.close' | translate }}</button>
@if (isSameVersion()) {
@if (item.type === ItemType.SOLUTION_TEMPLATE) {
<button mat-flat-button color="primary" (click)="openEntityDetails()">
{{ 'iot-hub.goto-main-dashboard' | translate }}
</button>
} @else {
<button mat-flat-button color="primary" (click)="openEntityDetails()">
{{ 'iot-hub.open-item-type-details' | translate:{ type: getTypeLabel() } }}
</button>
}
} @else if (hasUpdate()) {
<button mat-flat-button color="primary" (click)="updateItem()">
{{ 'iot-hub.update' | translate }}
</button>
} @else {
<button mat-flat-button color="primary" (click)="install()">
{{ 'iot-hub.install' | translate }}
</button>
}
</div>
</div>

58
ui-ngx/src/app/modules/home/pages/iot-hub/iot-hub-item-detail-dialog.component.scss

@ -471,11 +471,65 @@
&.active { background: rgba(0, 0, 0, 0.6); }
}
// Footer — Design: border-top rgba(0,0,0,0.12), p-8, flex row, justify-end, gap-8
.dlg-footer {
// Info status row — "Installed v1.0.0" badge + links
.dlg-info-status-row {
display: flex;
align-items: center;
gap: 16px;
flex-wrap: wrap;
}
.dlg-installed-badge {
display: inline-flex;
align-items: center;
gap: 4px;
font-size: 14px;
font-weight: 500;
color: #2e7d32;
mat-icon {
font-size: 18px;
width: 18px;
height: 18px;
}
}
.dlg-info-link {
display: inline-flex;
align-items: center;
gap: 4px;
font-size: 14px;
font-weight: 500;
color: $tb-primary-color;
cursor: pointer;
text-decoration: none;
mat-icon {
font-size: 18px;
width: 18px;
height: 18px;
}
&:hover {
text-decoration: underline;
}
}
// Action buttons row in info section
.dlg-info-actions {
display: flex;
align-items: center;
gap: 8px;
}
.dlg-info-actions-spacer {
flex: 1;
}
// Footer — only Close button
.dlg-footer {
display: flex;
align-items: center;
padding: 8px;
border-top: 1px solid rgba(0, 0, 0, 0.12);
flex-shrink: 0;

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

@ -3773,6 +3773,7 @@
"delete-confirm-title": "Delete '{{name}}'?",
"delete-desc": "Deleting this will also remove the installed entity and its associated resources within your tenant",
"delete-anyway": "Delete anyway",
"remove": "Remove",
"select-entity-for-cf": "Select entity for calculated field '{{name}}'",
"install-type": "Type: {{type}}",
"install-creator": "Creator: {{creator}}",

Loading…
Cancel
Save