diff --git a/ui-ngx/src/app/core/services/menu.models.ts b/ui-ngx/src/app/core/services/menu.models.ts index 8a391383c5..443debdc43 100644 --- a/ui-ngx/src/app/core/services/menu.models.ts +++ b/ui-ngx/src/app/core/services/menu.models.ts @@ -750,7 +750,7 @@ export const menuSectionMap = new Map([ name: 'iot-hub.iot-hub', type: 'link', path: '/iot-hub', - icon: 'store', + icon: 'hub', isNew: true } ] diff --git a/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-widget-select.component.html b/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-widget-select.component.html index 6719d02eb7..7d2ea9cdb5 100644 --- a/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-widget-select.component.html +++ b/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-widget-select.component.html @@ -19,13 +19,25 @@
@if (showTopLevelWidgetModeToggle()) { - - {{ 'widget.installed' | translate }} - {{ 'iot-hub.iot-hub' | translate }} + + + +
+ now_widgets +
{{ 'widget.installed' | translate }}
+
+
+ +
+ hub +
{{ 'iot-hub.iot-hub' | translate }}
+
+
} @else if (showBackButton()) { + } @else { + }
- + + @for (option of sortOptions; track option.value; let i = $index) { + + } + - -
+ +
{{ 'iot-hub.results-count' | translate:{ count: totalElements } }} @@ -391,16 +399,10 @@ {{ 'iot-hub.clear-all' | translate }} } - - - - @for (option of sortOptions; track option.value; let i = $index) { - - } -
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 4a0ad1b5cd..b377219bb7 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 @@ -325,27 +325,49 @@ } .tb-iot-hub-search-field { - @include tb-iot-hub-search-container; - width: 320px; -} - -.tb-iot-hub-search-icon { - @include tb-iot-hub-search-icon; + @include tb-iot-hub-page-search-container; } .tb-iot-hub-search-input { - @include tb-iot-hub-search-input-text; + @include tb-iot-hub-page-search-input; } -.tb-iot-hub-search-clear.mat-mdc-icon-button { - @include tb-iot-hub-search-clear; +.tb-iot-hub-search-action { + @include tb-iot-hub-page-search-action; } -// Sort button — Design: 14px Medium, primary color, with filter_list icon +// Sort button — Design: same row as search, 40px h, 88px min-w, 4px radius, +// 14px Medium primary color, trailing arrow_drop_down 24px icon .tb-iot-hub-sort-btn { flex-shrink: 0; + height: 40px; + min-width: 88px; + padding: 8px; font-size: 14px; font-weight: 500; + line-height: 20px; + letter-spacing: 0.25px; + border-radius: 4px; + + .mat-icon { + font-size: 24px; + width: 24px; + height: 24px; + } +} + +// Filter chips row — Design: 32px tall, no padding, centered +.tb-iot-hub-sort-row { + height: 32px; + align-items: center; + padding: 0; + margin-top: 16px; + margin-bottom: 12px; + + .mat-mdc-chip { + margin-top: 0; + margin-bottom: 0; + } } // Active filter chips — Design: mat-chip-set, gap-8, chip bg rgba(0,0,0,0.04) @@ -557,10 +579,6 @@ width: 100%; max-width: 100%; } - - .tb-iot-hub-search-field { - width: 200px; - } } @media #{$mat-xs} { 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 a6daaf8772..149ef64912 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 @@ -93,6 +93,19 @@ export class TbIotHubBrowseComponent implements OnInit, AfterViewInit, OnDestroy || this._activeType === ItemType.RULE_CHAIN; } + get searchPlaceholderKey(): string { + switch (this._activeType) { + case ItemType.WIDGET: return 'iot-hub.search-widgets'; + case ItemType.DASHBOARD: return 'iot-hub.search-dashboards'; + case ItemType.SOLUTION_TEMPLATE: return 'iot-hub.search-solution-templates'; + case ItemType.CALCULATED_FIELD: return 'iot-hub.search-calculated-fields'; + case ItemType.ALARM_RULE: return 'iot-hub.search-alarm-rules'; + case ItemType.RULE_CHAIN: return 'iot-hub.search-rule-chains'; + case ItemType.DEVICE: return 'iot-hub.search-devices'; + default: return 'iot-hub.search'; + } + } + items: MpItemVersionView[] = []; totalElements = 0; pageSize = 12; 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 176aac34ab..7bbff19a85 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 @@ -16,7 +16,7 @@ -->
-
+
@@ -134,19 +134,26 @@
-
- @if (isLoading) { -
- -
- } + @if (isLoading) { +
+ +
+ } - @if (!isLoading && dataSource.length === 0) { -
- {{ 'iot-hub.no-installed-items' | translate }} -
- } + @if (!isLoading && dataSource.length === 0) { +
+
+

{{ 'iot-hub.no-installed-items' | translate }}

+

{{ 'iot-hub.no-installed-items-text' | translate }}

+ @if (hasActiveFilters()) { + + } +
+ } +
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 817bd7dc16..d83bb3e192 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 @@ -203,8 +203,25 @@ } } -.tb-installed-empty { - color: rgba(0, 0, 0, 0.54); +// Empty state — mirrors the browse component's tb-iot-hub-empty-state +.tb-iot-hub-empty-state { + .tb-no-data-bg { + flex: auto; + height: 100px; + } + + h3 { + font-size: 18px; + font-weight: 500; + color: rgba(0, 0, 0, 0.87); + margin: 16px 0 8px; + } + + p { + font-size: 14px; + color: rgba(0, 0, 0, 0.54); + margin: 0 0 24px; + } } :host(:not(.tb-installed-with-version)) { 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 2ad2946fd4..cc0f760ac5 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 @@ -19,12 +19,14 @@ import { ChangeDetectorRef, Component, ElementRef, + EventEmitter, HostBinding, Input, NgZone, OnChanges, OnDestroy, OnInit, + Output, SimpleChanges, ViewChild } from '@angular/core'; @@ -59,6 +61,12 @@ export class TbIotHubInstalledItemsTableComponent implements OnInit, OnChanges, @Input() typeFilters: string[] = []; @Input() itemVersion: MpItemVersionView; + @Output() clearFilters = new EventEmitter(); + + hasActiveFilters(): boolean { + return !!this.textSearch || (this.typeFilters?.length ?? 0) > 0; + } + @HostBinding('class.tb-installed-with-version') get withVersionClass() { return !!this.itemVersion; } diff --git a/ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-search.component.html b/ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-search.component.html index af3931b9a6..cf14453fb7 100644 --- a/ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-search.component.html +++ b/ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-search.component.html @@ -25,22 +25,25 @@
-
- search +
@if (searchText) { - + } @else { + }
- @for (item of popularWidgets; track item.id) { + @for (item of popularDevices; track item.id) { + (installClick)="installItem($event)"> }
} - + @if (popularSolutionTemplates.length) {
@@ -203,34 +207,36 @@
} - - @if (popularDevices.length) { + + @if (popularWidgets.length) {
-
- @for (item of popularDevices; track item.id) { + @for (item of popularWidgets; track item.id) { + (installClick)="installItem($event)" + (updateClick)="updateItem($event)" + (deleteClick)="deleteInstalledItem($event)"> }
} - + @if (popularCalcFields.length) {
@@ -248,11 +254,11 @@
} - + @if (popularAlarmRules.length) {
@@ -270,11 +276,11 @@
} - + @if (popularRuleChains.length) {
diff --git a/ui-ngx/src/app/modules/home/pages/iot-hub/iot-hub-home.component.scss b/ui-ngx/src/app/modules/home/pages/iot-hub/iot-hub-home.component.scss index a728bf25ec..9905ab1515 100644 --- a/ui-ngx/src/app/modules/home/pages/iot-hub/iot-hub-home.component.scss +++ b/ui-ngx/src/app/modules/home/pages/iot-hub/iot-hub-home.component.scss @@ -29,7 +29,8 @@ border-radius: 8px; overflow: hidden; - // Dot grid pattern — covers top 800px, fades out via gradient mask + // Dot grid pattern — covers top 800px, fades out via gradient mask. + // Layered ABOVE the colored blobs so the dots overlay the glow. &::before { content: ''; position: absolute; @@ -42,12 +43,12 @@ mask-image: linear-gradient(to bottom, black 0%, transparent 100%); -webkit-mask-image: linear-gradient(to bottom, black 0%, transparent 100%); pointer-events: none; - z-index: 0; + z-index: 1; } - > *:not(.tb-iot-hub-installed-btn) { + > *:not(.tb-iot-hub-installed-btn):not(.tb-iot-hub-blob) { position: relative; - z-index: 1; + z-index: 2; } } @@ -56,7 +57,7 @@ position: absolute; top: 24px; right: 24px; - z-index: 2; + z-index: 3; background: white; box-shadow: 0 1px 4px 0 rgba(0, 0, 0, 0.08), 0 4px 8px 0 rgba(0, 0, 0, 0.08); @@ -73,84 +74,80 @@ overflow: hidden; } -// Animated background gradient -.tb-iot-hub-hero-gradient { +// Soft colored glow blobs — direct CSS port of the design's two +// 568×568 ellipses (Ellipse 399 right, Ellipse 400 left) with layer +// opacity 0.16. Children of the page container so the halo spreads +// across the whole page background, not just the hero. Fill comes +// from the active hero type via `currentColor` (driven by +// `[style.color]`). +// +// The design's "Layer Blur 240" is a Figma renderer parameter — when +// translated to CSS `filter: blur(<σ>)` the visual match is around +// σ=120 (Figma's radius is roughly twice the Gaussian σ used by CSS). +// At σ=240 the kernel reaches well outside the 568px ellipse and peak +// intensity collapses to ~58 % before opacity is applied, which +// produced an almost invisible wash. σ=120 keeps the centre near +// full strength while still spreading the halo across the page. +.tb-iot-hub-blob { position: absolute; - inset: 0; - transition: background 0.6s ease; + width: 568px; + height: 568px; + border-radius: 50%; + background: currentColor; + opacity: 0.16; + filter: blur(120px); pointer-events: none; + z-index: 0; + transition: color 0.6s ease; + will-change: filter; +} + +// Ellipse 400 — top-left corner at (-221, 56) inside the page-container. +.tb-iot-hub-blob-left { + top: 56px; + left: -221px; } -// Floating icons container per type +// Ellipse 399 — top-left corner at (1266, 259) inside a 1638-wide +// page-container. Anchored to the right edge so it stays in place on +// any viewport width: 1638 - (1266 + 568) = -196. +.tb-iot-hub-blob-right { + top: 259px; + right: -196px; +} + +// Floating icons cluster per type — one composite SVG with all icons baked in. +// Active variant fades in expanding outward from the hero center; inactive +// variants fade out collapsing back toward the center. This is achieved by +// uniformly scaling the wrapper around its centre — peripheral icons travel +// further than central ones, giving the "burst from / collapse to centre" +// motion shown in the design prototype. .tb-iot-hub-hero-icons { position: absolute; inset: 0; pointer-events: none; + opacity: 0; + transform: scale(0.8); + transform-origin: 50% 50%; + transition: opacity 0.4s ease-out, transform 0.6s cubic-bezier(0.4, 0, 0.2, 1); - // Icons start near center (translated toward center, scaled down, invisible) - .tb-iot-hub-hero-float-icon { - opacity: 0; - transform: translate(var(--start-x), var(--start-y)) scale(0.9); - transition: opacity 0.5s ease, transform 0.6s cubic-bezier(0.34, 1.56, 0.64, 1); - } - - // Active: icons move outward to final position, scale to 1, fully visible - &.active .tb-iot-hub-hero-float-icon { + &.active { opacity: 1; - transform: translate(0, 0) scale(1); + transform: scale(1); } } -// Individual floating icon — SVG has rotation/bg/shadow baked in, CSS handles position + animation -// Base: ≥1600px — 78px top icons (top: 40px), 87px bottom icons (top: 216px, bottom edge: 303px) -.tb-iot-hub-hero-float-icon { +// Cluster SVG — sits above the title, centered, scales with viewport. +// Aspect ratio is preserved by the SVG's intrinsic dimensions. +.tb-iot-hub-hero-cluster { position: absolute; - width: 78px; - height: 78px; - - img { - width: 100%; - height: 100%; - display: block; - } - - // Top-left - &.icon-pos-1 { - top: 40px; - left: calc(50% - 404px); - --start-x: 40px; - --start-y: 12px; - } - - // Top-right — mirrors icon-pos-1 - &.icon-pos-2 { - top: 40px; - left: auto; - right: calc(50% - 404px); - --start-x: -40px; - --start-y: 12px; - } - - // Bottom-left — 87px bounding box - &.icon-pos-3 { - top: 216px; - left: calc(50% - 487px); - width: 87px; - height: 87px; - --start-x: 50px; - --start-y: -8px; - } - - // Bottom-right — 87px bounding box, mirrors icon-pos-3 - &.icon-pos-4 { - top: 216px; - left: auto; - right: calc(50% - 487px); - width: 87px; - height: 87px; - --start-x: -45px; - --start-y: -4px; - } + top: 40px; + left: 50%; + transform: translateX(-50%); + width: min(890px, calc(100% - 80px)); + height: auto; + display: block; + pointer-events: none; } .tb-iot-hub-hero-content { @@ -444,7 +441,10 @@ width: 100%; } -// Card — Design: flex-col, gap=24, pt=24, rounded-8, border, overflow-clip, h=220 +// Card — design: flex-col, gap=24, pt=24, rounded-8, h=220, overflow clipped +// to crop the scaled hover image. The hover state mirrors the design's +// SMART_ANIMATE on hover (200ms ease-out): the image scales up slightly +// and the title chevron fades+slides in. .tb-iot-hub-category-card { border-radius: 8px; cursor: pointer; @@ -453,62 +453,93 @@ align-items: center; gap: 24px; padding-top: 24px; - transition: transform 0.2s, box-shadow 0.2s; + height: 220px; border: 1px solid rgba(0, 0, 0, 0.12); overflow: hidden; &:hover { - transform: translateY(-2px); - box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08); + .tb-iot-hub-category-img img { + // 408 / 387 ≈ 1.054 — design grows the img frame from 387×148 → 408×156 + transform: scale(1.054); + } + .tb-iot-hub-category-chevron { + opacity: 1; + width: 24px; + margin-left: 4px; + transform: translateX(0); + } } } -// Title — Design: 18px Medium, centered, tracking=0.15, flex child +// Title — design: 18px Medium, centered horizontally with chevron, 4px gap .tb-iot-hub-category-title { font-size: 18px; font-weight: 500; line-height: 24px; letter-spacing: 0.15px; color: rgba(0, 0, 0, 0.87); - text-align: center; - width: 100%; - flex-shrink: 0; -} - -// Card image — Design: h=148, w=full, overflow-clip, fills remaining space -.tb-iot-hub-category-img { - width: 100%; - object-fit: contain; + display: inline-flex; + align-items: center; + justify-content: center; flex-shrink: 0; } -// Exact Design gradients (104.75deg angle) -.category-widgets { - background: linear-gradient(104.75deg, rgb(240, 255, 245) 0%, rgb(147, 246, 182) 100%); +.tb-iot-hub-category-title-text { + white-space: nowrap; } -.category-dashboards { - background: linear-gradient(104.75deg, rgb(245, 246, 255) 0%, rgb(189, 197, 255) 100%); -} - -.category-solutions { - background: linear-gradient(104.75deg, rgb(245, 250, 255) 0%, rgb(149, 200, 255) 100%); +// Chevron — hidden in default state, slides in on card hover (200ms ease-out) +.tb-iot-hub-category-chevron { + width: 0; + height: 24px; + margin-left: 0; + opacity: 0; + overflow: hidden; + transform: translateX(-4px); + font-size: 24px; + color: rgba(0, 0, 0, 0.87); + transition: + opacity 0.2s ease-out, + transform 0.2s ease-out, + width 0.2s ease-out, + margin-left 0.2s ease-out; } -.category-calc-fields { - background: linear-gradient(104.75deg, rgb(245, 252, 255) 0%, rgb(149, 222, 248) 100%); -} +// Card image wrapper — fixed 148px tall; overflow visible lets the 5.4% +// hover scale bleed past the wrapper. The card itself has overflow: +// hidden, so the bleed is still clipped at the card edges. +.tb-iot-hub-category-img { + width: 100%; + height: 148px; + flex-shrink: 0; + overflow: visible; -.category-alarm-rules { - background: linear-gradient(104.75deg, rgb(245, 246, 255) 0%, rgb(189, 197, 255) 100%); + img { + width: 100%; + height: 100%; + object-fit: cover; + object-position: center top; + transition: transform 0.2s ease-out; + } } -.category-rule-chains { - background: linear-gradient(104.75deg, rgb(255, 252, 245) 0%, rgb(255, 238, 194) 100%); -} +// Per-card flat background colors sampled from the design. +.category-devices { background: #ccd5ff; } +.category-solutions { background: #b7d8ff; } +.category-widgets { background: #a3ffc3; } +.category-calc-fields { background: #bcedff; } +.category-alarm-rules { background: #ffe6cc; } +.category-rule-chains { background: #ebd1ff; } -.category-devices { - background: linear-gradient(104.75deg, rgb(245, 255, 252) 0%, rgb(147, 240, 213) 100%); +// "Most popular in IoT Hub" title — design: 28/36 Medium, sits between +// the post-cards divider and the first popular section. +.tb-iot-hub-most-popular-title { + font-size: 28px; + font-weight: 500; + line-height: 36px; + letter-spacing: 0.15px; + color: rgba(0, 0, 0, 0.87); + margin: 0; } // Sections — inside main-content, no individual padding needed @@ -552,6 +583,12 @@ background: rgba(0, 0, 0, 0.12); } +// Bleed variant — used inside main-content (which has 40px horizontal +// padding) to span the full page-container width like in the design. +.tb-iot-hub-divider-bleed { + margin: 0 -40px; +} + // Become a Creator — matches Design (pt=64, text centered, button at y=156) .tb-iot-hub-become-creator { text-align: center; @@ -673,60 +710,18 @@ padding: 64px 24px; } - // Icons: ≥1280px — 69px top (top: 90px), 77px bottom (top: 246px, bottom edge: 323px) - .tb-iot-hub-hero-float-icon { - width: 69px; - height: 69px; - - &.icon-pos-1 { - top: 90px; - left: 106px; - } - - &.icon-pos-2 { - top: 90px; - left: auto; - right: 106px; - } - - &.icon-pos-3 { - top: 246px; - left: 28px; - width: 77px; - height: 77px; - } - - &.icon-pos-4 { - top: 246px; - left: auto; - right: 28px; - width: 77px; - height: 77px; - } + // Cluster shrinks with viewport — keep some gutter on the sides + .tb-iot-hub-hero-cluster { + top: 30px; + width: min(900px, calc(100% - 48px)); } } -// ≤959px: only top pair, area width ≤160px (icon 51px + gap + icon 51px) +// ≤959px: cluster sits closer to the title and uses the full content width @media #{$mat-lt-md} { - .tb-iot-hub-hero-float-icon { - width: 51px; - height: 51px; - - &.icon-pos-1 { - top: 80px; - left: calc(50% - 80px); - } - - &.icon-pos-2 { - top: 80px; - left: auto; - right: calc(50% - 80px); - } - - &.icon-pos-3, - &.icon-pos-4 { - display: none; - } + .tb-iot-hub-hero-cluster { + top: 64px; + width: calc(100% - 32px); } } 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 898230a1e4..e095ef3cc8 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 @@ -44,8 +44,7 @@ interface HeroTypeConfig { type: ItemType; labelKey: string; color: string; - gradientColor: string; - icons: string[]; + icon: string; } interface SearchResultGroup { @@ -53,6 +52,11 @@ interface SearchResultGroup { items: MpItemVersionView[]; } +const SEARCH_GROUP_ORDER: ItemType[] = [ + ItemType.DEVICE, ItemType.SOLUTION_TEMPLATE, ItemType.WIDGET, + ItemType.CALCULATED_FIELD, ItemType.ALARM_RULE, ItemType.RULE_CHAIN +]; + @Component({ selector: 'tb-iot-hub-home', standalone: false, @@ -76,34 +80,28 @@ export class TbIotHubHomeComponent implements OnInit, OnDestroy { heroTypes: HeroTypeConfig[] = [ { - type: ItemType.WIDGET, labelKey: 'item.type-widget-plural', color: '#2c9755', - gradientColor: 'rgba(44, 151, 85, 0.1)', - icons: ['assets/iot-hub/hero-widget-icon-1.svg', 'assets/iot-hub/hero-widget-icon-2.svg', 'assets/iot-hub/hero-widget-icon-3.svg', 'assets/iot-hub/hero-widget-icon-4.svg'] + type: ItemType.DEVICE, labelKey: 'item.type-device-plural', color: '#4b63cc', + icon: 'assets/iot-hub/hero-device-cluster.svg' }, { - type: ItemType.SOLUTION_TEMPLATE, labelKey: 'item.type-solution-template-plural', color: '#2666a9', - gradientColor: 'rgba(38, 102, 169, 0.1)', - icons: ['assets/iot-hub/hero-solution-template-icon-1.svg', 'assets/iot-hub/hero-solution-template-icon-2.svg', 'assets/iot-hub/hero-solution-template-icon-3.svg', 'assets/iot-hub/hero-solution-template-icon-4.svg'] + type: ItemType.SOLUTION_TEMPLATE, labelKey: 'item.type-solution-template-plural', color: '#2b6bb4', + icon: 'assets/iot-hub/hero-solution-template-cluster.svg' }, { - type: ItemType.DEVICE, labelKey: 'item.type-device-plural', color: '#4b8a79', - gradientColor: 'rgba(75, 138, 121, 0.1)', - icons: ['assets/iot-hub/hero-device-icon-1.svg', 'assets/iot-hub/hero-device-icon-2.svg', 'assets/iot-hub/hero-device-icon-3.svg', 'assets/iot-hub/hero-device-icon-4.svg'] + type: ItemType.WIDGET, labelKey: 'item.type-widget-plural', color: '#2c9755', + icon: 'assets/iot-hub/hero-widget-cluster.svg' }, { - type: ItemType.CALCULATED_FIELD, labelKey: 'item.type-calculated-field-plural', color: '#006d92', - gradientColor: 'rgba(0, 109, 146, 0.1)', - icons: ['assets/iot-hub/hero-calculated-field-icon-1.svg', 'assets/iot-hub/hero-calculated-field-icon-2.svg', 'assets/iot-hub/hero-calculated-field-icon-3.svg', 'assets/iot-hub/hero-calculated-field-icon-4.svg'] + type: ItemType.CALCULATED_FIELD, labelKey: 'item.type-calculated-field-plural', color: '#3cb4e0', + icon: 'assets/iot-hub/hero-calculated-field-cluster.svg' }, { - type: ItemType.ALARM_RULE, labelKey: 'item.type-alarm-rule-plural', color: '#4d5fd0', - gradientColor: 'rgba(77, 95, 208, 0.1)', - icons: ['assets/iot-hub/hero-dashboard-icon-1.svg', 'assets/iot-hub/hero-dashboard-icon-2.svg', 'assets/iot-hub/hero-dashboard-icon-3.svg', 'assets/iot-hub/hero-dashboard-icon-4.svg'] + type: ItemType.ALARM_RULE, labelKey: 'item.type-alarm-rule-plural', color: '#d66f2e', + icon: 'assets/iot-hub/hero-alarm-rule-cluster.svg' }, { - type: ItemType.RULE_CHAIN, labelKey: 'item.type-rule-chain-plural', color: '#95694b', - gradientColor: 'rgba(149, 105, 75, 0.1)', - icons: ['assets/iot-hub/hero-rule-chain-icon-1.svg', 'assets/iot-hub/hero-rule-chain-icon-2.svg', 'assets/iot-hub/hero-rule-chain-icon-3.svg', 'assets/iot-hub/hero-rule-chain-icon-4.svg'] + type: ItemType.RULE_CHAIN, labelKey: 'item.type-rule-chain-plural', color: '#a95ae2', + icon: 'assets/iot-hub/hero-rule-chain-cluster.svg' } ]; @@ -112,12 +110,12 @@ export class TbIotHubHomeComponent implements OnInit, OnDestroy { private heroInterval: any; categoryCards: CategoryCard[] = [ - { type: ItemType.WIDGET, titleKey: 'item.type-widget-plural', icon: 'widgets', cssClass: 'category-widgets', image: 'assets/iot-hub/category-widgets-img.svg' }, + { type: ItemType.DEVICE, titleKey: 'iot-hub.device-library', icon: 'memory', cssClass: 'category-devices', image: 'assets/iot-hub/category-device-library-img.png' }, { type: ItemType.SOLUTION_TEMPLATE, titleKey: 'item.type-solution-template-plural', icon: 'integration_instructions', cssClass: 'category-solutions', image: 'assets/iot-hub/category-solution-templates-img.png' }, - { type: ItemType.DEVICE, titleKey: 'iot-hub.device-library', icon: 'memory', cssClass: 'category-devices', image: 'assets/iot-hub/category-device-library-img.svg' }, - { type: ItemType.CALCULATED_FIELD, titleKey: 'item.type-calculated-field-plural', icon: 'functions', cssClass: 'category-calc-fields', image: 'assets/iot-hub/category-calculated-fields-img.svg' }, - { type: ItemType.ALARM_RULE, titleKey: 'item.type-alarm-rule-plural', icon: 'notification_important', cssClass: 'category-alarm-rules', image: 'assets/iot-hub/category-dashboards-img.svg' }, - { type: ItemType.RULE_CHAIN, titleKey: 'item.type-rule-chain-plural', icon: 'account_tree', cssClass: 'category-rule-chains', image: 'assets/iot-hub/category-rule-chains-img.svg' } + { type: ItemType.WIDGET, titleKey: 'item.type-widget-plural', icon: 'widgets', cssClass: 'category-widgets', image: 'assets/iot-hub/category-widgets-img.png' }, + { type: ItemType.CALCULATED_FIELD, titleKey: 'item.type-calculated-field-plural', icon: 'functions', cssClass: 'category-calc-fields', image: 'assets/iot-hub/category-calculated-fields-img.png' }, + { type: ItemType.ALARM_RULE, titleKey: 'item.type-alarm-rule-plural', icon: 'notification_important', cssClass: 'category-alarm-rules', image: 'assets/iot-hub/category-alarm-rules-img.png' }, + { type: ItemType.RULE_CHAIN, titleKey: 'item.type-rule-chain-plural', icon: 'account_tree', cssClass: 'category-rule-chains', image: 'assets/iot-hub/category-rule-chains-img.png' } ]; popularWidgets: MpItemVersionView[] = []; @@ -301,6 +299,15 @@ export class TbIotHubHomeComponent implements OnInit, OnDestroy { void this.router.navigate(['/iot-hub', this.getTypeRoute(type)]); } + hasAnyPopularItems(): boolean { + return this.popularDevices.length > 0 + || this.popularSolutionTemplates.length > 0 + || this.popularWidgets.length > 0 + || this.popularCalcFields.length > 0 + || this.popularAlarmRules.length > 0 + || this.popularRuleChains.length > 0; + } + private getTypeRoute(type: ItemType): string { switch (type) { case ItemType.WIDGET: return 'widgets'; @@ -522,6 +529,9 @@ export class TbIotHubHomeComponent implements OnInit, OnDestroy { private groupSearchResults(items: MpItemVersionView[]): SearchResultGroup[] { const groupMap = new Map(); for (const item of items) { + if (!SEARCH_GROUP_ORDER.includes(item.type)) { + continue; + } let list = groupMap.get(item.type); if (!list) { list = []; @@ -529,6 +539,8 @@ export class TbIotHubHomeComponent implements OnInit, OnDestroy { } list.push(item); } - return Array.from(groupMap.entries()).map(([type, groupItems]) => ({ type, items: groupItems })); + return SEARCH_GROUP_ORDER + .filter(type => groupMap.has(type)) + .map(type => ({ type, items: groupMap.get(type) })); } } diff --git a/ui-ngx/src/app/modules/home/pages/iot-hub/iot-hub-installed-items.component.html b/ui-ngx/src/app/modules/home/pages/iot-hub/iot-hub-installed-items.component.html index c284d3d548..be6793f766 100644 --- a/ui-ngx/src/app/modules/home/pages/iot-hub/iot-hub-installed-items.component.html +++ b/ui-ngx/src/app/modules/home/pages/iot-hub/iot-hub-installed-items.component.html @@ -37,8 +37,8 @@ }
- -
+ +
} - - + + +
+
+ [typeFilters]="typeFilters" + (clearFilters)="clearAllFilters()">
diff --git a/ui-ngx/src/app/modules/home/pages/iot-hub/iot-hub-installed-items.component.scss b/ui-ngx/src/app/modules/home/pages/iot-hub/iot-hub-installed-items.component.scss index eb97f64682..0ac5db7e61 100644 --- a/ui-ngx/src/app/modules/home/pages/iot-hub/iot-hub-installed-items.component.scss +++ b/ui-ngx/src/app/modules/home/pages/iot-hub/iot-hub-installed-items.component.scss @@ -15,6 +15,7 @@ */ @import "../../../../../scss/constants"; +@import "../../components/iot-hub/iot-hub-common"; :host { display: block; @@ -49,12 +50,25 @@ margin: 0; } -// Toolbar: filter + search -.tb-installed-toolbar { +// Filter row — filter button + active chips on top +.tb-installed-filter-row { display: flex; + flex-wrap: wrap; align-items: center; gap: 8px; margin-bottom: 16px; + + .mat-mdc-chip { + margin-top: 0; + margin-bottom: 0; + } +} + +// Search row — full-width search input below the filter row +.tb-installed-search-row { + display: flex; + align-items: center; + margin-bottom: 16px; } .tb-installed-filter-btn { @@ -104,67 +118,19 @@ } } -// Search field .tb-installed-search { - width: 320px; - height: 40px; - display: flex; - align-items: center; - gap: 8px; - padding: 8px 12px; - border-radius: 8px; - border: 1px solid rgba(0, 0, 0, 0.12); - background: white; -} - -.tb-installed-search-icon { - font-size: 24px; - width: 24px; - height: 24px; - color: rgba(0, 0, 0, 0.38); - flex-shrink: 0; + @include tb-iot-hub-page-search-container; } .tb-installed-search-input { - flex: 1; - border: none; - outline: none; - font-size: 14px; - font-weight: 400; - color: rgba(0, 0, 0, 0.87); - background: transparent; - font-family: inherit; - - &::placeholder { - color: rgba(0, 0, 0, 0.38); - } + @include tb-iot-hub-page-search-input; } -// Responsive -@media #{$mat-lt-lg} { - .tb-installed-toolbar { - flex-wrap: wrap; - } - - .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; - } +.tb-installed-search-action { + @include tb-iot-hub-page-search-action; } +// Responsive @media #{$mat-lt-md} { .tb-installed-items-page { padding: 40px 24px; @@ -182,8 +148,4 @@ align-items: flex-start; gap: 16px; } - - .tb-installed-search { - width: 200px; - } } diff --git a/ui-ngx/src/app/modules/home/pages/iot-hub/iot-hub-installed-items.component.ts b/ui-ngx/src/app/modules/home/pages/iot-hub/iot-hub-installed-items.component.ts index 116df9f91f..9f118a4c1e 100644 --- a/ui-ngx/src/app/modules/home/pages/iot-hub/iot-hub-installed-items.component.ts +++ b/ui-ngx/src/app/modules/home/pages/iot-hub/iot-hub-installed-items.component.ts @@ -35,7 +35,7 @@ export class TbIotHubInstalledItemsComponent implements OnInit, OnDestroy { typeFilters: string[] = []; activeTypeFilters = new Set(); - allItemTypes: string[] = ['WIDGET', 'DASHBOARD', 'SOLUTION_TEMPLATE', 'CALCULATED_FIELD', 'RULE_CHAIN', 'DEVICE']; + allItemTypes: string[] = ['DEVICE', 'SOLUTION_TEMPLATE', 'WIDGET', 'CALCULATED_FIELD', 'ALARM_RULE', 'RULE_CHAIN']; @ViewChild(TbIotHubInstalledItemsTableComponent) tableComponent: TbIotHubInstalledItemsTableComponent; @@ -97,6 +97,8 @@ export class TbIotHubInstalledItemsComponent implements OnInit, OnDestroy { clearAllFilters(): void { this.activeTypeFilters.clear(); this.typeFilters = []; + this.textSearch = ''; + this.appliedTextSearch = ''; } hasActiveFilters(): boolean { diff --git a/ui-ngx/src/app/modules/home/pages/iot-hub/iot-hub-items-page.component.ts b/ui-ngx/src/app/modules/home/pages/iot-hub/iot-hub-items-page.component.ts index 6be857519e..28209b9b7d 100644 --- a/ui-ngx/src/app/modules/home/pages/iot-hub/iot-hub-items-page.component.ts +++ b/ui-ngx/src/app/modules/home/pages/iot-hub/iot-hub-items-page.component.ts @@ -67,7 +67,7 @@ const PAGE_CONFIGS: Record = { type: ItemType.ALARM_RULE, titleKey: 'item.type-alarm-rule-plural', descriptionKey: 'iot-hub.items-page-desc-alarm-rules', - image: 'assets/iot-hub/items-page-dashboards-hero.svg', + image: 'assets/iot-hub/items-page-alarm-rules-hero.svg', routeSegment: 'alarm-rules' }, RULE_CHAIN: { diff --git a/ui-ngx/src/app/modules/home/pages/iot-hub/iot-hub-routing.module.ts b/ui-ngx/src/app/modules/home/pages/iot-hub/iot-hub-routing.module.ts index 9fd8cd7d3d..4a6cf80c52 100644 --- a/ui-ngx/src/app/modules/home/pages/iot-hub/iot-hub-routing.module.ts +++ b/ui-ngx/src/app/modules/home/pages/iot-hub/iot-hub-routing.module.ts @@ -32,7 +32,7 @@ const routes: Routes = [ auth: [Authority.TENANT_ADMIN], breadcrumb: { label: 'iot-hub.iot-hub', - icon: 'store' + icon: 'hub' } }, children: [ diff --git a/ui-ngx/src/app/shared/components/toggle-header.component.html b/ui-ngx/src/app/shared/components/toggle-header.component.html index bddaa896b6..c71e226dce 100644 --- a/ui-ngx/src/app/shared/components/toggle-header.component.html +++ b/ui-ngx/src/app/shared/components/toggle-header.component.html @@ -42,14 +42,18 @@ [(ngModel)]="value" (ngModelChange)="valueChange.emit(value)"> - {{ option.name }} - - warning - + @if (option.template) { + + } @else { + {{ option.name }} + + warning + + }
diff --git a/ui-ngx/src/app/shared/components/toggle-header.component.ts b/ui-ngx/src/app/shared/components/toggle-header.component.ts index c60faf810a..53b000d429 100644 --- a/ui-ngx/src/app/shared/components/toggle-header.component.ts +++ b/ui-ngx/src/app/shared/components/toggle-header.component.ts @@ -33,7 +33,7 @@ import { OnInit, Output, QueryList, - SimpleChanges, + SimpleChanges, TemplateRef, ViewChild } from '@angular/core'; import { PageComponent } from '@shared/components/page.component'; @@ -50,6 +50,7 @@ import { MatButtonToggle, MatButtonToggleGroup } from '@angular/material/button- export interface ToggleHeaderOption { name: string; value: any; + template?: TemplateRef; error$?: Observable; } @@ -69,6 +70,8 @@ export class ToggleOption implements OnChanges, OnDestroy { @Input() value: any; + @Input() template: TemplateRef; + @Input() error: string; currentError = new ReplaySubject(1); @@ -127,6 +130,7 @@ export abstract class _ToggleBase extends PageComponent implements AfterContentI { name: option.viewValue, value: option.value, + template: option.template, error$: option.currentError.asObservable() } ); diff --git a/ui-ngx/src/assets/iot-hub/category-alarm-rules-img.png b/ui-ngx/src/assets/iot-hub/category-alarm-rules-img.png new file mode 100644 index 0000000000..ab374fadef Binary files /dev/null and b/ui-ngx/src/assets/iot-hub/category-alarm-rules-img.png differ diff --git a/ui-ngx/src/assets/iot-hub/category-calculated-fields-img.png b/ui-ngx/src/assets/iot-hub/category-calculated-fields-img.png new file mode 100644 index 0000000000..acdcd322e8 Binary files /dev/null and b/ui-ngx/src/assets/iot-hub/category-calculated-fields-img.png differ diff --git a/ui-ngx/src/assets/iot-hub/category-calculated-fields-img.svg b/ui-ngx/src/assets/iot-hub/category-calculated-fields-img.svg deleted file mode 100644 index e74a12f489..0000000000 --- a/ui-ngx/src/assets/iot-hub/category-calculated-fields-img.svg +++ /dev/null @@ -1,233 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ui-ngx/src/assets/iot-hub/category-dashboards-img.svg b/ui-ngx/src/assets/iot-hub/category-dashboards-img.svg deleted file mode 100644 index 2db1d0fafa..0000000000 --- a/ui-ngx/src/assets/iot-hub/category-dashboards-img.svg +++ /dev/null @@ -1,84 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ui-ngx/src/assets/iot-hub/category-device-library-img.png b/ui-ngx/src/assets/iot-hub/category-device-library-img.png new file mode 100644 index 0000000000..9e7817b70a Binary files /dev/null and b/ui-ngx/src/assets/iot-hub/category-device-library-img.png differ diff --git a/ui-ngx/src/assets/iot-hub/category-device-library-img.svg b/ui-ngx/src/assets/iot-hub/category-device-library-img.svg deleted file mode 100644 index 57b90cde55..0000000000 --- a/ui-ngx/src/assets/iot-hub/category-device-library-img.svg +++ /dev/null @@ -1,95 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ui-ngx/src/assets/iot-hub/category-rule-chains-img.png b/ui-ngx/src/assets/iot-hub/category-rule-chains-img.png new file mode 100644 index 0000000000..bd136772b3 Binary files /dev/null and b/ui-ngx/src/assets/iot-hub/category-rule-chains-img.png differ diff --git a/ui-ngx/src/assets/iot-hub/category-rule-chains-img.svg b/ui-ngx/src/assets/iot-hub/category-rule-chains-img.svg deleted file mode 100644 index 09bd6882da..0000000000 --- a/ui-ngx/src/assets/iot-hub/category-rule-chains-img.svg +++ /dev/null @@ -1,107 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ui-ngx/src/assets/iot-hub/category-solution-templates-img.png b/ui-ngx/src/assets/iot-hub/category-solution-templates-img.png index efcd683abd..3c649f92ef 100644 Binary files a/ui-ngx/src/assets/iot-hub/category-solution-templates-img.png and b/ui-ngx/src/assets/iot-hub/category-solution-templates-img.png differ diff --git a/ui-ngx/src/assets/iot-hub/category-widgets-img.png b/ui-ngx/src/assets/iot-hub/category-widgets-img.png new file mode 100644 index 0000000000..0808b123cc Binary files /dev/null and b/ui-ngx/src/assets/iot-hub/category-widgets-img.png differ diff --git a/ui-ngx/src/assets/iot-hub/category-widgets-img.svg b/ui-ngx/src/assets/iot-hub/category-widgets-img.svg deleted file mode 100644 index 607a9c4911..0000000000 --- a/ui-ngx/src/assets/iot-hub/category-widgets-img.svg +++ /dev/null @@ -1,181 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ui-ngx/src/assets/iot-hub/hero-alarm-rule-cluster.svg b/ui-ngx/src/assets/iot-hub/hero-alarm-rule-cluster.svg new file mode 100644 index 0000000000..545e7db89b --- /dev/null +++ b/ui-ngx/src/assets/iot-hub/hero-alarm-rule-cluster.svg @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ui-ngx/src/assets/iot-hub/hero-calculated-field-cluster.svg b/ui-ngx/src/assets/iot-hub/hero-calculated-field-cluster.svg new file mode 100644 index 0000000000..a5206aa4ea --- /dev/null +++ b/ui-ngx/src/assets/iot-hub/hero-calculated-field-cluster.svg @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ui-ngx/src/assets/iot-hub/hero-calculated-field-icon-1.svg b/ui-ngx/src/assets/iot-hub/hero-calculated-field-icon-1.svg deleted file mode 100644 index 7734b75c7a..0000000000 --- a/ui-ngx/src/assets/iot-hub/hero-calculated-field-icon-1.svg +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ui-ngx/src/assets/iot-hub/hero-calculated-field-icon-2.svg b/ui-ngx/src/assets/iot-hub/hero-calculated-field-icon-2.svg deleted file mode 100644 index ac28694c40..0000000000 --- a/ui-ngx/src/assets/iot-hub/hero-calculated-field-icon-2.svg +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ui-ngx/src/assets/iot-hub/hero-calculated-field-icon-3.svg b/ui-ngx/src/assets/iot-hub/hero-calculated-field-icon-3.svg deleted file mode 100644 index 860997b4a5..0000000000 --- a/ui-ngx/src/assets/iot-hub/hero-calculated-field-icon-3.svg +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ui-ngx/src/assets/iot-hub/hero-calculated-field-icon-4.svg b/ui-ngx/src/assets/iot-hub/hero-calculated-field-icon-4.svg deleted file mode 100644 index 356d5dece0..0000000000 --- a/ui-ngx/src/assets/iot-hub/hero-calculated-field-icon-4.svg +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ui-ngx/src/assets/iot-hub/hero-dashboard-icon-1.svg b/ui-ngx/src/assets/iot-hub/hero-dashboard-icon-1.svg deleted file mode 100644 index 85f1a39345..0000000000 --- a/ui-ngx/src/assets/iot-hub/hero-dashboard-icon-1.svg +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ui-ngx/src/assets/iot-hub/hero-dashboard-icon-2.svg b/ui-ngx/src/assets/iot-hub/hero-dashboard-icon-2.svg deleted file mode 100644 index ff17afc8fb..0000000000 --- a/ui-ngx/src/assets/iot-hub/hero-dashboard-icon-2.svg +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ui-ngx/src/assets/iot-hub/hero-dashboard-icon-3.svg b/ui-ngx/src/assets/iot-hub/hero-dashboard-icon-3.svg deleted file mode 100644 index 36ec0aca84..0000000000 --- a/ui-ngx/src/assets/iot-hub/hero-dashboard-icon-3.svg +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ui-ngx/src/assets/iot-hub/hero-dashboard-icon-4.svg b/ui-ngx/src/assets/iot-hub/hero-dashboard-icon-4.svg deleted file mode 100644 index 547826eeb1..0000000000 --- a/ui-ngx/src/assets/iot-hub/hero-dashboard-icon-4.svg +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ui-ngx/src/assets/iot-hub/hero-device-cluster.svg b/ui-ngx/src/assets/iot-hub/hero-device-cluster.svg new file mode 100644 index 0000000000..7e75c744a7 --- /dev/null +++ b/ui-ngx/src/assets/iot-hub/hero-device-cluster.svg @@ -0,0 +1,138 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ui-ngx/src/assets/iot-hub/hero-device-icon-1.svg b/ui-ngx/src/assets/iot-hub/hero-device-icon-1.svg deleted file mode 100644 index 8ef1b628a4..0000000000 --- a/ui-ngx/src/assets/iot-hub/hero-device-icon-1.svg +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ui-ngx/src/assets/iot-hub/hero-device-icon-2.svg b/ui-ngx/src/assets/iot-hub/hero-device-icon-2.svg deleted file mode 100644 index 57e615a72d..0000000000 --- a/ui-ngx/src/assets/iot-hub/hero-device-icon-2.svg +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ui-ngx/src/assets/iot-hub/hero-device-icon-3.svg b/ui-ngx/src/assets/iot-hub/hero-device-icon-3.svg deleted file mode 100644 index 1e7f844ba7..0000000000 --- a/ui-ngx/src/assets/iot-hub/hero-device-icon-3.svg +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ui-ngx/src/assets/iot-hub/hero-device-icon-4.svg b/ui-ngx/src/assets/iot-hub/hero-device-icon-4.svg deleted file mode 100644 index 164db57b9a..0000000000 --- a/ui-ngx/src/assets/iot-hub/hero-device-icon-4.svg +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ui-ngx/src/assets/iot-hub/hero-rule-chain-cluster.svg b/ui-ngx/src/assets/iot-hub/hero-rule-chain-cluster.svg new file mode 100644 index 0000000000..ee3a4d39de --- /dev/null +++ b/ui-ngx/src/assets/iot-hub/hero-rule-chain-cluster.svg @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ui-ngx/src/assets/iot-hub/hero-rule-chain-icon-1.svg b/ui-ngx/src/assets/iot-hub/hero-rule-chain-icon-1.svg deleted file mode 100644 index 53a6019a4d..0000000000 --- a/ui-ngx/src/assets/iot-hub/hero-rule-chain-icon-1.svg +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ui-ngx/src/assets/iot-hub/hero-rule-chain-icon-2.svg b/ui-ngx/src/assets/iot-hub/hero-rule-chain-icon-2.svg deleted file mode 100644 index 917f875faa..0000000000 --- a/ui-ngx/src/assets/iot-hub/hero-rule-chain-icon-2.svg +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ui-ngx/src/assets/iot-hub/hero-rule-chain-icon-3.svg b/ui-ngx/src/assets/iot-hub/hero-rule-chain-icon-3.svg deleted file mode 100644 index c5ecbe9b74..0000000000 --- a/ui-ngx/src/assets/iot-hub/hero-rule-chain-icon-3.svg +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ui-ngx/src/assets/iot-hub/hero-rule-chain-icon-4.svg b/ui-ngx/src/assets/iot-hub/hero-rule-chain-icon-4.svg deleted file mode 100644 index eda7544128..0000000000 --- a/ui-ngx/src/assets/iot-hub/hero-rule-chain-icon-4.svg +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ui-ngx/src/assets/iot-hub/hero-solution-template-cluster.svg b/ui-ngx/src/assets/iot-hub/hero-solution-template-cluster.svg new file mode 100644 index 0000000000..2afd1f2ab8 --- /dev/null +++ b/ui-ngx/src/assets/iot-hub/hero-solution-template-cluster.svg @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ui-ngx/src/assets/iot-hub/hero-solution-template-icon-1.svg b/ui-ngx/src/assets/iot-hub/hero-solution-template-icon-1.svg deleted file mode 100644 index f1d0ee4799..0000000000 --- a/ui-ngx/src/assets/iot-hub/hero-solution-template-icon-1.svg +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ui-ngx/src/assets/iot-hub/hero-solution-template-icon-2.svg b/ui-ngx/src/assets/iot-hub/hero-solution-template-icon-2.svg deleted file mode 100644 index 9708abc935..0000000000 --- a/ui-ngx/src/assets/iot-hub/hero-solution-template-icon-2.svg +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ui-ngx/src/assets/iot-hub/hero-solution-template-icon-3.svg b/ui-ngx/src/assets/iot-hub/hero-solution-template-icon-3.svg deleted file mode 100644 index 7151c40b16..0000000000 --- a/ui-ngx/src/assets/iot-hub/hero-solution-template-icon-3.svg +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ui-ngx/src/assets/iot-hub/hero-solution-template-icon-4.svg b/ui-ngx/src/assets/iot-hub/hero-solution-template-icon-4.svg deleted file mode 100644 index 11a06c0a4f..0000000000 --- a/ui-ngx/src/assets/iot-hub/hero-solution-template-icon-4.svg +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ui-ngx/src/assets/iot-hub/hero-widget-cluster.svg b/ui-ngx/src/assets/iot-hub/hero-widget-cluster.svg new file mode 100644 index 0000000000..0df6ad4336 --- /dev/null +++ b/ui-ngx/src/assets/iot-hub/hero-widget-cluster.svg @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ui-ngx/src/assets/iot-hub/hero-widget-icon-1.svg b/ui-ngx/src/assets/iot-hub/hero-widget-icon-1.svg deleted file mode 100644 index 7058c55569..0000000000 --- a/ui-ngx/src/assets/iot-hub/hero-widget-icon-1.svg +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ui-ngx/src/assets/iot-hub/hero-widget-icon-2.svg b/ui-ngx/src/assets/iot-hub/hero-widget-icon-2.svg deleted file mode 100644 index 905ae06615..0000000000 --- a/ui-ngx/src/assets/iot-hub/hero-widget-icon-2.svg +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ui-ngx/src/assets/iot-hub/hero-widget-icon-3.svg b/ui-ngx/src/assets/iot-hub/hero-widget-icon-3.svg deleted file mode 100644 index 129999a1a7..0000000000 --- a/ui-ngx/src/assets/iot-hub/hero-widget-icon-3.svg +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ui-ngx/src/assets/iot-hub/hero-widget-icon-4.svg b/ui-ngx/src/assets/iot-hub/hero-widget-icon-4.svg deleted file mode 100644 index 4483d53642..0000000000 --- a/ui-ngx/src/assets/iot-hub/hero-widget-icon-4.svg +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ui-ngx/src/assets/iot-hub/items-page-alarm-rules-hero.svg b/ui-ngx/src/assets/iot-hub/items-page-alarm-rules-hero.svg new file mode 100644 index 0000000000..74ba7569b4 --- /dev/null +++ b/ui-ngx/src/assets/iot-hub/items-page-alarm-rules-hero.svg @@ -0,0 +1,150 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ui-ngx/src/assets/iot-hub/items-page-calculated-fields-hero.svg b/ui-ngx/src/assets/iot-hub/items-page-calculated-fields-hero.svg index fa88380d61..916c521ea0 100644 --- a/ui-ngx/src/assets/iot-hub/items-page-calculated-fields-hero.svg +++ b/ui-ngx/src/assets/iot-hub/items-page-calculated-fields-hero.svg @@ -1,103 +1,103 @@ - - + + - - - + + + - - + + - - - + + + - - - - - - - + + + + + + + - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + - - - + + + - - - + + + - + - + - + - + - + - + - - + + - + - - + + - - + + - - + + - + - + diff --git a/ui-ngx/src/assets/iot-hub/items-page-devices-hero.svg b/ui-ngx/src/assets/iot-hub/items-page-devices-hero.svg index cbe42a4707..d951dd8744 100644 --- a/ui-ngx/src/assets/iot-hub/items-page-devices-hero.svg +++ b/ui-ngx/src/assets/iot-hub/items-page-devices-hero.svg @@ -1,258 +1,243 @@ - - - - + + + + - - + + - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + - - - - + - - - - - - - - + + + + + + + + + + + + + - - - - - - - - - + + + + + + + + - - - + + + - - + + - - + + - - + + - - + + - - + + - + - - + + - - + + - - + + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + - - + + - - + + - - + + - - + + - - + + - + - - + + - - - - - - - - + + + + + + + + - - + + - - + + - - + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + - + - + - + - - + + - - - - - - - + - + - - - - - + + - - diff --git a/ui-ngx/src/assets/locale/locale.constant-en_US.json b/ui-ngx/src/assets/locale/locale.constant-en_US.json index 5820da1213..7fc3eca27b 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -4198,6 +4198,7 @@ "and-devices": "& Devices", "search-placeholder": "Search in IoT Hub...", "search": "Search...", + "search-published-items": "Search published items...", "see-all-results": "See all results", "no-search-results": "No results found for '{{ search }}'", "no-items-available": "No items available", @@ -4229,13 +4230,7 @@ "items-page-desc-rule-chains": "From sophisticated data processing to seamless API integrations, Rule Chain templates provide the architectural foundation you need to scale without building from scratch.", "items-page-desc-devices": "Explore the device library to find pre-configured connectivity templates you can deploy in minutes to connect your hardware instantly.", "device-library": "Device Library", - "popular-widgets": "Popular Widgets", - "popular-dashboards": "Popular Dashboards", - "popular-solution-templates": "Popular Solution Templates", - "popular-calculated-fields": "Popular Calculated Fields", - "popular-alarm-rules": "Popular Alarm Rules", - "popular-rule-chains": "Popular Rule Chains", - "popular-devices": "Popular Devices", + "most-popular-in-iot-hub": "Most popular in IoT Hub", "become-creator-text": "Submit your templates to the ThingsBoard IoT Hub to get featured and showcase your solutions to our global community.", "contribute": "Contribute", "creator-profile": "Creator Profile", @@ -4253,7 +4248,6 @@ "subtitle-alarm-rules": "Browse alarm rule templates", "subtitle-rule-chains": "Browse rule chain templates", "subtitle-devices": "Browse device configurations", - "search-widgets": "Search widgets...", "search-dashboards": "Search dashboards...", "search-solution-templates": "Search solution templates...", "search-calculated-fields": "Search calculated fields...", @@ -4263,7 +4257,6 @@ "sort-most-installed": "Most installed", "sort-newest": "Newest", "sort-name": "Name (A-Z)", - "type": "Type", "type-filter-label": "Type", "category": "Category", "use-case": "Use case", @@ -4349,6 +4342,7 @@ "item-version": "Version", "installed-date": "Installed", "no-installed-items": "No installed items found", + "no-installed-items-text": "Try adjusting your search or filters.", "remove-installed-item-title": "Remove Installed Item", "remove-installed-item-text": "Are you sure you want to remove '{{name}}'? The installed entity will also be removed.", "installed-item-removed": "'{{name}}' has been removed",