Replaces the temporary v4.3-upgrade-required rejection with the actual
backend handlers. Alarm rules install as CalculatedField entities with
type=ALARM, mirroring the CALCULATED_FIELD path:
- installAlarmRule parses the alarm-rule JSON, validates type==ALARM,
saves via tbCalculatedFieldService, and returns
AlarmRuleInstalledItemDescriptor with calculatedFieldId + entityId.
- updateAlarmRule re-saves the existing CF with new name, type, and
configuration.
- Delete branch removes the underlying calculated field on installed-item
delete.
- Checksum dispatch unifies CF and ALARM_RULE through a shared
calculateCalculatedFieldChecksum(CalculatedFieldId) helper.
Frontend: drops the v4.3 info-dialog interception in IotHubActionsService
(install now actually runs); restores the select-entity branch for
ALARM_RULE in the install dialog so users can pick a parent device.
Removes the now-unused alarm-rule-install-update-required* locale keys.
Resolves descriptor unwrapping conflicts in iot-hub-installed-items-table
and iot-hub-item-detail-dialog: ALARM_RULE follows the lts-4.3 pattern of
navigating to the calculated-field entity itself (calculatedFieldId +
EntityType.CALCULATED_FIELD), matching CALCULATED_FIELD.
* feat(iot-hub): scaffold ALARM_RULE item type and CREATOR_VISIBLE_ITEM_TYPES
* feat(iot-hub): wire ALARM_RULE through browse, item card, detail dialog, installed items, and install dialog
* feat(iot-hub): reorder home cards, hide Dashboards, add Alarm Rules
* feat(iot-hub): scaffold ALARM_RULE descriptor and reject install with v4.3 upgrade hint
Registers AlarmRuleInstalledItemDescriptor in the Jackson polymorphism so
4.2 can browse Alarm Rule items from the marketplace without descriptor
deserialization failures.
The install handler explicitly rejects ALARM_RULE with a friendly message
asking the user to upgrade to v4.3+. The full install/update/delete
implementation depends on CalculatedFieldType.ALARM (added in v4.3) and
will land once master is merged into this branch.
* feat(iot-hub): hide redundant Type filter on Alarm Rules browse
* feat(iot-hub): show v4.3 update info dialog directly when installing an Alarm Rule
Relocate the iot_hub_installed_item CREATE TABLE statement from the
basic schema_update.sql to the LTS cumulative schema_update.sql, where
it belongs for this LTS line.
Relocate the iot_hub_installed_item CREATE TABLE statement from the
basic schema_update.sql to the LTS cumulative schema_update.sql, where
it belongs for this LTS line.
STRING and PASSWORD fields in SHOW_FORM gain optional randomGenerator,
randomSize, and randomByDefault properties. randomByDefault pre-fills the
field on form open; an autorenew icon (next to the eye toggle on PASSWORD)
regenerates on demand. Reuses generateSecret from @core/utils.
Two new markdown placeholders, ${product.button} and ${datasheet.button},
render as inline buttons linking to the manufacturer's product page and
datasheet. They work in SHOW_INSTRUCTION steps (install dialog) and in
overview.md (detail dialog readme). URLs come from device-info.json's
productURL/datasheetURL — install reads from the parsed package, detail
dialog reads from item.dataDescriptor.
- TbIotHubSelectCfEntityDialogComponent: small reusable dialog mirroring
the install dialog's select-entity state (Title + select-entity-for-cf
description + tb-entity-select over DEVICE/ASSET/DEVICE_PROFILE/
ASSET_PROFILE, default DEVICE_PROFILE).
- TbIotHubAddItemDialogComponent.onAddItem: when itemType ===
CALCULATED_FIELD and no parent entityId is supplied, open the new
dialog and pass the chosen EntityId into installItemVersion.
installItem() extracted as a shared helper.
- Open-installed-CF flow now uses the descriptor's calculatedFieldId +
EntityType.CALCULATED_FIELD (in installed-items-table and detail
dialog), and registers /calculatedFields in baseDetailsPageByEntityType
so the link resolves.
- Introduce HasAppliedToEntity interface used by CreatedAlarmRuleInfo and
CreatedCalculatedFieldInfo to share the entity page-link logic and
cover DEVICE / ASSET in addition to the profile types.
- Add static from(EntityId, name, CalculatedField) factories to both
records; SolutionInstallContext now uses them and detects ALARM
calculated fields via type instead of the previous TODO/hardcoded
false.
- AlarmSeverity and CalculatedFieldType expose display names used when
formatting created-alarm-rule severities and CF type column.
- DefaultSolutionService switches the CF arguments check from
BaseCalculatedFieldConfiguration to ArgumentsBasedCalculatedFieldConfiguration
and throws ThingsboardRuntimeException for missing references.
Re-throw EntitiesLimitExceededException from IoT Hub item install and
solution-template install paths instead of folding it into the generic
install error response, so the PE entity-limit error reaches the global
HTTP error handler.
In the device install wizard switch saveDevice/createDevice (and
overwrite) calls from ignoreErrors:true to false so the limit-exceeded
toast is shown when the backend rejects the create.
The guard around iterating createdEntityIds was checking isEmpty()
instead of !isEmpty(), so entity deletion was skipped whenever there
was actually data to clean up.
SolutionTemplateInstalledItemDescriptor and SolutionInstallResponse now
carry tenantTelemetryKeys and tenantAttributeKeys lists. SolutionService
.deleteSolution takes the full descriptor (instead of just the
created-entity list) so uninstall can also clean up tenant-scoped
telemetry/attributes. Update IotHub install descriptor population and
delete call sites; force-update path logs and continues if delete throws.
Install and update dialogs now render error details via tb-markdown
when the failing item is a SOLUTION_TEMPLATE, falling back to the plain
text block for other item types. Supports the rich instruction-style
error messages returned by the solution install flow.
Propagate User through SolutionInstallContext, DefaultSolutionService,
and TbCalculatedFieldService.delete so non-security-context callers can
drive solution installs and calculated-field cleanup. Pass
TenantSolutionTemplateInstructions into the context constructor so the
caller controls instruction state.
Add optional isNew flag on MenuSection; when set, menu-link and
menu-toggle components render a NEW badge next to the label. Marks
the IoT Hub entry as new.
Add CreatedRuleChainInfo extending CreatedEntityInfo that overrides
getEntityPageLink to produce /edgeManagement/ruleChains/<id> for EDGE
rule chains and /ruleChains/<id> otherwise. SolutionInstallContext now
registers rule chains with this type-aware info.
The IoT Hub backend sends the literal string 'Initial release' as the
changelog payload for every newly-published item. That text tells the
user nothing they don't already see from the v 1.0.0 chip in the meta
bar — just informational noise. Hide the Changelog heading + body when
the trimmed changelog equals 'Initial release'.
Both the inner section guard and the outer container guard use the new
shouldShowChangelog() helper so an item with empty readme + initial
release changelog doesn't leave an empty wrapper.
- Two-column widget showing top-3 solution templates and top-3 devices
fetched by totalInstallCount DESC, with installed-state fetching
(solution templates list + device counts)
- Section titles as .tb-title-link routerLinks to /iot-hub/solution-templates
and /iot-hub/devices
- Item cards open detail dialog via IotHubActionsService; solution template
cards show green check_circle badge in top-right when installed
- HomePageWidgetsModule now imports IotHubComponentsModule to resolve
IotHubActionsService
Device preview styling:
- Switch item card .tb-iot-hub-card-preview to white bg + bottom border
when item.type === DEVICE
- Switch detail dialog .dlg-preview to white bg + full border when DEVICE
Creates missing system images from application/src/main/data/resources/images
during LTS patch startup, mirroring the upgrade-path loadSystemResources logic.
Existing system images in the DB are left untouched.
Reintroduces the canonical item link (/iot-hub/{itemId}) that resolves
to the latest published version. The preview shape (/iot-hub/{itemId}/preview)
stays removed — if a creator wants to preview a specific draft, they
share the /iot-hub/version/{itemVersionId} link with that exact
versionId.
Final URL shapes:
- /iot-hub/{itemId} → latest published version
- /iot-hub/version/{itemVersionId} → specific version, warning if unpublished
Resolver branches on which route param is present — no extra data flag.
Restores getPublishedVersion API method. IoT Hub ask adds back one new
endpoint: GET /api/items/{itemId}/published.
Consolidates to a single deep-link shape: /iot-hub/version/{itemVersionId}.
A specific version snapshot is a more useful sharable link than
"latest of item" — stable, unambiguous, and fits creator review
workflows ("please look at exactly this draft").
Removes /iot-hub/{itemId} and /iot-hub/{itemId}/preview routes, the
getPublishedVersion and getLatestVersion API methods (now unused), the
byVersion and preview route-data flags, and the iot-hub.item-preview
i18n key. Simplifies the resolver to a single getVersionInfo call with
the same warning-if-unpublished gate.
Big win for the IoT Hub backend contract: no new endpoints needed, only
a behavior guarantee on existing /api/versions/{versionId}.
Third URL shape for deep links, pointing at a specific version snapshot
rather than "latest of item". Stable link — useful for creators sharing
"review exactly this draft" references. Routes through the same
resolver component with a new byVersion flag on route data; reuses the
existing getVersionInfo API and the same warning-if-unpublished gate as
the preview flow.
Spec + plan updated to document the new shape and the expanded IoT Hub
backend contract.