Browse Source

Responsive installed items, detail dialog, search, remove DEVICE from compact

Installed items:
- Sticky actions column with more_vert dropdown menu on lt-lg
- Scrollable table wrapper, column sizing with nowrap
- ResizeObserver hidePageSize at <640px
- Filter chips/clear on separate row below toolbar on lt-lg
- Responsive padding (24px lt-md, 16px xs), column header on xs

Item detail dialog:
- Responsive widths: 1200px default, 900px lt-xxl, 768px lt-lg, 100% lt-md
- Column layout for dlg-row-1 on lt-md, header on xs
- Custom carousel controls: arrows + dots on same row
- Carousel aspect-ratio 1.5 for solution templates
- isCompactLayout method (CF/RC only, no DEVICE)

Search page:
- Responsive padding (24px lt-lg, 16px lt-sm)
- Sort button color="primary", wraps on lt-sm
- Pagination column layout on lt-sm
- Results count below pagination on lt-lg

DEVICE removed from compact layout across all components:
- Item card, browse, detail dialog, home, search
- DEVICE now uses big card layout (same as widgets/dashboards)
pull/15508/head
Igor Kulikov 3 months ago
parent
commit
a27bae710e
  1. 2
      ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-browse.component.html
  2. 1
      ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-browse.component.scss
  3. 2
      ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-browse.component.ts
  4. 2
      ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-item-card.component.ts
  5. 39
      ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-item-detail-dialog.component.html
  6. 99
      ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-item-detail-dialog.component.scss
  7. 12
      ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-item-detail-dialog.component.ts
  8. 2
      ui-ngx/src/app/modules/home/pages/iot-hub/iot-hub-home.component.ts
  9. 93
      ui-ngx/src/app/modules/home/pages/iot-hub/iot-hub-installed-items.component.html
  10. 131
      ui-ngx/src/app/modules/home/pages/iot-hub/iot-hub-installed-items.component.scss
  11. 29
      ui-ngx/src/app/modules/home/pages/iot-hub/iot-hub-installed-items.component.ts
  12. 2
      ui-ngx/src/app/modules/home/pages/iot-hub/iot-hub-search.component.html
  13. 49
      ui-ngx/src/app/modules/home/pages/iot-hub/iot-hub-search.component.scss
  14. 6
      ui-ngx/src/app/modules/home/pages/iot-hub/iot-hub-search.component.ts

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

@ -213,7 +213,7 @@
</button>
}
<span class="tb-iot-hub-sort-spacer"></span>
<button mat-button class="tb-iot-hub-sort-btn" [matMenuTriggerFor]="sortMenu">
<button mat-button color="primary" class="tb-iot-hub-sort-btn" [matMenuTriggerFor]="sortMenu">
<mat-icon>filter_list</mat-icon>
{{ sortOptions[selectedSortIndex].label | translate }}
</button>

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

@ -304,7 +304,6 @@
// Sort button Design: 14px Medium, primary color, with filter_list icon
.tb-iot-hub-sort-btn {
color: $tb-primary-color;
flex-shrink: 0;
font-size: 14px;
font-weight: 500;

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

@ -74,7 +74,7 @@ export class TbIotHubBrowseComponent implements OnInit, OnDestroy {
}
get isCompactType(): boolean {
return this._activeType === ItemType.CALCULATED_FIELD || this._activeType === ItemType.RULE_CHAIN || this._activeType === ItemType.DEVICE;
return this._activeType === ItemType.CALCULATED_FIELD || this._activeType === ItemType.RULE_CHAIN;
}
items: MpItemVersionView[] = [];

2
ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-item-card.component.ts

@ -93,7 +93,7 @@ export class TbIotHubItemCardComponent {
}
getCustomIconColor(): string | null {
if ((this.item.type === ItemType.CALCULATED_FIELD || this.item.type === ItemType.RULE_CHAIN) && this.item.color) {
if (this.isCompactLayout() && this.item.color) {
return this.item.color;
}
return null;

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

@ -18,7 +18,7 @@
<div class="tb-iot-hub-detail-dialog">
<!-- Header -->
<div class="dlg-header">
@if (item.type === ItemType.CALCULATED_FIELD || item.type === ItemType.RULE_CHAIN) {
@if (isCompactLayout()) {
<div class="dlg-header-icon" [style.background]="item.color || '#048ad3'">
<tb-icon>{{ getCompactIcon() }}</tb-icon>
</div>
@ -52,7 +52,7 @@
<div class="dlg-body">
<!-- Main content -->
<div class="dlg-main">
@if (item.type === ItemType.CALCULATED_FIELD || item.type === ItemType.RULE_CHAIN || item.type === ItemType.DEVICE) {
@if (isCompactLayout()) {
<!-- CF/RC/Device: description + author (no image) -->
<div class="dlg-info dlg-info-compact">
<div class="dlg-info-text">
@ -107,7 +107,7 @@
} @else {
<!-- Widget/Dashboard/Solution: image + description side by side -->
<div class="dlg-row-1">
<div class="dlg-preview">
<div class="dlg-preview" [class.dlg-preview-carousel]="item.type === ItemType.SOLUTION_TEMPLATE && carouselImages.length > 1">
@if (item.type === ItemType.SOLUTION_TEMPLATE && carouselImages.length > 1) {
<div class="dlg-hero-carousel">
<ngx-hm-carousel
@ -118,6 +118,7 @@
[between-delay]="0"
[autoplay]="true"
[mouse-enable]="true"
[show-num]="1"
class="dlg-carousel">
<section ngx-hm-carousel-container class="dlg-carousel-container">
<article class="dlg-carousel-item"
@ -126,21 +127,25 @@
<img [src]="imageUrl" alt="">
</article>
</section>
<ng-template #carouselPrev>
<button mat-icon-button class="dlg-carousel-nav">
<mat-icon>chevron_left</mat-icon>
</button>
</ng-template>
<ng-template #carouselNext>
<button mat-icon-button class="dlg-carousel-nav">
<mat-icon>chevron_right</mat-icon>
</button>
</ng-template>
<ng-template #carouselDot let-model>
<div class="dlg-carousel-dot"
[class.active]="model.index === model.currentIndex"></div>
</ng-template>
<ng-template #carouselPrev><span class="dlg-carousel-hidden-nav"></span></ng-template>
<ng-template #carouselNext><span class="dlg-carousel-hidden-nav"></span></ng-template>
<ng-template #carouselDot><span></span></ng-template>
</ngx-hm-carousel>
<div class="dlg-carousel-controls">
<button mat-icon-button class="dlg-carousel-nav" (click)="goToPrevSlide()">
<mat-icon>chevron_left</mat-icon>
</button>
<div class="dlg-carousel-dots">
@for (img of carouselImages; track img; let i = $index) {
<div class="dlg-carousel-dot"
[class.active]="i === carouselIndex"
(click)="carouselIndex = i"></div>
}
</div>
<button mat-icon-button class="dlg-carousel-nav" (click)="goToNextSlide()">
<mat-icon>chevron_right</mat-icon>
</button>
</div>
</div>
} @else {
@if (getPreviewUrl(); as url) {

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

@ -24,7 +24,24 @@
border-radius: 8px;
overflow: hidden;
max-height: 80vh;
width: 900px;
width: 1200px;
@media #{$mat-lt-xxl} {
width: 900px;
}
@media #{$mat-lt-lg} {
width: 768px;
}
@media #{$mat-lt-md} {
width: 100%;
}
@media #{$mat-xs} {
max-height: 100%;
height: 100%;
}
}
// Header Design: pl-24, pr-12, py-16, gap between icon+content=16, content+close=8
@ -135,6 +152,10 @@
align-items: center;
justify-content: center;
padding: 16px;
&.dlg-preview-carousel {
aspect-ratio: 1.5;
}
}
.dlg-preview-img {
@ -399,6 +420,8 @@
.dlg-hero-carousel {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
animation: dlg-carousel-fade-in 0s 0.3s forwards;
visibility: hidden;
}
@ -413,17 +436,12 @@
::ng-deep .carousel {
display: flex !important;
flex-direction: column !important;
flex: 1;
> section { flex: 1; min-height: 0; }
ul.indicators {
position: relative !important;
bottom: auto !important;
flex-shrink: 0;
padding: 8px 0;
}
.direction { height: calc(100% - 40px) !important; }
ul.indicators { display: none !important; }
.direction { display: none !important; }
}
.dlg-carousel-container {
@ -440,28 +458,50 @@
width: 100%;
height: 100%;
object-fit: contain;
padding: 8px;
}
}
}
}
.dlg-carousel-hidden-nav {
display: none;
}
.dlg-carousel-controls {
display: flex;
align-items: center;
justify-content: space-between;
flex-shrink: 0;
padding-top: 16px;
}
.dlg-carousel-dots {
display: flex;
align-items: center;
justify-content: center;
flex: 1;
}
.dlg-carousel-nav {
color: rgba(0, 0, 0, 0.6);
background: rgba(255, 255, 255, 0.8);
width: 40px;
height: 40px;
background: white;
color: rgba(0, 0, 0, 0.76);
flex-shrink: 0;
&:hover { background: rgba(255, 255, 255, 0.95); }
&:hover { background: rgba(245, 245, 245, 1); }
}
.dlg-carousel-dot {
width: 8px;
height: 8px;
border-radius: 50%;
background: rgba(0, 0, 0, 0.2);
margin: 0 3px;
width: 6px;
height: 6px;
border-radius: 999px;
background: rgba(0, 0, 0, 0.38);
margin: 9px 12px;
cursor: pointer;
transition: background 0.2s;
&.active { background: rgba(0, 0, 0, 0.6); }
&.active { background: rgba(0, 0, 0, 0.76); }
}
// Info panel Design: flex-col, space-between, py-16, gap-32
@ -576,3 +616,24 @@
.dlg-footer-spacer {
flex: 1;
}
// Responsive
@media #{$mat-lt-md} {
.dlg-row-1 {
flex-direction: column;
}
}
@media #{$mat-xs} {
.dlg-header {
flex-direction: column;
position: relative;
padding-right: 48px;
}
.dlg-close {
position: absolute;
top: 12px;
right: 12px;
}
}

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

@ -90,6 +90,10 @@ export class TbIotHubItemDetailDialogComponent extends DialogComponent<TbIotHubI
return translationKey ? this.translate.instant(translationKey) : key;
}
isCompactLayout(): boolean {
return this.item.type === ItemType.CALCULATED_FIELD || this.item.type === ItemType.RULE_CHAIN;
}
getPreviewUrl(): string | null {
return this.item.image ? this.iotHubApiService.resolveResourceUrl(this.item.image) : null;
}
@ -379,6 +383,14 @@ export class TbIotHubItemDetailDialogComponent extends DialogComponent<TbIotHubI
this.dialogRef.close({ action: 'add', item: this.item });
}
goToPrevSlide(): void {
this.carouselIndex = (this.carouselIndex - 1 + this.carouselImages.length) % this.carouselImages.length;
}
goToNextSlide(): void {
this.carouselIndex = (this.carouselIndex + 1) % this.carouselImages.length;
}
close(): void {
this.dialogRef.close();
}

2
ui-ngx/src/app/modules/home/pages/iot-hub/iot-hub-home.component.ts

@ -254,7 +254,7 @@ export class TbIotHubHomeComponent implements OnInit, OnDestroy {
}
isCompactType(type: ItemType): boolean {
return type === ItemType.CALCULATED_FIELD || type === ItemType.RULE_CHAIN || type === ItemType.DEVICE;
return type === ItemType.CALCULATED_FIELD || type === ItemType.RULE_CHAIN;
}
getCompactIcon(item: MpItemVersionView): string {

93
ui-ngx/src/app/modules/home/pages/iot-hub/iot-hub-installed-items.component.html

@ -39,37 +39,36 @@
<!-- Filter + Search row -->
<div class="tb-installed-toolbar">
<div class="tb-installed-filter-area">
<button mat-stroked-button color="primary" class="tb-installed-filter-btn" [matMenuTriggerFor]="filterMenu">
<mat-icon>filter_list</mat-icon>
{{ 'iot-hub.filter' | translate }}
</button>
<mat-menu #filterMenu="matMenu" class="tb-installed-filter-menu" xPosition="after">
@for (type of allItemTypes; track type; let last = $last) {
<div mat-menu-item class="tb-installed-filter-item" (click)="$event.stopPropagation(); toggleTypeFilter(type)">
<mat-checkbox [checked]="isTypeFilterActive(type)">
{{ getItemTypeLabel(type) }}
</mat-checkbox>
</div>
@if (!last) {
<mat-divider></mat-divider>
}
<button mat-stroked-button color="primary" class="tb-installed-filter-btn" [matMenuTriggerFor]="filterMenu">
<mat-icon>filter_list</mat-icon>
{{ 'iot-hub.filter' | translate }}
</button>
<mat-menu #filterMenu="matMenu" class="tb-installed-filter-menu" xPosition="after">
@for (type of allItemTypes; track type; let last = $last) {
<div mat-menu-item class="tb-installed-filter-item" (click)="$event.stopPropagation(); toggleTypeFilter(type)">
<mat-checkbox [checked]="isTypeFilterActive(type)">
{{ getItemTypeLabel(type) }}
</mat-checkbox>
</div>
@if (!last) {
<mat-divider></mat-divider>
}
</mat-menu>
@if (hasActiveFilters()) {
<mat-chip-set class="tb-installed-filter-chips">
@for (type of activeTypeFilters; track type) {
<mat-chip (removed)="removeTypeFilter(type)">
{{ getItemTypeLabel(type) }}
<mat-icon matChipRemove>close</mat-icon>
</mat-chip>
}
</mat-chip-set>
<button class="tb-installed-clear-btn" (click)="clearAllFilters()">
{{ 'iot-hub.clear-all' | translate }}
</button>
}
</div>
</mat-menu>
@if (hasActiveFilters()) {
<mat-chip-set class="tb-installed-filter-chips">
@for (type of activeTypeFilters; track type) {
<mat-chip (removed)="removeTypeFilter(type)">
{{ getItemTypeLabel(type) }}
<mat-icon matChipRemove>close</mat-icon>
</mat-chip>
}
</mat-chip-set>
<button class="tb-installed-clear-btn" (click)="clearAllFilters()">
{{ 'iot-hub.clear-all' | translate }}
</button>
}
<span class="tb-installed-toolbar-spacer"></span>
<div class="tb-installed-search">
<mat-icon class="tb-installed-search-icon">search</mat-icon>
<input class="tb-installed-search-input"
@ -81,6 +80,7 @@
<!-- Table + Paginator wrapped in border -->
<div class="tb-installed-table-container">
<div class="tb-installed-table-wrapper">
<table mat-table [dataSource]="dataSource" matSort matSortActive="createdTime" matSortDirection="desc">
<!-- Name -->
<ng-container matColumnDef="itemName">
@ -144,10 +144,14 @@
</ng-container>
<!-- Actions -->
<ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef></th>
<ng-container matColumnDef="actions" stickyEnd>
<th mat-header-cell *matHeaderCellDef>
<div class="gt-md:!hidden" style="min-width: 48px;"></div>
<div class="lt-lg:!hidden" style="min-width: 144px;"></div>
</th>
<td mat-cell *matCellDef="let item">
<div class="tb-installed-actions">
<!-- Desktop: individual buttons -->
<div class="tb-installed-actions lt-lg:!hidden">
<button mat-icon-button (click)="viewItemDetails(item)" matTooltip="{{ 'iot-hub.view-item-details' | translate }}">
<mat-icon>info_outline</mat-icon>
</button>
@ -158,12 +162,33 @@
<tb-icon>mdi:trash-can-outline</tb-icon>
</button>
</div>
<!-- Mobile: dropdown menu -->
<div class="gt-md:!hidden">
<button mat-icon-button (click)="$event.stopPropagation()" [matMenuTriggerFor]="actionsMenu">
<mat-icon>more_vert</mat-icon>
</button>
<mat-menu #actionsMenu="matMenu" xPosition="before">
<button mat-menu-item (click)="viewItemDetails(item)">
<mat-icon>info_outline</mat-icon>
<span>{{ 'iot-hub.view-item-details' | translate }}</span>
</button>
<button mat-menu-item (click)="openEntity(item)">
<mat-icon>open_in_new</mat-icon>
<span>{{ (item.itemType === 'SOLUTION_TEMPLATE' ? 'iot-hub.goto-main-dashboard' : 'iot-hub.open-item-type') | translate:{ type: getItemTypeLabel(item.itemType) } }}</span>
</button>
<button mat-menu-item (click)="deleteItem(item)">
<tb-icon>mdi:trash-can-outline</tb-icon>
<span>{{ 'iot-hub.remove' | translate }}</span>
</button>
</mat-menu>
</div>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-header-row *matHeaderRowDef="displayedColumns; sticky: true"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>
</div>
@if (isLoading) {
<div class="tb-installed-loading">
@ -178,11 +203,13 @@
}
<!-- Paginator inside border -->
<mat-divider></mat-divider>
<mat-paginator
[length]="totalElements"
[pageSize]="pageSize"
[pageIndex]="pageIndex"
[pageSizeOptions]="[10, 25, 50]"
[hidePageSize]="hidePageSize"
(page)="onPageChange($event)"
showFirstLastButtons>
</mat-paginator>

131
ui-ngx/src/app/modules/home/pages/iot-hub/iot-hub-installed-items.component.scss

@ -19,17 +19,22 @@
:host {
display: block;
padding: 16px;
height: 100%;
}
.tb-installed-items-page {
background: white;
border-radius: 8px;
padding: 40px 40px 40px;
height: 100%;
display: flex;
flex-direction: column;
}
// Back button
.tb-installed-back-btn {
margin-bottom: 40px;
align-self: flex-start;
}
// Header: title + check for updates
@ -52,14 +57,12 @@
.tb-installed-toolbar {
display: flex;
align-items: center;
justify-content: space-between;
gap: 8px;
margin-bottom: 16px;
}
.tb-installed-filter-area {
display: flex;
align-items: center;
gap: 8px;
.tb-installed-toolbar-spacer {
flex: 1;
}
.tb-installed-filter-btn {
@ -151,6 +154,14 @@
border: 1px solid rgba(0, 0, 0, 0.12);
border-radius: 8px;
overflow: hidden;
flex: 1;
display: flex;
flex-direction: column;
}
.tb-installed-table-wrapper {
overflow: auto;
flex: 1;
table {
width: 100%;
@ -172,10 +183,55 @@
letter-spacing: 0.2px;
color: rgba(0, 0, 0, 0.76);
}
}
::ng-deep .mat-mdc-paginator {
border-top: none;
}
// Column sizing
.mat-column-itemName {
width: 50%;
min-width: 200px;
max-width: 50%;
}
.mat-column-itemType {
width: 50%;
min-width: 50%;
max-width: 50%;
}
.mat-column-version {
width: 80px;
min-width: 80px;
max-width: 80px;
}
.mat-column-createdTime {
width: 100px;
min-width: 100px;
max-width: 100px;
}
.mat-column-updates {
width: 250px;
min-width: 250px;
max-width: 250px;
}
.mat-column-actions {
width: 108px;
min-width: 108px;
max-width: 108px;
}
::ng-deep .mat-mdc-paginator-range-label {
white-space: nowrap;
}
// Nowrap columns
.mat-column-itemType,
.mat-column-createdTime,
.mat-column-updates {
white-space: nowrap;
}
// Type chip Design: pill, h-32, rounded-16, px-12 py-6, gap-4, bg at 6% opacity
@ -308,3 +364,62 @@
color: rgba(0, 0, 0, 0.54);
font-size: 14px;
}
// Responsive
@media #{$mat-lt-lg} {
.tb-installed-toolbar {
flex-wrap: wrap;
}
.tb-installed-toolbar-spacer {
order: 0;
}
.tb-installed-search {
order: 1;
}
.tb-installed-filter-chips {
order: 10;
}
.tb-installed-clear-btn {
order: 11;
}
.tb-installed-toolbar::before {
content: '';
width: 100%;
order: 9;
}
.mat-column-actions {
width: 36px;
min-width: 36px;
max-width: 36px;
}
}
@media #{$mat-lt-md} {
.tb-installed-items-page {
padding: 40px 24px;
}
}
@media #{$mat-xs} {
.tb-installed-items-page {
padding-left: 16px;
padding-right: 16px;
}
.tb-installed-header {
flex-direction: column;
align-items: flex-start;
gap: 16px;
}
.tb-installed-search {
width: 200px;
}
}

29
ui-ngx/src/app/modules/home/pages/iot-hub/iot-hub-installed-items.component.ts

@ -14,7 +14,7 @@
/// limitations under the License.
///
import { Component, OnInit, AfterViewInit, ViewChild } from '@angular/core';
import { Component, OnInit, AfterViewInit, OnDestroy, ViewChild, ElementRef, NgZone, ChangeDetectorRef } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { MatDialog } from '@angular/material/dialog';
import { MatSort } from '@angular/material/sort';
@ -43,12 +43,15 @@ import { TbIotHubDeleteDialogComponent, IotHubDeleteDialogData } from '@home/com
templateUrl: './iot-hub-installed-items.component.html',
styleUrls: ['./iot-hub-installed-items.component.scss']
})
export class TbIotHubInstalledItemsComponent implements OnInit, AfterViewInit {
export class TbIotHubInstalledItemsComponent implements OnInit, AfterViewInit, OnDestroy {
displayedColumns: string[] = ['itemName', 'itemType', 'version', 'createdTime', 'updates', 'actions'];
dataSource: IotHubInstalledItem[] = [];
totalElements = 0;
pageSize = 10;
hidePageSize = false;
private widgetResize$: ResizeObserver;
pageIndex = 0;
isLoading = false;
textSearch = '';
@ -74,8 +77,22 @@ export class TbIotHubInstalledItemsComponent implements OnInit, AfterViewInit {
private store: Store<AppState>,
private route: ActivatedRoute,
private router: Router,
private dialog: MatDialog
) {}
private dialog: MatDialog,
private elementRef: ElementRef,
private zone: NgZone,
private cd: ChangeDetectorRef
) {
this.widgetResize$ = new ResizeObserver(() => {
this.zone.run(() => {
const shouldHide = this.elementRef.nativeElement.offsetWidth < 640;
if (shouldHide !== this.hidePageSize) {
this.hidePageSize = shouldHide;
this.cd.markForCheck();
}
});
});
this.widgetResize$.observe(this.elementRef.nativeElement);
}
ngOnInit(): void {
const itemType = this.route.snapshot.queryParamMap.get('itemType');
@ -92,6 +109,10 @@ export class TbIotHubInstalledItemsComponent implements OnInit, AfterViewInit {
this.loadData();
}
ngOnDestroy(): void {
this.widgetResize$?.disconnect();
}
ngAfterViewInit(): void {
this.sort.sortChange.subscribe(() => {
this.pageIndex = 0;

2
ui-ngx/src/app/modules/home/pages/iot-hub/iot-hub-search.component.html

@ -47,7 +47,7 @@
<mat-icon>search</mat-icon>
</button>
</mat-form-field>
<button mat-button class="tb-search-sort-btn" [matMenuTriggerFor]="sortMenu">
<button mat-button color="primary" class="tb-search-sort-btn" [matMenuTriggerFor]="sortMenu">
<mat-icon>filter_list</mat-icon>
{{ sortOptions[selectedSortIndex].label | translate }}
</button>

49
ui-ngx/src/app/modules/home/pages/iot-hub/iot-hub-search.component.scss

@ -65,7 +65,6 @@
}
.tb-search-sort-btn {
color: $tb-primary-color;
font-size: 14px;
font-weight: 500;
line-height: 20px;
@ -258,6 +257,29 @@
}
@media #{$mat-lt-lg} {
.tb-search-page {
padding: 24px;
}
.tb-search-input-field {
width: 400px;
}
.tb-search-pagination-row {
flex-direction: column;
align-items: flex-start;
gap: 12px;
}
.tb-search-results-count {
order: 1;
}
.tb-search-pagination {
order: 0;
width: 100%;
}
.tb-search-card-grid {
grid-template-columns: repeat(2, 1fr);
@ -272,14 +294,33 @@
width: 100%;
flex: 1;
}
}
@media #{$mat-lt-sm} {
.tb-search-page {
padding: 24px;
padding: 16px;
}
.tb-search-toolbar {
flex-wrap: wrap;
}
.tb-search-sort-btn {
width: 100%;
justify-content: flex-start;
}
}
@media #{$mat-lt-sm} {
.tb-search-card-grid {
grid-template-columns: repeat(1, 1fr);
}
.tb-search-pagination {
flex-direction: column;
align-items: center;
gap: 16px;
}
.tb-search-page-size {
margin-left: 0;
}
}

6
ui-ngx/src/app/modules/home/pages/iot-hub/iot-hub-search.component.ts

@ -39,8 +39,8 @@ interface SortOption {
}
const TYPE_ORDER: ItemType[] = [
ItemType.WIDGET, ItemType.DASHBOARD, ItemType.SOLUTION_TEMPLATE,
ItemType.CALCULATED_FIELD, ItemType.RULE_CHAIN, ItemType.DEVICE
ItemType.WIDGET, ItemType.DASHBOARD, ItemType.SOLUTION_TEMPLATE, ItemType.DEVICE,
ItemType.CALCULATED_FIELD, ItemType.RULE_CHAIN
];
@Component({
@ -168,7 +168,7 @@ export class TbIotHubSearchComponent implements OnInit, OnDestroy {
// Type helpers
isCompactType(type: ItemType): boolean {
return type === ItemType.CALCULATED_FIELD || type === ItemType.RULE_CHAIN || type === ItemType.DEVICE;
return type === ItemType.CALCULATED_FIELD || type === ItemType.RULE_CHAIN;
}
getTypeLabel(type: ItemType): string {

Loading…
Cancel
Save