diff --git a/ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-installed-items-table.component.html b/ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-installed-items-table.component.html
index 7bbff19a85..545d219596 100644
--- a/ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-installed-items-table.component.html
+++ b/ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-installed-items-table.component.html
@@ -29,7 +29,7 @@
{{ 'iot-hub.item-type' | translate }} |
- {{ getItemTypeIcon(item.itemType) }}
+ {{ getItemTypeIcon(item.itemType) }}
{{ getItemTypeLabel(item.itemType) }}
|
diff --git a/ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-installed-items-table.component.scss b/ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-installed-items-table.component.scss
index d83bb3e192..1edef65112 100644
--- a/ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-installed-items-table.component.scss
+++ b/ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-installed-items-table.component.scss
@@ -122,12 +122,14 @@
--mat-icon-color: currentColor;
}
-.tb-type-widget { color: rgb(32, 115, 61); background: rgba(46, 166, 88, 0.06); }
-.tb-type-dashboard { color: rgb(61, 76, 166); background: rgba(61, 76, 166, 0.06); }
-.tb-type-solution-template { color: rgb(0, 137, 186); background: rgba(0, 137, 186, 0.06); }
-.tb-type-calc-field { color: rgb(40, 120, 148); background: rgba(40, 120, 148, 0.06); }
-.tb-type-rule-chain { color: rgb(178, 121, 29); background: rgba(179, 121, 29, 0.06); }
-.tb-type-device { color: rgb(24, 146, 110); background: rgba(24, 146, 110, 0.06); }
+// Colors mirror itemTypeChipColors from the iot-hub mp-item.models.
+.tb-type-device { color: #3d4ca6; background: rgba(61, 76, 166, 0.06); }
+.tb-type-solution-template { color: #2c6cb4; background: rgba(44, 108, 180, 0.06); }
+.tb-type-widget { color: #20733d; background: rgba(46, 166, 88, 0.06); }
+.tb-type-calc-field { color: #3db5e0; background: rgba(61, 181, 224, 0.06); }
+.tb-type-alarm-rule { color: #d7702f; background: rgba(215, 112, 47, 0.06); }
+.tb-type-rule-chain { color: #aa5be3; background: rgba(170, 91, 227, 0.06); }
+.tb-type-dashboard { color: #607d8b; background: rgba(96, 125, 139, 0.06); }
// "vX.X.X Available" button — Design: border rgba(0,0,0,0.12), rounded-4, px-12 py-6, gap-8
.tb-installed-version-btn {
diff --git a/ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-installed-items-table.component.ts b/ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-installed-items-table.component.ts
index 09917528be..b625d96e2b 100644
--- a/ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-installed-items-table.component.ts
+++ b/ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-installed-items-table.component.ts
@@ -44,7 +44,7 @@ import {
ItemPublishedVersionInfo
} from '@shared/models/iot-hub/iot-hub-installed-item.models';
import { MpItemVersionView } from '@shared/models/iot-hub/iot-hub-version.models';
-import { ItemType, itemTypeTranslations } from '@shared/models/iot-hub/iot-hub-item.models';
+import { getItemTypeIcon, ItemType, itemTypeTranslations } from '@shared/models/iot-hub/iot-hub-item.models';
import { EntityType } from '@shared/models/entity-type.models';
import { getEntityDetailsPageURL } from '@core/utils';
import { IotHubActionsService } from '@home/components/iot-hub/iot-hub-actions.service';
@@ -153,16 +153,7 @@ export class TbIotHubInstalledItemsTableComponent implements OnInit, OnChanges,
}
getItemTypeIcon(itemType: string): string {
- switch (itemType) {
- case 'WIDGET': return 'widgets';
- case 'DASHBOARD': return 'dashboard';
- case 'SOLUTION_TEMPLATE': return 'integration_instructions';
- case 'CALCULATED_FIELD': return 'functions';
- case 'ALARM_RULE': return 'notification_important';
- case 'RULE_CHAIN': return 'settings_ethernet';
- case 'DEVICE': return 'memory';
- default: return 'category';
- }
+ return getItemTypeIcon(itemType);
}
deleteItem(item: IotHubInstalledItem): void {
diff --git a/ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-item-card.component.ts b/ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-item-card.component.ts
index 38c1e26dcf..bdf50acddf 100644
--- a/ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-item-card.component.ts
+++ b/ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-item-card.component.ts
@@ -16,7 +16,7 @@
import { Component, EventEmitter, Input, Output } from '@angular/core';
import { MpItemVersionView, cfTypeTranslations, cfTypeIcons, ruleChainTypeTranslations, widgetTypeTranslations } from '@shared/models/iot-hub/iot-hub-version.models';
-import { ItemType } from '@shared/models/iot-hub/iot-hub-item.models';
+import { getItemTypeIcon, ItemType } from '@shared/models/iot-hub/iot-hub-item.models';
import { IotHubInstalledItem } from '@shared/models/iot-hub/iot-hub-installed-item.models';
import { TranslateService } from '@ngx-translate/core';
import { IotHubApiService } from '@core/http/iot-hub-api.service';
@@ -69,17 +69,21 @@ export class TbIotHubItemCardComponent {
getPlaceholderIcon(): string {
switch (this.item.type) {
- case ItemType.WIDGET: return 'widgets';
- case ItemType.DASHBOARD: return 'dashboard';
- case ItemType.SOLUTION_TEMPLATE: return 'integration_instructions';
case ItemType.CALCULATED_FIELD:
- return this.item.icon || cfTypeIcons.get(this.item.dataDescriptor?.cfType) || 'functions';
+ return this.item.icon
+ || cfTypeIcons.get(this.item.dataDescriptor?.cfType)
+ || getItemTypeIcon(ItemType.CALCULATED_FIELD);
case ItemType.ALARM_RULE:
- return this.item.icon || 'notification_important';
+ return this.item.icon || getItemTypeIcon(ItemType.ALARM_RULE);
case ItemType.RULE_CHAIN:
- return this.item.icon || (this.item.dataDescriptor?.ruleChainType === 'EDGE' ? 'router' : 'device_hub');
- case ItemType.DEVICE: return 'memory';
- default: return 'extension';
+ return this.item.icon
+ || (this.item.dataDescriptor?.ruleChainType === 'EDGE'
+ ? 'router'
+ : (this.item.dataDescriptor?.ruleChainType === 'CORE'
+ ? 'device_hub'
+ : getItemTypeIcon(ItemType.RULE_CHAIN)));
+ default:
+ return getItemTypeIcon(this.item.type);
}
}
diff --git a/ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-item-detail-dialog.component.ts b/ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-item-detail-dialog.component.ts
index c770045ddc..382f2d0f88 100644
--- a/ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-item-detail-dialog.component.ts
+++ b/ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-item-detail-dialog.component.ts
@@ -21,7 +21,7 @@ import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state';
import { DialogComponent } from '@shared/components/dialog.component';
import { MpItemVersionView, cfTypeTranslations, cfTypeIcons, ruleChainTypeTranslations, widgetTypeTranslations, NodeInfo } from '@shared/models/iot-hub/iot-hub-version.models';
-import { ItemType, itemTypeTranslations } from '@shared/models/iot-hub/iot-hub-item.models';
+import { getItemTypeIcon, ItemType, itemTypeTranslations } from '@shared/models/iot-hub/iot-hub-item.models';
import { IotHubInstalledItem } from '@shared/models/iot-hub/iot-hub-installed-item.models';
import { IotHubApiService } from '@core/http/iot-hub-api.service';
import { TranslateService } from '@ngx-translate/core';
@@ -103,16 +103,7 @@ export class TbIotHubItemDetailDialogComponent extends DialogComponent
} @else {
- {{ getTypeIcon() }}
+ {{ getTypeIcon() }}
}
}
diff --git a/ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-item-link-card/iot-hub-item-link-card.component.ts b/ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-item-link-card/iot-hub-item-link-card.component.ts
index c2ca0ba1ea..743f02bea4 100644
--- a/ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-item-link-card/iot-hub-item-link-card.component.ts
+++ b/ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-item-link-card/iot-hub-item-link-card.component.ts
@@ -17,7 +17,7 @@
import { Component, Input, OnInit } from '@angular/core';
import { IotHubApiService } from '@core/http/iot-hub-api.service';
import { MpItemVersionView } from '@shared/models/iot-hub/iot-hub-version.models';
-import { ItemType } from '@shared/models/iot-hub/iot-hub-item.models';
+import { getItemTypeIcon, ItemType } from '@shared/models/iot-hub/iot-hub-item.models';
type CardState = 'loading' | 'loaded' | 'unavailable';
@@ -71,29 +71,11 @@ export class TbIotHubItemLinkCardComponent implements OnInit {
getCompactIcon(): string {
const item = this.item!;
- if (item.icon) {
- return item.icon;
- }
- switch (item.type) {
- case ItemType.CALCULATED_FIELD: return 'functions';
- case ItemType.ALARM_RULE: return 'notification_important';
- case ItemType.RULE_CHAIN: return 'account_tree';
- default: return 'category';
- }
+ return item.icon || getItemTypeIcon(item.type);
}
getTypeIcon(): string {
- const item = this.item!;
- switch (item.type) {
- case ItemType.WIDGET: return 'widgets';
- case ItemType.DASHBOARD: return 'dashboard';
- case ItemType.SOLUTION_TEMPLATE: return 'integration_instructions';
- case ItemType.CALCULATED_FIELD: return 'functions';
- case ItemType.ALARM_RULE: return 'notification_important';
- case ItemType.RULE_CHAIN: return 'account_tree';
- case ItemType.DEVICE: return 'memory';
- default: return 'category';
- }
+ return getItemTypeIcon(this.item!.type);
}
getCompactColor(): string {
diff --git a/ui-ngx/src/app/modules/home/pages/iot-hub/iot-hub-home.component.html b/ui-ngx/src/app/modules/home/pages/iot-hub/iot-hub-home.component.html
index 682411d884..f9f7285c3b 100644
--- a/ui-ngx/src/app/modules/home/pages/iot-hub/iot-hub-home.component.html
+++ b/ui-ngx/src/app/modules/home/pages/iot-hub/iot-hub-home.component.html
@@ -109,7 +109,7 @@
@if (getItemImage(item); as imgUrl) {
} @else {
-
+
}
}
diff --git a/ui-ngx/src/app/modules/home/pages/iot-hub/iot-hub-home.component.ts b/ui-ngx/src/app/modules/home/pages/iot-hub/iot-hub-home.component.ts
index 72a5513056..c8fff1ea7e 100644
--- a/ui-ngx/src/app/modules/home/pages/iot-hub/iot-hub-home.component.ts
+++ b/ui-ngx/src/app/modules/home/pages/iot-hub/iot-hub-home.component.ts
@@ -25,7 +25,7 @@ import { MediaBreakpoints } from '@shared/models/constants';
import { PageLink } from '@shared/models/page/page-link';
import { Direction, SortOrder } from '@shared/models/page/sort-order';
import { MpItemVersionQuery, MpItemVersionView } from '@shared/models/iot-hub/iot-hub-version.models';
-import { ItemType, itemTypeTranslations } from '@shared/models/iot-hub/iot-hub-item.models';
+import { getItemTypeIcon, ItemType, itemTypeTranslations } from '@shared/models/iot-hub/iot-hub-item.models';
import { IotHubInstalledItem } from '@shared/models/iot-hub/iot-hub-installed-item.models';
import { IotHubApiService } from '@core/http/iot-hub-api.service';
import { TranslateService } from '@ngx-translate/core';
@@ -266,15 +266,7 @@ export class TbIotHubHomeComponent implements OnInit, OnDestroy {
}
getCompactIcon(item: MpItemVersionView): string {
- if (item.icon) {
- return item.icon;
- }
- switch (item.type) {
- case ItemType.CALCULATED_FIELD: return 'functions';
- case ItemType.ALARM_RULE: return 'notification_important';
- case ItemType.RULE_CHAIN: return 'settings_ethernet';
- default: return 'category';
- }
+ return item.icon || getItemTypeIcon(item.type);
}
getItemImage(item: MpItemVersionView): string | null {
@@ -282,14 +274,7 @@ export class TbIotHubHomeComponent implements OnInit, OnDestroy {
}
getItemTypeIcon(type: ItemType): string {
- switch (type) {
- case ItemType.WIDGET: return 'widgets';
- case ItemType.DASHBOARD: return 'dashboard';
- case ItemType.SOLUTION_TEMPLATE: return 'integration_instructions';
- case ItemType.ALARM_RULE: return 'notification_important';
- case ItemType.DEVICE: return 'memory';
- default: return 'category';
- }
+ return getItemTypeIcon(type);
}
getSearchGroupLabel(type: ItemType): string {
diff --git a/ui-ngx/src/app/shared/models/iot-hub/iot-hub-item.models.ts b/ui-ngx/src/app/shared/models/iot-hub/iot-hub-item.models.ts
index 6451bc5d52..6c528384c4 100644
--- a/ui-ngx/src/app/shared/models/iot-hub/iot-hub-item.models.ts
+++ b/ui-ngx/src/app/shared/models/iot-hub/iot-hub-item.models.ts
@@ -36,6 +36,23 @@ export const itemTypeTranslations = new Map(
]
);
+// Canonical icon lookup per item type. Values are tb-icon
+// identifiers (Material symbol names or `mdi:*` strings) and should
+// be used everywhere an icon is rendered for an item type so the
+// mapping stays consistent across the app.
+export const itemTypeIcons: Record = {
+ [ItemType.WIDGET]: 'widgets',
+ [ItemType.DASHBOARD]: 'dashboard',
+ [ItemType.SOLUTION_TEMPLATE]: 'apps',
+ [ItemType.CALCULATED_FIELD]: 'mdi:function-variant',
+ [ItemType.RULE_CHAIN]: 'settings_ethernet',
+ [ItemType.ALARM_RULE]: 'mdi:bell-cog',
+ [ItemType.DEVICE]: 'devices_other'
+};
+
+export const getItemTypeIcon = (type?: string | null): string =>
+ type && itemTypeIcons[type] ? itemTypeIcons[type] : 'category';
+
/**
* Item types discoverable to creators in the marketplace UI.
* DASHBOARD is intentionally absent (IoT Hub no longer accepts Dashboard contributions).