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 cbe83cf  ui events: per-widget result events after the dashboard batch 
returns
cbe83cf is described below

commit cbe83cf6e4b17e522b56c431ae51dee23c973d63
Author: Wu Sheng <[email protected]>
AuthorDate: Sun May 17 12:01:44 2026 +0800

    ui events: per-widget result events after the dashboard batch returns
    
    After the orchestrator's step 6 ("widgets rendered M/N") fires, emit
    one info / ok / err event per widget in the batch — labelled by the
    widget's title (from the config bundle) and tagged with what came
    back: a scalar value, N series, top-N items, or an explicit error /
    "no data". Topic is `widget/<widget-id>` so paired starts (none —
    the batch fires once at the dashboard step) and any future per-
    widget refetches dedup correctly per id.
    
    Operator can now scan the EventTicker history and tell at a glance
    which specific widget MQE landed and which came back empty without
    having to scroll the grid looking for blank cards.
---
 .../layer-dashboard/useLayerPageOrchestrator.ts    | 46 +++++++++++++++++++++-
 1 file changed, 45 insertions(+), 1 deletion(-)

diff --git a/apps/ui/src/render/layer-dashboard/useLayerPageOrchestrator.ts 
b/apps/ui/src/render/layer-dashboard/useLayerPageOrchestrator.ts
index 6b82d3a..703fe18 100644
--- a/apps/ui/src/render/layer-dashboard/useLayerPageOrchestrator.ts
+++ b/apps/ui/src/render/layer-dashboard/useLayerPageOrchestrator.ts
@@ -69,7 +69,16 @@ export interface OrchestratorRefs {
   endpointList: Ref<ReadonlyArray<{ id: string; name: string }>>;
   effectiveEndpoint: Ref<string | null>;
   /** Dashboard response — widgets rendered. */
-  dashboard: Ref<{ widgets?: Array<{ error?: string; value?: unknown; series?: 
unknown[]; topList?: unknown[]; topGroups?: unknown[] }> } | null>;
+  dashboard: Ref<{
+    widgets?: Array<{
+      id: string;
+      error?: string;
+      value?: unknown;
+      series?: unknown[];
+      topList?: unknown[];
+      topGroups?: unknown[];
+    }>;
+  } | null>;
 }
 
 type Phase =
@@ -242,6 +251,41 @@ export function useLayerPageOrchestrator(refs: 
OrchestratorRefs): {
       report('dashboard', `Step 6 · widgets rendered · ${withData}/${total} 
with data`);
       stamps.dashboard = true;
       done.value = true;
+
+      // After the batch dashboard returns, emit a per-widget event
+      // for every result so the EventTicker shows which widget got
+      // data, which came back empty, and which errored. The dashboard
+      // query is batched server-side (one GraphQL trip for all MQEs)
+      // so these are post-hoc info events, not separate fetches —
+      // they let the operator pinpoint a specific widget's status
+      // without staring at the rendered grid.
+      const cfgWidgets = (refs.config.value?.widgets ?? []) as Array<{ id?: 
string; title?: string }>;
+      const titleById = new Map<string, string>();
+      for (const cw of cfgWidgets) {
+        if (cw?.id) titleById.set(cw.id, cw.title ?? cw.id);
+      }
+      for (const r of widgets) {
+        const label = titleById.get(r.id) ?? r.id;
+        let kind: 'ok' | 'err' | 'info' = 'info';
+        let detail = 'no data';
+        if (r.error) {
+          kind = 'err';
+          detail = `error: ${r.error}`;
+        } else if (r.value != null) {
+          kind = 'ok';
+          detail = `value ${r.value}`;
+        } else if (Array.isArray(r.series) && r.series.length > 0) {
+          kind = 'ok';
+          detail = `${r.series.length} series`;
+        } else if (Array.isArray(r.topList) && r.topList.length > 0) {
+          kind = 'ok';
+          detail = `top ${r.topList.length}`;
+        } else if (Array.isArray(r.topGroups) && r.topGroups.length > 0) {
+          kind = 'ok';
+          detail = `${r.topGroups.length} group${r.topGroups.length === 1 ? '' 
: 's'}`;
+        }
+        pushEvent(`widget/${r.id}`, kind, `Widget ${label} · ${detail}`);
+      }
     },
     { immediate: true },
   );

Reply via email to