Browse Source

Refine add item dialog, add rule chain IoT Hub integration, UI improvements

- Add item dialog: use mat-toolbar/mat-dialog-content/mat-dialog-actions pattern
- Dialog content width 1000px at gt-md, border-top on actions
- Browse add mode: hide top border, add padding-bottom to results,
  responsive 2-col regular / 1-col compact at gt-sm
- Item card add mode: disable creator navigation (label only, no hover)
- Item detail dialog add mode: creator as label (primary color, no click)
- Add "Add from IoT Hub" to rule chains page (tenant/edges scope)
- Remove unnecessary table updateData before navigation
- Browse filters: no padding-bottom/margin-bottom in add mode
pull/15508/head
Igor Kulikov 3 months ago
parent
commit
76577a0335
  1. 22
      ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-add-item-dialog.component.html
  2. 35
      ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-add-item-dialog.component.scss
  3. 2
      ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-browse.component.html
  4. 34
      ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-browse.component.scss
  5. 4
      ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-item-card.component.html
  6. 22
      ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-item-card.component.scss
  7. 4
      ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-item-detail-dialog.component.html
  8. 9
      ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-item-detail-dialog.component.scss
  9. 7
      ui-ngx/src/app/modules/home/pages/dashboard/dashboards-table-config.resolver.ts
  10. 31
      ui-ngx/src/app/modules/home/pages/rulechain/rulechains-table-config.resolver.ts

22
ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-add-item-dialog.component.html

@ -15,14 +15,17 @@
limitations under the License.
-->
<div class="tb-iot-hub-add-item-dialog">
<div class="tb-iot-hub-add-item-header">
<form>
<mat-toolbar color="primary">
<h2>{{ getTitle() }}</h2>
<button mat-icon-button (click)="close()">
<span class="flex-1"></span>
<button mat-icon-button
(click)="close()"
type="button">
<mat-icon>close</mat-icon>
</button>
</div>
<div class="tb-iot-hub-add-item-content">
</mat-toolbar>
<div mat-dialog-content>
@if (isInstalling) {
<div class="tb-iot-hub-add-item-loading">
<mat-spinner diameter="40"></mat-spinner>
@ -36,4 +39,11 @@
(addItem)="onAddItem($event)">
</tb-iot-hub-browse>
</div>
</div>
<div mat-dialog-actions class="flex items-center justify-end">
<button mat-button
type="button"
(click)="close()">
{{ 'action.close' | translate }}
</button>
</div>
</form>

35
ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-add-item-dialog.component.scss

@ -14,34 +14,21 @@
* limitations under the License.
*/
.tb-iot-hub-add-item-dialog {
display: flex;
flex-direction: column;
width: 100%;
height: 100%;
}
@import "../../../../../scss/constants";
.tb-iot-hub-add-item-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 16px 24px;
border-bottom: 1px solid rgba(0, 0, 0, 0.12);
flex-shrink: 0;
:host-context(.mat-mdc-dialog-container) {
.mat-mdc-dialog-content {
position: relative;
padding: 0;
h2 {
margin: 0;
font-size: 20px;
font-weight: 500;
line-height: 28px;
color: rgba(0, 0, 0, 0.87);
@media #{$mat-gt-md} {
width: 1000px;
}
}
}
.tb-iot-hub-add-item-content {
flex: 1;
overflow: hidden;
position: relative;
.mat-mdc-dialog-actions {
border-top: 1px solid rgba(0, 0, 0, 0.12);
}
}
.tb-iot-hub-add-item-loading {

2
ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-browse.component.html

@ -15,7 +15,7 @@
limitations under the License.
-->
<div class="tb-iot-hub-browse" [class.embedded]="embedded" [class.tabs-hidden]="hideTabs">
<div class="tb-iot-hub-browse" [class.embedded]="embedded" [class.tabs-hidden]="hideTabs" [class.add-mode]="mode === 'add'">
<!-- Type tabs -->
<nav mat-tab-nav-bar class="tb-iot-hub-tabs" [tabPanel]="tabPanel" [class.hidden]="hideTabs">
<a mat-tab-link

34
ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-browse.component.scss

@ -25,7 +25,7 @@
flex-direction: column;
height: 100%;
&.tabs-hidden {
&.tabs-hidden:not(.add-mode) {
border-top: 1px solid rgba(0, 0, 0, 0.12);
}
}
@ -60,6 +60,11 @@
position: relative;
padding-bottom: 48px;
margin-bottom: -48px;
.add-mode & {
padding-bottom: 0;
margin-bottom: 0;
}
}
.tb-iot-hub-filters-wrapper {
@ -121,6 +126,10 @@
flex-direction: column;
overflow-y: auto;
padding: 0 40px 0 20px;
.add-mode & {
padding-bottom: 20px;
}
}
// Top bar: results count + search
@ -410,3 +419,26 @@
width: 240px;
}
}
// Add mode responsive overrides
.add-mode {
@media #{$mat-gt-sm} {
.tb-iot-hub-card-grid {
grid-template-columns: repeat(2, 1fr);
&.tb-iot-hub-card-grid-compact {
grid-template-columns: repeat(1, 1fr);
}
}
}
@media #{$mat-lt-md} {
.tb-iot-hub-card-grid {
grid-template-columns: repeat(1, 1fr);
&.tb-iot-hub-card-grid-compact {
grid-template-columns: repeat(1, 1fr);
}
}
}
}

4
ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-item-card.component.html

@ -28,7 +28,7 @@
<h3 class="tb-iot-hub-compact-name">{{ item.name }}</h3>
<div class="tb-iot-hub-compact-meta">
<tb-icon class="tb-iot-hub-compact-author-icon">person</tb-icon>
<span class="tb-iot-hub-compact-creator" (click)="onCreatorClick($event)">{{ item.creatorDisplayName }}</span>
<span class="tb-iot-hub-compact-creator" [class.clickable]="mode !== 'add'" (click)="mode !== 'add' && onCreatorClick($event)">{{ item.creatorDisplayName }}</span>
<span class="tb-iot-hub-compact-dot">&middot;</span>
<tb-icon class="tb-iot-hub-compact-download-icon">download</tb-icon>
<span class="tb-iot-hub-compact-count">{{ item.totalInstallCount | shortNumber }}</span>
@ -71,7 +71,7 @@
<h3 class="tb-iot-hub-card-name">{{ item.name }}</h3>
<div class="tb-iot-hub-card-footer">
<tb-icon class="tb-iot-hub-card-author-icon">person</tb-icon>
<span class="tb-iot-hub-card-creator" (click)="onCreatorClick($event)">{{ item.creatorDisplayName }}</span>
<span class="tb-iot-hub-card-creator" [class.clickable]="mode !== 'add'" (click)="mode !== 'add' && onCreatorClick($event)">{{ item.creatorDisplayName }}</span>
<span class="tb-iot-hub-card-dot">&middot;</span>
<span class="tb-iot-hub-card-stat">
<tb-icon>download</tb-icon>

22
ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-item-card.component.scss

@ -178,14 +178,17 @@
}
.tb-iot-hub-compact-creator {
cursor: pointer;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
&:hover {
color: #00695c;
text-decoration: underline;
&.clickable {
cursor: pointer;
&:hover {
color: $tb-primary-color;
text-decoration: underline;
}
}
}
@ -255,11 +258,14 @@
.tb-iot-hub-card-creator {
overflow: hidden;
text-overflow: ellipsis;
cursor: pointer;
&:hover {
color: #00695c;
text-decoration: underline;
&.clickable {
cursor: pointer;
&:hover {
color: $tb-primary-color;
text-decoration: underline;
}
}
}

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

@ -73,7 +73,7 @@
<tb-markdown [data]="item.description"></tb-markdown>
</div>
}
<div class="dlg-author" (click)="navigateToCreator()">
<div class="dlg-author" [class.clickable]="mode !== 'add'" (click)="mode !== 'add' && navigateToCreator()">
<tb-icon>person</tb-icon>
<span>{{ item.creatorDisplayName }}</span>
</div>
@ -191,7 +191,7 @@
<tb-markdown [data]="item.description"></tb-markdown>
</div>
}
<div class="dlg-author" (click)="navigateToCreator()">
<div class="dlg-author" [class.clickable]="mode !== 'add'" (click)="mode !== 'add' && navigateToCreator()">
<tb-icon>person</tb-icon>
<span>{{ item.creatorDisplayName }}</span>
</div>

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

@ -178,7 +178,6 @@
display: flex;
align-items: center;
gap: 4px;
cursor: pointer;
tb-icon {
font-size: 16px;
@ -195,8 +194,12 @@
color: $tb-primary-color;
}
&:hover span {
text-decoration: underline;
&.clickable {
cursor: pointer;
&:hover span {
text-decoration: underline;
}
}
}

7
ui-ngx/src/app/modules/home/pages/dashboard/dashboards-table-config.resolver.ts

@ -402,12 +402,10 @@ export class DashboardsTableConfigResolver {
}
}
addDashboardFromIotHub($event: Event) {
if ($event) {
$event.stopPropagation();
}
addDashboardFromIotHub(_$event: Event) {
const dialogRef = this.dialog.open(TbIotHubAddItemDialogComponent, {
panelClass: ['tb-dialog', 'tb-fullscreen-dialog'],
disableClose: true,
autoFocus: false,
data: {
itemType: ItemType.DASHBOARD,
@ -416,7 +414,6 @@ export class DashboardsTableConfigResolver {
});
dialogRef.afterClosed().subscribe((result: IotHubAddItemDialogResult) => {
if (result?.descriptor?.type === 'DASHBOARD' && result.descriptor.dashboardId?.id) {
this.config.getTable().updateData();
this.router.navigateByUrl(`dashboards/${result.descriptor.dashboardId.id}`);
}
});

31
ui-ngx/src/app/modules/home/pages/rulechain/rulechains-table-config.resolver.ts

@ -49,6 +49,13 @@ import { isUndefined } from '@core/utils';
import { PageLink } from '@shared/models/page/page-link';
import { Edge } from '@shared/models/edge.models';
import { mergeMap } from 'rxjs/operators';
import { ItemType } from '@shared/models/iot-hub/iot-hub-item.models';
import { IotHubApiService } from '@core/http/iot-hub-api.service';
import {
TbIotHubAddItemDialogComponent,
IotHubAddItemDialogData,
IotHubAddItemDialogResult
} from '@home/components/iot-hub/iot-hub-add-item-dialog.component';
import { PageData } from '@shared/models/page/page-data';
import { CustomTranslatePipe } from '@shared/pipe/custom-translate.pipe';
@ -63,6 +70,7 @@ export class RuleChainsTableConfigResolver {
private importExport: ImportExportService,
private itembuffer: ItemBufferService,
private edgeService: EdgeService,
private iotHubApiService: IotHubApiService,
private translate: TranslateService,
private datePipe: DatePipe,
private router: Router,
@ -168,6 +176,12 @@ export class RuleChainsTableConfigResolver {
icon: 'file_upload',
isEnabled: () => true,
onAction: ($event) => this.importRuleChain($event)
},
{
name: this.translate.instant('iot-hub.add-from-iot-hub'),
icon: 'store',
isEnabled: () => true,
onAction: (_$event) => this.addRuleChainFromIotHub()
}
);
}
@ -288,6 +302,23 @@ export class RuleChainsTableConfigResolver {
return actions;
}
addRuleChainFromIotHub() {
const dialogRef = this.dialog.open(TbIotHubAddItemDialogComponent, {
panelClass: ['tb-dialog', 'tb-fullscreen-dialog'],
disableClose: true,
autoFocus: false,
data: {
itemType: ItemType.RULE_CHAIN,
iotHubApiService: this.iotHubApiService
} as IotHubAddItemDialogData
});
dialogRef.afterClosed().subscribe((result: IotHubAddItemDialogResult) => {
if (result?.descriptor?.type === 'RULE_CHAIN' && result.descriptor.ruleChainId?.id) {
this.router.navigateByUrl(`ruleChains/${result.descriptor.ruleChainId.id}`);
}
});
}
importRuleChain($event: Event) {
if ($event) {
$event.stopPropagation();

Loading…
Cancel
Save