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.