This is an automated email from the ASF dual-hosted git repository. wu-sheng pushed a commit to branch refactor/decompose-large-files in repository https://gitbox.apache.org/repos/asf/skywalking-horizon-ui.git
commit c3a0e82adc97f06649ac275939958a702fad4389 Author: Wu Sheng <[email protected]> AuthorDate: Fri Jun 26 23:28:50 2026 +0800 fix(alarms,k8s): timeline selection band + legend, narrow-width detail, dashboard heights The alarm timeline draws the orange selection band on a flag click (not only on drag) and gains a firing/recovered legend so the red-bottom / green-top stack reads clearly. The alarm list/detail split stacks below ~1080px instead of overflowing, and long service names wrap cleanly. K8s dashboard status tables (k8s_service Pods Waiting / Pod Restarts; kubernetes Node / Deployment / Service / Pod status) drop from rowSpan 3-4 to 2 to remove the blank space. --- apps/bff/src/bundled_templates/layers/k8s.json | 12 ++--- .../src/bundled_templates/layers/k8s_service.json | 4 +- apps/ui/src/components/charts/AlarmsTimeline.vue | 54 +++++++++++++++------- apps/ui/src/features/alarms/AlarmDetailPanel.vue | 4 +- apps/ui/src/features/alarms/AlarmsView.vue | 7 +++ 5 files changed, 56 insertions(+), 25 deletions(-) diff --git a/apps/bff/src/bundled_templates/layers/k8s.json b/apps/bff/src/bundled_templates/layers/k8s.json index e40c368..f82745a 100644 --- a/apps/bff/src/bundled_templates/layers/k8s.json +++ b/apps/bff/src/bundled_templates/layers/k8s.json @@ -209,7 +209,7 @@ ], "showTableValues": false, "span": 4, - "rowSpan": 4 + "rowSpan": 2 }, { "id": "deployment_status", @@ -225,7 +225,7 @@ ], "showTableValues": false, "span": 4, - "rowSpan": 4 + "rowSpan": 2 }, { "id": "deployment_replicas", @@ -241,7 +241,7 @@ ], "showTableValues": true, "span": 4, - "rowSpan": 4 + "rowSpan": 2 }, { "id": "service_pod_status", @@ -257,7 +257,7 @@ ], "showTableValues": false, "span": 4, - "rowSpan": 4 + "rowSpan": 2 }, { "id": "pod_not_running", @@ -273,7 +273,7 @@ ], "showTableValues": false, "span": 4, - "rowSpan": 4 + "rowSpan": 2 }, { "id": "pod_waiting", @@ -289,7 +289,7 @@ ], "showTableValues": false, "span": 4, - "rowSpan": 4 + "rowSpan": 2 } ], "instance": [ diff --git a/apps/bff/src/bundled_templates/layers/k8s_service.json b/apps/bff/src/bundled_templates/layers/k8s_service.json index adf68aa..8a541c5 100644 --- a/apps/bff/src/bundled_templates/layers/k8s_service.json +++ b/apps/bff/src/bundled_templates/layers/k8s_service.json @@ -83,7 +83,7 @@ ], "showTableValues": false, "span": 4, - "rowSpan": 3 + "rowSpan": 2 }, { "id": "pod_restarts", @@ -98,7 +98,7 @@ ], "showTableValues": true, "span": 4, - "rowSpan": 3 + "rowSpan": 2 }, { "id": "cpu_resources", diff --git a/apps/ui/src/components/charts/AlarmsTimeline.vue b/apps/ui/src/components/charts/AlarmsTimeline.vue index c4457aa..f92b148 100644 --- a/apps/ui/src/components/charts/AlarmsTimeline.vue +++ b/apps/ui/src/components/charts/AlarmsTimeline.vue @@ -359,27 +359,49 @@ watch( { deep: true }, ); -/* Parent-driven brush clear: when the operator hits the "clear - * selection" button in the list header, the parent sets its - * `selectedRange` ref to null. Mirror that into the chart by - * wiping the brush rectangle. We only act on the null transition — - * a non-null selection on this side is either echoed from a drag we - * just did (no-op needed) or from a click on a flag (no rectangle - * needed; the row list narrowing is the visual feedback). */ -watch( - () => props.selectedRange, - (next) => { - if (next === null || next === undefined) clearBrush(); - }, -); +/** Draw the orange selection band for a range (or wipe it when null). + * Keeps the chart's rectangle in sync with the parent's `selectedRange` + * whatever the source — a drag (snaps to the whole-minute range), a flag + * click (a single-minute band, so the operator sees which slice is + * active, not just the narrowed list), or the parent's clear button. */ +function drawBrush(range: { startTime: number; endTime: number } | null | undefined): void { + if (!chart) return; + if (range === null || range === undefined) { + clearBrush(); + return; + } + chart.dispatchAction({ + type: 'brush', + areas: [{ brushType: 'lineX', xAxisIndex: 0, coordRange: [range.startTime, range.endTime] }], + }); +} +watch(() => props.selectedRange, (next) => drawBrush(next)); </script> <template> - <div ref="container" class="alarms-timeline" :style="{ height: `${height ?? 110}px` }" /> + <div class="alarms-timeline-wrap"> + <div ref="container" class="alarms-timeline" :style="{ height: `${height ?? 110}px` }" /> + <!-- Legend — the stack is firing (red) on the bottom, recovered (green) + on top; without this the colored areas / pins read ambiguously. --> + <div class="atl-legend"> + <span class="atl-leg"><i class="atl-swatch firing" /> firing</span> + <span class="atl-leg"><i class="atl-swatch recovered" /> recovered</span> + </div> + </div> </template> <style scoped> -.alarms-timeline { - width: 100%; +.alarms-timeline-wrap { width: 100%; } +.alarms-timeline { width: 100%; } +.atl-legend { + display: flex; + gap: 16px; + padding: 2px 4px 0; + font-size: 10.5px; + color: var(--sw-fg-3); } +.atl-leg { display: inline-flex; align-items: center; gap: 5px; } +.atl-swatch { width: 9px; height: 9px; border-radius: 2px; display: inline-block; } +.atl-swatch.firing { background: #ef4444; } +.atl-swatch.recovered { background: #22c55e; } </style> diff --git a/apps/ui/src/features/alarms/AlarmDetailPanel.vue b/apps/ui/src/features/alarms/AlarmDetailPanel.vue index 78d4041..73cd56d 100644 --- a/apps/ui/src/features/alarms/AlarmDetailPanel.vue +++ b/apps/ui/src/features/alarms/AlarmDetailPanel.vue @@ -330,7 +330,9 @@ const rulePeriod = computed<number | null>(() => ruleDetail.value?.period ?? nul color: var(--sw-fg-0); margin: 0; line-height: 1.4; - word-break: break-all; + /* `anywhere` breaks long dotted/hyphenated service names only when they + can't fit, instead of `break-all` chopping every line mid-character. */ + overflow-wrap: anywhere; } /* Probe-source classifier (`agent`, `mesh-svr`, `mesh-dp`, `mesh-cp`). * Just operational metadata — muted, not accent. Render as a quiet diff --git a/apps/ui/src/features/alarms/AlarmsView.vue b/apps/ui/src/features/alarms/AlarmsView.vue index 72095cf..3f9c491 100644 --- a/apps/ui/src/features/alarms/AlarmsView.vue +++ b/apps/ui/src/features/alarms/AlarmsView.vue @@ -859,6 +859,13 @@ onMounted(() => { grid-template-columns: 1fr 360px; gap: 16px; } +/* Narrow viewports: the fixed 360px detail rail + squeezed list overflow, + so stack the detail below the list at full width instead. */ +@media (max-width: 1080px) { + .ax__split { + grid-template-columns: 1fr; + } +} .ax__list { display: flex; flex-direction: column; gap: 12px; } .ax__empty { padding: 24px;
