diff --git a/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-widget-select.component.ts b/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-widget-select.component.ts
index 8671057520..3034cee011 100644
--- a/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-widget-select.component.ts
+++ b/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-widget-select.component.ts
@@ -26,7 +26,7 @@ import {
widgetType,
WidgetTypeInfo
} from '@shared/models/widget.models';
-import { debounceTime, distinctUntilChanged, map, skip, switchMap } from 'rxjs/operators';
+import { debounceTime, distinctUntilChanged, map, skip } from 'rxjs/operators';
import { BehaviorSubject, combineLatest, forkJoin, of } from 'rxjs';
import { PageLink } from '@shared/models/page/page-link';
import { Direction, SortOrder } from '@shared/models/page/sort-order';
@@ -780,21 +780,17 @@ export class DashboardWidgetSelectComponent {
}
private fetchInstalledWidgetVersions() {
- const itemIds = (this.installedWidgets || []).map(i => i.itemId);
- if (itemIds.length === 0) {
+ const versionIds = (this.installedWidgets || [])
+ .map(i => i.itemVersionId)
+ .filter(id => !!id);
+ if (versionIds.length === 0) {
this.installedWidgetVersions = [];
return of([]);
}
- return this.iotHubApiService.getItemsPublishedVersions(itemIds, { ignoreLoading: true }).pipe(
- switchMap(infos => {
- if (infos.length === 0) {
- return of([]);
- }
- const versionRequests = infos.map(info =>
- this.iotHubApiService.getVersionInfo(info.publishedVersionId, { ignoreLoading: true })
- );
- return forkJoin(versionRequests);
- }),
+ const versionRequests = versionIds.map(id =>
+ this.iotHubApiService.getVersionInfo(id, { ignoreLoading: true })
+ );
+ return forkJoin(versionRequests).pipe(
map(versions => {
this.installedWidgetVersions = versions.sort((a, b) => b.totalInstallCount - a.totalInstallCount);
return this.installedWidgetVersions;
diff --git a/ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-browse.component.html b/ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-browse.component.html
index cb59c9f5e9..0448de834c 100644
--- a/ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-browse.component.html
+++ b/ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-browse.component.html
@@ -405,87 +405,92 @@
-
- @if (isLoading) {
-
-
-
- }
+
-
- @if (hasError && !isLoading) {
-
-
-
{{ 'iot-hub.unable-to-load' | translate }}
-
{{ 'iot-hub.unable-to-load-text' | translate }}
-
-
- }
-
-
- @if (!isLoading && !hasError && items.length === 0) {
-
-
-
{{ 'iot-hub.no-items-found' | translate }}
-
{{ 'iot-hub.no-items-found-text' | translate }}
- @if (hasActiveFilters()) {
-
+
+ @if (hasError) {
+
+
+
{{ 'iot-hub.network-server-unavailable' | translate }}
+
{{ 'iot-hub.network-server-unavailable-text' | translate }}
+
+
}
-
- }
-
- @if (!isLoading && !hasError && items.length > 0) {
-
- @for (item of items; track item.id) {
-
-
+
+ @if (!hasError && items.length === 0) {
+
+
+
{{ 'iot-hub.no-items-found' | translate }}
+
{{ 'iot-hub.no-items-found-text' | translate }}
+ @if (hasActiveFilters()) {
+
+ }
+
}
-
-
-
- }
diff --git a/ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-browse.component.scss b/ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-browse.component.scss
index b377219bb7..fc685f5b90 100644
--- a/ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-browse.component.scss
+++ b/ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-browse.component.scss
@@ -112,7 +112,8 @@
}
.tb-iot-hub-filters-wrapper {
- position: absolute;
+ position: sticky;
+ max-height: calc(100vh - var(--mat-toolbar-standard-height, 64px));
inset: 0;
overflow-y: auto;
}
@@ -146,10 +147,12 @@
width: 60%;
max-width: 550px;
min-width: 300px;
- margin-bottom: -48px;
-
- .embedded & {
- margin-bottom: 0;
+ &:not(.embedded &) {
+ position: fixed;
+ top: var(--mat-toolbar-standard-height, 64px);
+ @media #{$mat-xs} {
+ top: var(--mat-toolbar-mobile-height, 56px);
+ }
}
}
@@ -421,7 +424,7 @@
// Empty state text + no-data image
.tb-iot-hub-empty-state {
- .tb-no-data-bg {
+ .tb-no-data-bg, .tb-no-service-bg {
flex: auto;
height: 100px;
}
diff --git a/ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-browse.component.ts b/ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-browse.component.ts
index 149ef64912..2efea716bf 100644
--- a/ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-browse.component.ts
+++ b/ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-browse.component.ts
@@ -113,6 +113,7 @@ export class TbIotHubBrowseComponent implements OnInit, AfterViewInit, OnDestroy
isLoading = false;
hasError = false;
filterDrawerOpened = false;
+ private retryTimer: any = null;
textSearch = '';
_activeType: ItemType = ItemType.WIDGET;
@@ -676,9 +677,23 @@ export class TbIotHubBrowseComponent implements OnInit, AfterViewInit, OnDestroy
});
}
+ retryLoadItems(): void {
+ if (this.retryTimer != null) {
+ clearTimeout(this.retryTimer);
+ }
+ this.isLoading = true;
+ this.retryTimer = setTimeout(() => {
+ this.retryTimer = null;
+ this.loadItems();
+ }, 350);
+ }
+
loadItems(): void {
+ if (this.retryTimer != null) {
+ clearTimeout(this.retryTimer);
+ this.retryTimer = null;
+ }
this.isLoading = true;
- this.hasError = false;
const sort = this.sortOptions[this.selectedSortIndex];
const sortOrder: SortOrder = { property: sort.value, direction: sort.direction };
const pageLink = new PageLink(this.pageSize, this.pageIndex, this.textSearch || null, sortOrder);
@@ -702,6 +717,7 @@ export class TbIotHubBrowseComponent implements OnInit, AfterViewInit, OnDestroy
this.items = data.data;
this.totalElements = data.totalElements;
this.isLoading = false;
+ this.hasError = false;
},
error: () => {
this.isLoading = false;
diff --git a/ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-item-card.component.html b/ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-item-card.component.html
index 70dc7d986e..dc2030b00a 100644
--- a/ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-item-card.component.html
+++ b/ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-item-card.component.html
@@ -80,7 +80,7 @@
} @else {
-
+
@if (getPreviewUrl(); as previewUrl) {
![]()
} @else {
diff --git a/ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-item-card.component.scss b/ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-item-card.component.scss
index 77d363f4ad..d46124d91e 100644
--- a/ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-item-card.component.scss
+++ b/ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-item-card.component.scss
@@ -52,11 +52,6 @@
position: relative;
overflow: hidden;
padding: 12px;
-
- &.tb-iot-hub-card-preview-device {
- background: white;
- border-bottom: 1px solid rgba(0, 0, 0, 0.12);
- }
}
.tb-iot-hub-preview-image {
diff --git a/ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-item-detail-dialog.component.html b/ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-item-detail-dialog.component.html
index c72e209037..6c0318abbc 100644
--- a/ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-item-detail-dialog.component.html
+++ b/ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-item-detail-dialog.component.html
@@ -94,8 +94,7 @@
1"
- [class.dlg-preview-device]="item.type === ItemType.DEVICE">
+ [class.dlg-preview-carousel]="item.type === ItemType.SOLUTION_TEMPLATE && carouselImages.length > 1">
@if (item.type === ItemType.SOLUTION_TEMPLATE && carouselImages.length > 1) {
-
+
- @if (!isLoading && totalElements > 0) {
-
- {{ 'iot-hub.results-count' | translate:{ count: totalElements } }}
-
- }
+
+ {{ 'iot-hub.results-count' | translate:{ count: totalElements } }}
+
@@ -56,92 +54,105 @@
-@if (!isLoading && totalElements > 0) {
-