Store install state (form values, entity outputs, selected connectivity)
in DeviceInstalledItemDescriptor during registration. Installed Items
info icon for DEVICE type re-fetches the ZIP and opens the wizard in
read-only review mode:
- All stepper steps clickable (jump to any step)
- Form fields populated with stored values and disabled
- Entity progress shows all items as completed
- Markdown instructions rendered with resolved variables
- Download buttons and image galleries still work
- Single "Close" button in footer
Backend: add selectedConnectivity and installState fields to descriptor
Test: verify installState deserialization round-trip
* Add device-package.models.ts with install wizard types
Defines ConnectivityType, InstallStepType, ENTITY_STEP_TYPES,
stepTypeAliasMap, DevicePackageInfo, DeviceInstallStep, form field
interfaces, and EntityStepProgress types for the device install wizard.
* Add device install wizard dialog component for IoT Hub
Multi-step dialog that provisions TB entities from a device package ZIP:
- Connectivity type selector, instruction/markdown views, dynamic forms
- Entity creation with progress tracking (device profile, device, dashboard, rule chain)
- Variable resolution across steps (form values, entity outputs, positional refs)
* fix(iot-hub): fix device install dialog template and translations
- Use correct tb-markdown inputs ([data] and [usePlainMarkdown])
- Fix translation key format (hyphens, not dots)
- Remove unused ConnectivityType import and resolveImageUrl method
- Auto-advance to first step when single connectivity type
- Use inline data URIs for helpImage directly
* feat(iot-hub): wire device install dialog into all install entry points
Branch DEVICE item type to fetch ZIP and open TbDeviceInstallDialogComponent
instead of the simple install dialog. Applied to:
- Item detail dialog (install button)
- Browse component (card install button)
- Home component (card install button)
* fix(iot-hub): fix build errors in device install dialog
- Fix tb-markdown input: [markdownText] → [data] in done view
- Fix JSZip entry type annotation for strict TS compilation
* fix(iot-hub): reuse existing device profiles and add missing retry translation
- Find device profile by name before creating; reuse if exists
- Add action.retry translation key (was showing raw key)
* feat(iot-hub): add find-or-create for rule chains in device install
Reuse existing rule chains by name (same pattern as device profiles).
Shared entities (device profile, rule chain) are looked up before creation.
Per-install entities (device, dashboard) are always created fresh.
* feat(iot-hub): refactor device install dialog to use mat-stepper
- Replace single-panel view switching with mat-horizontal-stepper
- Group consecutive entity steps into a single "Provisioning" stepper step
- Each SHOW_INSTRUCTION and SHOW_FORM is its own stepper step
- Add 2s minimum display time per entity creation step
- Connectivity selector shown before stepper (not a stepper step)
- Progress step auto-advances to next step after completion
- Stepper shows completed checkmarks for finished steps
* fix(iot-hub): fix stepper navigation by tracking step completion
Linear mat-stepper requires steps to be marked completed before
advancing. Added completed flag to WizardStep, set it when user
clicks Next or when entity steps finish.
* feat(iot-hub): add device package install tracking with entity cleanup
Backend:
- Expand DeviceInstalledItemDescriptor with createdEntityIds and dashboardId
- Add POST /api/iot-hub/device/register endpoint to save installed item
- Implement reverse-order entity deletion for DEVICE uninstall
- Update DEVICE case in updateItemVersion to clean old entities
Frontend:
- Expand DeviceInstalledItemDescriptor TS model
- Add registerDeviceInstall API method
- Wire wizard to collect entity IDs and register after completion
- Enable dashboard navigation for installed device packages
* fix(iot-hub): add type discriminator to device register request body
Jackson requires the 'type' field for @JsonTypeInfo polymorphic
deserialization of DeviceInstalledItemDescriptor.
* feat(iot-hub): show entity type in provisioning progress rows
Each progress row now displays "Device Profile — ESP32 Dev Kit" instead
of just "ESP32 Dev Kit", making it clear what type of entity is being
provisioned.
* fix(iot-hub): suppress global error toast and add Back button on provisioning error
- Add ignoreErrors: true to all entity creation API calls so errors
are only shown in the dialog, not as global toast notifications
- Add Back button on provisioning error to navigate back to the last
form step, allowing users to fix parameters (e.g. device name)
- Make form steps editable so stepper allows backward navigation
- Reset progress step state when going back so it re-runs with
updated form values
* fix(iot-hub): resolve ExpressionChangedAfterItHasBeenCheckedError in device install dialog
Inject ChangeDetectorRef and call detectChanges() after async state
mutations (entity step status changes, stepper auto-advance, ngOnInit
completion). The NG0100 error occurred because async operations
(setTimeout, HTTP calls) mutated component state outside Angular's
change detection cycle.
* fix(iot-hub): fix device register endpoint JSON deserialization
Accept JsonNode and use JacksonUtil.treeToValue() instead of direct
@RequestBody DeviceInstalledItemDescriptor. The @JsonTypeInfo on the
parent interface caused Spring's message converter to fail when
deserializing the concrete class directly.
* fix(iot-hub): fix dashboardId serialization in device register request
DashboardId implements EntityId which uses EntityIdDeserializer requiring
both entityType and id fields. Frontend was sending {"id":"..."} without
entityType, causing "Missing entityType or id!" 400 error.
Fix: include entityType: "DASHBOARD" in the dashboardId payload.
Add deserialization unit test to verify the exact frontend payload format.
- Add SolutionService with install/delete/rollback flow, entity provisioning
(customers, assets, devices, dashboards, edges, rule chains, CFs, users),
telemetry emulators, instructions templating, and public customer support
- Add SolutionInstallDialogComponent in home/components/solution with markdown
details display and "Go to main dashboard" navigation
- Update IoT Hub install dialog to open solution dialog on template success
- Add SOLUTION_TEMPLATE type support across frontend (item cards, detail dialog,
installed items table with dashboard entity mapping)
- Add solution instructions button to item detail dialog for installed templates
- Update edge detail URLs and dashboard links for correct CE routing
- Refactor update/delete endpoints to use installed item's own ID instead of marketplace itemId
- Add SHA-256 checksum comparison to detect local entity modifications before update
- Support force update to skip checksum check when user confirms overwrite
- Add per-type update methods (widget, dashboard, calculated field, rule chain)
- Add entityId field to CalculatedFieldInstalledItemDescriptor
- Replace checkForUpdates with getItemsPublishedVersions API
- Replace getInstalledItemInfos with getInstalledItemIds returning List<UUID>
- Remove unused IotHubInstalledItemInfo class and resolver
- Set metadata version from saved rule chain in install/update flows
- Add entity-modified confirmation dialog in update UI
- Full entity stack: IotHubInstalledItem with ID, descriptors, JPA entity, DAO (extends JpaAbstractDao), service
- Controller endpoints: install, list (paginated), list infos, get by itemId, delete
- Install flow saves descriptor with entity IDs, delete cascades to installed entities
- Frontend installed items page with search, pagination, type chips, action buttons
- Browse page shows "Installed" label on cards, detail dialog shows "Open details" for installed items
- Installed item infos fetched on browse page init to track installation state
In Jackson 2.18.x, EXISTING_PROPERTY type info combined with the no-arg
@JsonIgnoreProperties causes the triggerType discriminator field to be
silently excluded from the serialized JSON. When the server then tries to
deserialize the POST body for /api/notification/rule, Jackson cannot find
triggerType and throws "missing type id property 'triggerType'", resulting
in a 500 for NotificationEdgeTest.testNotificationRule.
Fix by:
1. Adding @JsonProperty("triggerType") to force the field into normal bean
serialization, overriding any suppression by the type info machinery.
2. Replacing the no-arg @JsonIgnoreProperties with @JsonIgnoreProperties(
ignoreUnknown = true) so unknown properties are ignored rather than
causing errors (e.g. for forward compatibility).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>