Browse Source
- Create TbIotHubDeleteDialogComponent with warn-colored "Delete anyway" button - Extract install dialog template and styles to separate HTML/SCSS files - Install dialog: simplified confirm/success layout matching design, "Close" label when only button shown on success - Item card: installed label is now a clickable button emitting deleteClick - Detail dialog: 64px colored icon header for CF/RC types, description-only layout (no image) for CF/RC, delete button (stroked warn) in footer when installed, closes with 'deleted' result after confirmed deletion - Home component: handle install/delete dialog results by reloading installed items, pass installedItem to detail dialogpull/15347/head
14 changed files with 423 additions and 173 deletions
@ -0,0 +1,83 @@ |
|||||
|
///
|
||||
|
/// Copyright © 2016-2026 The Thingsboard Authors
|
||||
|
///
|
||||
|
/// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
/// you may not use this file except in compliance with the License.
|
||||
|
/// You may obtain a copy of the License at
|
||||
|
///
|
||||
|
/// http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
///
|
||||
|
/// Unless required by applicable law or agreed to in writing, software
|
||||
|
/// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
/// See the License for the specific language governing permissions and
|
||||
|
/// limitations under the License.
|
||||
|
///
|
||||
|
|
||||
|
import { Component, Inject } from '@angular/core'; |
||||
|
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; |
||||
|
|
||||
|
export interface IotHubDeleteDialogData { |
||||
|
itemName: string; |
||||
|
} |
||||
|
|
||||
|
@Component({ |
||||
|
selector: 'tb-iot-hub-delete-dialog', |
||||
|
standalone: false, |
||||
|
template: ` |
||||
|
<div class="tb-iot-hub-delete-content"> |
||||
|
<h2 class="tb-iot-hub-delete-title">{{ 'iot-hub.delete-confirm-title' | translate:{ name: data.itemName } }}</h2> |
||||
|
<p class="tb-iot-hub-delete-desc">{{ 'iot-hub.delete-desc' | translate }}</p> |
||||
|
</div> |
||||
|
<div class="tb-iot-hub-delete-actions"> |
||||
|
<button mat-button (click)="cancel()">{{ 'action.cancel' | translate }}</button> |
||||
|
<button mat-flat-button color="warn" (click)="confirm()">{{ 'iot-hub.delete-anyway' | translate }}</button> |
||||
|
</div> |
||||
|
`,
|
||||
|
styles: [` |
||||
|
.tb-iot-hub-delete-content { |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
gap: 20px; |
||||
|
padding: 24px; |
||||
|
} |
||||
|
.tb-iot-hub-delete-title { |
||||
|
font-size: 20px; |
||||
|
font-weight: 600; |
||||
|
line-height: 24px; |
||||
|
letter-spacing: 0.1px; |
||||
|
color: rgba(0, 0, 0, 0.87); |
||||
|
margin: 0; |
||||
|
} |
||||
|
.tb-iot-hub-delete-desc { |
||||
|
font-size: 14px; |
||||
|
font-weight: 400; |
||||
|
line-height: 20px; |
||||
|
letter-spacing: 0.2px; |
||||
|
color: rgba(0, 0, 0, 0.54); |
||||
|
margin: 0; |
||||
|
} |
||||
|
.tb-iot-hub-delete-actions { |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: flex-end; |
||||
|
gap: 8px; |
||||
|
padding: 8px; |
||||
|
} |
||||
|
`]
|
||||
|
}) |
||||
|
export class TbIotHubDeleteDialogComponent { |
||||
|
|
||||
|
constructor( |
||||
|
@Inject(MAT_DIALOG_DATA) public data: IotHubDeleteDialogData, |
||||
|
private dialogRef: MatDialogRef<TbIotHubDeleteDialogComponent> |
||||
|
) {} |
||||
|
|
||||
|
confirm(): void { |
||||
|
this.dialogRef.close(true); |
||||
|
} |
||||
|
|
||||
|
cancel(): void { |
||||
|
this.dialogRef.close(false); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,80 @@ |
|||||
|
<!-- |
||||
|
|
||||
|
Copyright © 2016-2026 The Thingsboard Authors |
||||
|
|
||||
|
Licensed under the Apache License, Version 2.0 (the "License"); |
||||
|
you may not use this file except in compliance with the License. |
||||
|
You may obtain a copy of the License at |
||||
|
|
||||
|
http://www.apache.org/licenses/LICENSE-2.0 |
||||
|
|
||||
|
Unless required by applicable law or agreed to in writing, software |
||||
|
distributed under the License is distributed on an "AS IS" BASIS, |
||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
|
See the License for the specific language governing permissions and |
||||
|
limitations under the License. |
||||
|
|
||||
|
--> |
||||
|
<div class="tb-iot-hub-install-content"> |
||||
|
@switch (state) { |
||||
|
@case ('confirm') { |
||||
|
<h2 class="tb-iot-hub-install-title">{{ 'iot-hub.install-confirm-title' | translate:{ name: item.name } }}</h2> |
||||
|
<p class="tb-iot-hub-install-desc">{{ 'iot-hub.install-desc' | translate }}</p> |
||||
|
} |
||||
|
@case ('select-entity') { |
||||
|
<h2 class="tb-iot-hub-install-title">{{ 'iot-hub.install-confirm-title' | translate:{ name: item.name } }}</h2> |
||||
|
<p class="tb-iot-hub-install-desc">{{ 'iot-hub.select-entity-for-cf' | translate:{ name: item.name } }}</p> |
||||
|
<tb-entity-select |
||||
|
[(ngModel)]="selectedEntityId" |
||||
|
[allowedEntityTypes]="cfEntityTypes" |
||||
|
[defaultEntityType]="defaultCfEntityType" |
||||
|
[filterAllowedEntityTypes]="false" |
||||
|
appearance="outline" |
||||
|
required> |
||||
|
</tb-entity-select> |
||||
|
} |
||||
|
@case ('installing') { |
||||
|
<h2 class="tb-iot-hub-install-title">{{ 'iot-hub.install-confirm-title' | translate:{ name: item.name } }}</h2> |
||||
|
<p class="tb-iot-hub-install-desc">{{ 'iot-hub.install-desc' | translate }}</p> |
||||
|
} |
||||
|
@case ('success') { |
||||
|
<h2 class="tb-iot-hub-install-title">{{ 'iot-hub.install-success-title' | translate }}</h2> |
||||
|
<p class="tb-iot-hub-install-desc">{{ 'iot-hub.install-success-desc' | translate:{ name: item.name } }}</p> |
||||
|
} |
||||
|
@case ('error') { |
||||
|
<h2 class="tb-iot-hub-install-title">{{ 'iot-hub.install-error-title' | translate }}</h2> |
||||
|
<p class="tb-iot-hub-install-desc">{{ 'iot-hub.install-error-message' | translate:{ name: item.name } }}</p> |
||||
|
<div class="tb-iot-hub-error-details">{{ errorMessage }}</div> |
||||
|
} |
||||
|
} |
||||
|
</div> |
||||
|
<mat-dialog-actions align="end"> |
||||
|
@switch (state) { |
||||
|
@case ('confirm') { |
||||
|
<button mat-button (click)="cancel()">{{ 'action.cancel' | translate }}</button> |
||||
|
<button mat-flat-button color="primary" (click)="install()">{{ 'iot-hub.install' | translate }}</button> |
||||
|
} |
||||
|
@case ('select-entity') { |
||||
|
<button mat-button (click)="cancel()">{{ 'action.cancel' | translate }}</button> |
||||
|
<button mat-flat-button color="primary" [disabled]="!selectedEntityId" (click)="doInstall()">{{ 'iot-hub.install' | translate }}</button> |
||||
|
} |
||||
|
@case ('installing') { |
||||
|
<button mat-button disabled>{{ 'action.cancel' | translate }}</button> |
||||
|
<button mat-flat-button color="primary" disabled> |
||||
|
<mat-spinner diameter="18" class="tb-iot-hub-inline-spinner"></mat-spinner> |
||||
|
{{ 'iot-hub.installing' | translate }} |
||||
|
</button> |
||||
|
} |
||||
|
@case ('success') { |
||||
|
<button mat-button (click)="close()">{{ (entityDetailsUrl ? 'action.cancel' : 'action.close') | translate }}</button> |
||||
|
@if (entityDetailsUrl) { |
||||
|
<button mat-flat-button color="primary" (click)="openEntityDetails()"> |
||||
|
{{ 'iot-hub.open-details' | translate }} |
||||
|
</button> |
||||
|
} |
||||
|
} |
||||
|
@case ('error') { |
||||
|
<button mat-button (click)="close()">{{ 'action.close' | translate }}</button> |
||||
|
} |
||||
|
} |
||||
|
</mat-dialog-actions> |
||||
@ -0,0 +1,57 @@ |
|||||
|
/** |
||||
|
* Copyright © 2016-2026 The Thingsboard Authors |
||||
|
* |
||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
|
* you may not use this file except in compliance with the License. |
||||
|
* You may obtain a copy of the License at |
||||
|
* |
||||
|
* http://www.apache.org/licenses/LICENSE-2.0 |
||||
|
* |
||||
|
* Unless required by applicable law or agreed to in writing, software |
||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
|
* See the License for the specific language governing permissions and |
||||
|
* limitations under the License. |
||||
|
*/ |
||||
|
|
||||
|
.tb-iot-hub-install-content { |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
gap: 20px; |
||||
|
padding: 24px; |
||||
|
} |
||||
|
|
||||
|
.tb-iot-hub-install-title { |
||||
|
font-size: 20px; |
||||
|
font-weight: 600; |
||||
|
line-height: 24px; |
||||
|
letter-spacing: 0.1px; |
||||
|
color: rgba(0, 0, 0, 0.87); |
||||
|
margin: 0; |
||||
|
} |
||||
|
|
||||
|
.tb-iot-hub-install-desc { |
||||
|
color: rgba(0, 0, 0, 0.54); |
||||
|
font-size: 14px; |
||||
|
line-height: 20px; |
||||
|
letter-spacing: 0.2px; |
||||
|
margin: 0; |
||||
|
} |
||||
|
|
||||
|
.tb-iot-hub-inline-spinner { |
||||
|
display: inline-block; |
||||
|
margin-right: 8px; |
||||
|
} |
||||
|
|
||||
|
.tb-iot-hub-error-details { |
||||
|
max-height: 200px; |
||||
|
overflow-y: auto; |
||||
|
padding: 12px; |
||||
|
background: #f5f5f5; |
||||
|
border-radius: 4px; |
||||
|
font-family: monospace; |
||||
|
font-size: 12px; |
||||
|
color: rgba(0, 0, 0, 0.7); |
||||
|
white-space: pre-wrap; |
||||
|
word-break: break-word; |
||||
|
} |
||||
Loading…
Reference in new issue