This is an automated email from the ASF dual-hosted git repository.

wu-sheng pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/skywalking-horizon-ui.git


The following commit(s) were added to refs/heads/main by this push:
     new 54b5adc  ui dashboards: don't bounce ?instance= when list is briefly 
empty + cover full upstream wait in loading state
54b5adc is described below

commit 54b5adc596d87b15be981d5439f98c909dd69521
Author: Wu Sheng <[email protected]>
AuthorDate: Sun May 17 17:59:20 2026 +0800

    ui dashboards: don't bounce ?instance= when list is briefly empty + cover 
full upstream wait in loading state
    
    Two complementary fixes that together stop the "two instances
    visible but neither selected and no dashboard" symptom on
    /layer/<x>/instance?service=&instance=:
    
    1. Instance auto-pick watch was clearing the URL `?instance=` on
       the transient empty-list state (service just resolved, the
       layer-instances vue-query has fired but the response hasn't
       landed yet). The clear caused a URL bounce: ?instance=X → no
       instance → ?instance=X again, with dashboard.enabled going
       false → true in between and the picker showing no highlight
       during the gap. Now we simply wait for actual instance data;
       if the list eventually resolves to truly empty (loading false +
       length 0), the picker's own empty state handles it.
    
    2. The "Reading data…" indicator was gated on
       `isFetching && data === null` — that misses the window where
       serviceName hasn't resolved (landing query still firing) and
       the dashboard query hasn't even been enabled yet
       (isFetching=false). The grid v-else rendered with empty
       widgets during that gap. Now gates on `data === null && reachable`,
       so the indicator covers the full upstream wait
       (landing → service → instance/endpoint → dashboard). OAP-
       unreachable still falls through to the existing error banner.
---
 .../render/layer-dashboard/LayerDashboardsView.vue | 35 ++++++++++++++--------
 1 file changed, 22 insertions(+), 13 deletions(-)

diff --git a/apps/ui/src/render/layer-dashboard/LayerDashboardsView.vue 
b/apps/ui/src/render/layer-dashboard/LayerDashboardsView.vue
index fc6babb..246ba7f 100644
--- a/apps/ui/src/render/layer-dashboard/LayerDashboardsView.vue
+++ b/apps/ui/src/render/layer-dashboard/LayerDashboardsView.vue
@@ -172,10 +172,15 @@ watch(serviceName, (next, prev) => {
 // the pick when the list arrived synchronously.
 watch([instanceList, scope], ([list, s]) => {
   if (s !== 'instance') return;
-  if (list.length === 0) {
-    if (selectedInstance.value) setSelectedInstance(null);
-    return;
-  }
+  // Don't clear the URL ?instance= when the list is TEMPORARILY
+  // empty (e.g. service just changed and the instance query is
+  // re-firing) — clearing causes a visible URL bounce that
+  // strips the operator's pick and breaks dashboard.enabled. We
+  // simply wait for actual instance data; if the list eventually
+  // resolves to truly empty (instancesLoading false + length 0),
+  // the picker's own empty state handles it and the dashboard
+  // gate keeps the widget batch quiet.
+  if (list.length === 0) return;
   if (!selectedInstance.value || !list.some((i) => i.name === 
selectedInstance.value)) {
     setSelectedInstance(list[0].name);
   }
@@ -537,15 +542,19 @@ function isVisible(
     <div v-else-if="widgets.length === 0" class="empty">
       No widgets defined for this layer. Phase 7 admin will let operators add 
their own.
     </div>
-    <!-- Single page-level loading state while the widget batch is
-         in flight without a prior result. Replaces the per-widget
-         "loading…" cards from f9866cf — the dashboard query is
-         batched so the widgets all land together; one indicator is
-         cleaner than N. Once the result is in `data`, the grid
-         takes over and shows each widget's value / no-data / error
-         normally. Background refetches (auto-refresh) keep showing
-         the prior data, no flash. -->
-    <div v-else-if="isFetching && data === null" class="empty reading">
+    <!-- Single page-level loading state while we don't yet have
+         widget data to render. Covers the whole upstream wait,
+         not just the dashboard fetch:
+           - landing query in flight (serviceName unresolved →
+             dashboard.enabled still false, isFetching=false,
+             but we're still loading)
+           - dashboard query in flight
+         The widget batch is server-side batched so widgets all
+         land together; one indicator is cleaner than N "loading…"
+         cards. Once `data` arrives, the grid takes over and shows
+         each widget's value / no-data / error normally. Background
+         refetches keep showing the prior data, no flash. -->
+    <div v-else-if="data === null && reachable" class="empty reading">
       <span class="reading-dot" /> Reading data…
     </div>
     <div v-else class="grid">

Reply via email to