From daed8abf909a821c4c40af4fa402a123579d25ae Mon Sep 17 00:00:00 2001 From: Igor Kulikov Date: Fri, 17 Apr 2026 16:42:30 +0300 Subject: [PATCH] feat(iot-hub): add verified creator badge, sticky meta bar in detail dialog Add verified field to CreatorView and creatorVerified to MpItemVersionView. Show verified badge (32px teal icon + tooltip) on creator profile page. Show 16px teal verified icon on item cards when creator is verified. Make dlg-meta-bar always rendered and sticky in item detail dialog. --- .../iot-hub/iot-hub-item-card.component.html | 12 ++++- .../iot-hub/iot-hub-item-card.component.scss | 4 ++ .../iot-hub-item-detail-dialog.component.html | 53 +++++++------------ .../iot-hub-item-detail-dialog.component.scss | 7 +++ .../iot-hub-creator-profile.component.html | 9 +++- .../iot-hub-creator-profile.component.scss | 15 ++++++ .../models/iot-hub/iot-hub-creator.models.ts | 1 + .../models/iot-hub/iot-hub-version.models.ts | 1 + .../assets/locale/locale.constant-en_US.json | 1 + 9 files changed, 66 insertions(+), 37 deletions(-) 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 35c5b3927c..ef20917b8f 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 @@ -28,7 +28,11 @@

{{ item.name }}

@if (showCreator) { - person + @if (item.creatorVerified) { + verified + } @else { + person + } {{ item.creatorDisplayName }} · } @@ -89,7 +93,11 @@

{{ item.name }}

- @if (item.type === ItemType.DEVICE) { - @if (item.dataDescriptor?.hardwareType || item.dataDescriptor?.connectivity?.length || item.useCases?.length) { -
-
+
+
+
+ @if (item.type === ItemType.DEVICE) { @if (item.dataDescriptor?.hardwareType) {
{{ 'iot-hub.hardware-type' | translate }} @@ -273,22 +273,7 @@
} - @if (item.useCases?.length) { -
- {{ 'iot-hub.use-cases' | translate }} -
- @for (uc of item.useCases; track uc) { - {{ uc }} - } -
-
- } -
- } - } @else { - @if (item.categories?.length || item.useCases?.length) { -
-
+ } @else { @if (item.categories?.length) {
{{ 'iot-hub.category' | translate }} @@ -299,33 +284,33 @@
} - @if (item.useCases?.length) { -
- {{ 'iot-hub.use-cases' | translate }} -
- @for (uc of item.useCases; track uc) { - {{ uc }} - } -
+ } + @if (item.useCases?.length) { +
+ {{ 'iot-hub.use-cases' | translate }} +
+ @for (uc of item.useCases; track uc) { + {{ uc }} + }
- } -
- } - } +
+ } +
+
+
@if (item.type === ItemType.RULE_CHAIN && getNodes().length) { -
@for (node of getNodes(); track node.name) { {{ node.name }} }
+
} @if (readmeContent || item.changelog) { -
@if (readmeContent) { diff --git a/ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-item-detail-dialog.component.scss b/ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-item-detail-dialog.component.scss index 44267a02fa..d326f6e7a6 100644 --- a/ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-item-detail-dialog.component.scss +++ b/ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-item-detail-dialog.component.scss @@ -263,6 +263,13 @@ background: rgba(0, 0, 0, 0.12); } +.dlg-meta-bar { + position: sticky; + top: 0; + z-index: 1; + background: white; +} + // Meta section (categories + use cases) — Design: px-24, py-16, gap-24, flex row .dlg-meta { display: flex; diff --git a/ui-ngx/src/app/modules/home/pages/iot-hub/iot-hub-creator-profile.component.html b/ui-ngx/src/app/modules/home/pages/iot-hub/iot-hub-creator-profile.component.html index 88a3e1c22c..cd0c4a8a7d 100644 --- a/ui-ngx/src/app/modules/home/pages/iot-hub/iot-hub-creator-profile.component.html +++ b/ui-ngx/src/app/modules/home/pages/iot-hub/iot-hub-creator-profile.component.html @@ -32,7 +32,14 @@ person }
-

{{ creator.displayName }}

+
+

{{ creator.displayName }}

+ @if (creator.verified) { + verified + } +
@if (creator.description) {

{{ creator.description }}

} diff --git a/ui-ngx/src/app/modules/home/pages/iot-hub/iot-hub-creator-profile.component.scss b/ui-ngx/src/app/modules/home/pages/iot-hub/iot-hub-creator-profile.component.scss index 8c4edca2c8..6ca99b6e24 100644 --- a/ui-ngx/src/app/modules/home/pages/iot-hub/iot-hub-creator-profile.component.scss +++ b/ui-ngx/src/app/modules/home/pages/iot-hub/iot-hub-creator-profile.component.scss @@ -79,6 +79,12 @@ } // Name +.tb-creator-name-row { + display: flex; + align-items: center; + gap: 8px; +} + .tb-creator-name { font-size: 28px; font-weight: 500; @@ -88,6 +94,15 @@ margin: 0; } +.tb-creator-verified-badge { + font-size: 32px; + width: 32px; + height: 32px; + color: #00695c; + flex-shrink: 0; + cursor: default; +} + // Description .tb-creator-desc { font-size: 16px; diff --git a/ui-ngx/src/app/shared/models/iot-hub/iot-hub-creator.models.ts b/ui-ngx/src/app/shared/models/iot-hub/iot-hub-creator.models.ts index 16c6a2c409..0f9c791f3d 100644 --- a/ui-ngx/src/app/shared/models/iot-hub/iot-hub-creator.models.ts +++ b/ui-ngx/src/app/shared/models/iot-hub/iot-hub-creator.models.ts @@ -26,4 +26,5 @@ export interface CreatorView { linkedinUrl: string; twitterUrl: string; publishedCount: number; + verified: boolean; } diff --git a/ui-ngx/src/app/shared/models/iot-hub/iot-hub-version.models.ts b/ui-ngx/src/app/shared/models/iot-hub/iot-hub-version.models.ts index d87cb41599..3edb1b5e46 100644 --- a/ui-ngx/src/app/shared/models/iot-hub/iot-hub-version.models.ts +++ b/ui-ngx/src/app/shared/models/iot-hub/iot-hub-version.models.ts @@ -106,6 +106,7 @@ export interface MpItemVersionView { creatorContactEmail: string; creatorDescription: string; creatorAvatarUrl: string; + creatorVerified: boolean; installCount: number; totalInstallCount: number; resources: MpItemVersionResource[]; 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 f683d7cac8..0d91179da1 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -3774,6 +3774,7 @@ "no-items-found-text": "Try adjusting your search or filters.", "become-a-creator": "Become a creator", "back-to-iot-hub": "Back to IoT Hub", + "verified-creator": "Verified Creator", "published-items": "Published items", "by-creator": "by {{name}}", "installs": "installs",