- Add itemTypeIcons + getItemTypeIcon helper to
iot-hub-item.models, mirroring mp-item.models in the iot-hub
project: widgets / dashboard / apps / mdi:function-variant /
settings_ethernet / mdi:bell-cog / devices_other with `category`
as the fallback.
- Replace every hand-rolled item-type → icon switch with calls to
getItemTypeIcon: item detail dialog (getTypeIcon / getCompactIcon
fallback path), installed-items table (getItemTypeIcon),
iot-hub-home (getCompactIcon / getItemTypeIcon), item-card
(getPlaceholderIcon default + per-type fallbacks), item-link-card
(getCompactIcon / getTypeIcon).
- Swap the remaining mat-icon placeholders that render an item-type
icon to tb-icon (installed-items table chip, home search popup
thumb placeholder, item-link-card thumb fallback). Generic
status / action icons stay on mat-icon.
- Refresh the colored item-type chip palette in the installed
items table to match itemTypeChipColors from mp-item.models, and
add the previously-missing tb-type-alarm-rule rule so that chip
picks up the new orange palette instead of falling through to no
background.
Treat DEVICE, CALCULATED_FIELD, ALARM_RULE, and RULE_CHAIN as
count-based item types in maybeOpenDeepLinkedItem: all four resolve
via getInstalledItemCounts(this.config.type) and pass only { count }
to openItemDetail. Singular-entity types (widgets, dashboards,
solution templates) still go through resolveInstalledItem and pass
{ installed }.
Collapse maybeOpenDeepLinkedItem into a single openItemDetail call.
Devices resolve via getInstalledItemCounts and pass only the
{ count } for the deep-linked itemId; every other type resolves via
resolveInstalledItem and passes only the matching { installed }
entity (no more synthetic 0/1 count for non-device types).
Bring the same fetch-failure UI to every IoT Hub surface (browse,
search, home, creator profile) so all of them recover gracefully
from network / server outages instead of dead-ending on a global
error toast or a hard redirect.
- Add a tb-no-service-bg global utility in form.scss that mirrors
tb-no-data-bg but renders /assets/home/no-service.svg (copied
from thingsboard.io). Same primary-color mask treatment, so PE
builds retint without re-exporting the asset.
- Add hasError / retryTimer state to the four affected components
and switch their data calls to ignoreErrors: true so the global
toast no longer fires. hasError flips to true on error, stays
true while retries are pending, and is only cleared in the
`next` callback of the next request that actually succeeds.
- Add retryLoad* helpers (retryLoadItems / retryLoadResults /
retryLoadPopularItems / retryLoadCreator) that set isLoading=true
immediately and schedule the real load via a 350ms setTimeout so
rapid-fire retry clicks coalesce into one network round-trip.
- Search component drops the inline switchMap-on-searchSubject path
and pipes the debounced subject straight into loadResults() so
search-triggered loads go through the same error / spinner /
retry plumbing.
- Render the error block consistently across surfaces: in browse
and search inside their respective results container, on the
home page right after the category cards, on the creator profile
as the whole page body (replacing the old router.navigate to
/iot-hub). Each block uses .tb-no-service-bg + the new
iot-hub.network-server-unavailable / -text / try-again locale
keys and binds the primary button to the matching retryLoad*
method.
- Add the matching .tb-iot-hub-empty-state typography (18/500
title, 14/0.54 body, 24px button gap) to the home and creator
profile SCSS so the wrapper matches the layout already used in
browse / search.
Also pick up an unrelated dashboard-widget-select adjustment touched
in the same workspace.
- Drop the DEVICE-only `tb-iot-hub-card-preview-device` /
`dlg-preview-device` variants in the item card and item detail
dialog. The previously-special white-background-with-border treatment
is gone — device previews now reuse the same dot-pattern background
as widgets / solution templates for a consistent look.
- In the home-page iot-hub widget, fold the
`tb-iot-hub-widget-card-image-pattern` modifier into the base
`.tb-iot-hub-widget-card-image` so every preview card already paints
the dot pattern (no opt-in class required).
- Rename `.tb-search-categories` to `.tb-results-container` across
the iot-hub-search component / search page / creator profile pages
so the wrapper class better reflects what it actually contains
(browse / search results) and stays consistent between the search
component and the screens that embed it.
- Pick up incidental browse / search component html / scss tweaks
touched alongside the rename.
- Provide a scoped Angular ErrorHandler on the dynamic component's
injector in HtmlContainerWidgetComponent so template-runtime
exceptions raised inside user-authored Angular templates flow
through handleWidgetException instead of crashing the global
Angular ErrorHandler.
- Add `ctx.invokeAction($event, actionName, additionalParams?)` to
WidgetActionsApi / WidgetComponent and a `WidgetDestroyCallback` +
ctx.registerDestroyCallback() API on WidgetContext (callbacks run
in registration order on destroy, errors per-callback are caught
so one bad cleanup doesn't break the rest).
- Surface widget actions on the HTML Container basic config: render
tb-widget-actions-panel with the new strokedPanel input below
the html-container settings, and register a default "JavaScript"
multi-action source on the html_container widget JSON.
- Expand the widget-completion docs for `registerDestroyCallback`
(when it fires, what to use it for, lifecycle semantics, exact
callback signature `() => void`) and for `invokeAction`'s
`additionalParams` arg (forwarded to the configured JS action
handler, common payload examples).
Netty 4.1.133.Final introduced a regression in MqttDecoder while fixing
CVE-2026-44248: when multiple MQTT packets are present in the same
cumulation buffer, the per-message size check used the total buffer size
instead of the current packet's declared remaining length. Valid in-limit
packets get rejected with TooLongFrameException("message length exceeds
65536: <small number>"). Fixed upstream by netty/netty#16787 and ported
to 4.1 as netty/netty@30f8f284db, released in 4.1.134.Final.
- Add a public listing item-version endpoint to IotHubApiService
(GET /api/listings/public/by-slug/{slug}/item-version?ce=true&
tbVersion=N) returning MpItemVersionView, with the new
ListingItemVersionNotFound shape capturing the documented 404
bodies (noMatchingVersions / peRequired / minTbVersionRequired).
- Wire a tbVersionIntToString helper alongside the existing
tbVersionToInt so the dialogs can render the resolved versions
compactly (430 → "4.3", 421 → "4.2.1").
- Route /iot-hub/listing/:slug to TbIotHubItemResolverComponent.
Resolver picks the slug path first, dispatches the 404 bodies to
three handlers: noMatchingVersions reuses the existing
deep-link-not-found notification, peRequired opens a new dialog,
minTbVersionRequired opens another with the resolved min version.
- New TbIotHubPeRequiredDialogComponent renders the "Professional
Edition required" prompt and TbIotHubUpgradeRequiredDialogComponent
renders the "ThingsBoard upgrade required" prompt. Both reuse a
single upgrade-required.svg asset (Figma export) tinted via CSS
mask + background-color so the PE accent inherits without touching
the asset. The shared "Upgrade instance" button links to the right
upgrade doc per dialog.
- New TbIotHubAlarmRulesUnavailablePageComponent replaces
TbIotHubItemsPageComponent on /iot-hub/alarm-rules. It mirrors the
iot-hub-home glow-blob + dot-pattern background (alarm-rule
accent), renders the alarm-rules hero, a 28px title with the
primary "Thingsboard v4.3" span, the description, an Upgrade
instance link (https://thingsboard.io/docs/installation/upgrade-
instructions/), Back to IoT Hub, and the current platform version
read from env.tbVersion.
- Locale: pe-required-title / pe-required-message (bolded "Professional
Edition" / "Community Edition"), upgrade-required-title /
upgrade-required-message (bolded interpolations), and the alarm-
rules-unavailable-* keys for the new page.
Exposes the dashboard entities-limit check as a reusable public method
so callers outside the validator can enforce the same limit without
duplicating the apiLimitService logic.
- Group the slide-toggle and the conditionally rendered profile
pickers in a single bordered card via tb-form-panel.stroked,
matching the 4.3 entity-aggregation 'Apply await timeout' pattern.
- Set the toggle's class to 'mat-slide flex' to match the canonical
TB idiom; switch the tooltip label to plain interpolation.
- Restore the trailing '?' in install-confirm-title — the confirm
step is still a real confirmation question for item types that
don't go through the select-entity flow.
CF and Rule Chain installs now open directly into the selection form,
skipping the prior "Install?" confirmation step. Rule Chain uses a
single "Set as profile default rule chain" toggle that reveals the
profile pickers when enabled, replacing the previous two-button
design. The overwrite-confirmation step is preserved.
Follow-up to #15645.