wu-sheng opened a new pull request, #79: URL: https://github.com/apache/skywalking-horizon-ui/pull/79
## Why A layer dashboard slot can only hold one widget today. When several related widgets belong together — golden signals, one panel per subsystem, traffic vs. errors vs. saturation — each one spends a grid slot, and dense dashboards run out of room. This adds a `tab` container so an operator can pack several widgets (each its own panel) into a single slot, querying only what's on screen. ## What A layer-dashboard widget can now be a **`tab` container**: one grid slot holding any number of **named tab panels**, each its own little dashboard of `card` / `line` / `top` / `record` / `table` widgets in a 12-column sub-grid. - **Lazy** — only the **active** tab is queried; switching loads a panel on demand and keeps it warm. A tab carries no MQE of its own and cannot nest another tab (one level deep). - **Authored inline** in the Layer dashboards admin — set a widget's type to `tab`, size the slot; a segmented tab bar switches the active panel, a per-tab `+ widget` drops widgets in place, click to edit in the drawer, drag a corner to resize, or drag a widget out to the top level. Tabs are managed (add / rename / reorder / delete) from the drawer's Tabs list. - **Full parity inside a tab** — multi-entity **compare** (per-entity card rows / overlaid lines / grouped tables), the top/record **pop-out**, and **`visibleWhen`** gating (compare-aware union, never the container) all work, via a shared host render context. A unified widget-tree traversal (`walkWidgets` / `findWidgetById` / `collectWidgetIds`) is the single place that descends tab panels, so find-by-id / id-uniqueness / topNOrder-enrichment never miss a tab child. - **Querying** — the SPA flattens to the active tab's leaves and chunks at the 40-widget request cap; the BFF flattens a tab to its first (default-active) panel for the template-fallback / direct-API paths, re-checks the cap after expansion for a hand-built body, accepts the `tab` type + empty `expressions`, and drops a half-authored (blank-MQE) leaf from the batch instead of 400-ing the scope. Rides along: a **Clear all** button on the compare bar to exit comparison (the CURRENT chip has no per-entity ×); compare-aware "OAP unreachable" banner / "refreshing" badge (a failed primary no longer mislabels a working cohort); memoized compare render data (stable array identity — no per-tick ECharts re-push); and `keepPreviousData` on the compare fan-out so a tab switch doesn't blank locked-entity siblings. Backend contract is unchanged — the `tab` type is a UI/BFF container; the GraphQL/MQE wire is the same. No bundled template ships a tab (operator-authored). ## Validation - `pnpm -r run type-check`, `build-ui`, `build-bff`, `pnpm -r run lint`, `pnpm license:check`, `pnpm -r run test:unit` (254 unit tests incl. new flatten / schema / chunking / topNOrder-in-tab coverage) — all green. - New UI strings translated across all 8 locales (en + zh-CN, es, pt, ja, ko, de, fr); `i18n:validate` green. - **Live OAP (public demo):** the BFF tab path returns only the active panel (lazy), rejects empty-MQE leaves and over-cap bodies; the runtime renders card/line/top, switches tabs (panel loads on demand), shows the pop-out, with zero console errors. - Docs (`docs/customization/layer-templates.md`) + `CHANGELOG.md` updated. - Reviewed adversarially in several passes (correctness, compare/visibleWhen parity, then missing/stale/improper/performance); confirmed findings fixed. -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
