unbridled-41 opened a new pull request, #4734:
URL: https://github.com/apache/rocketmq-dashboard/pull/4734

   Fixes #4731.
   
   ### Problem
   
   The asset/dashboard preview modal renders a failed request as an empty box. 
`handleView` catches the failed preview request and only raises a toast, while 
the modal body branches on `viewLoading` alone — so after loading ends the 
`<pre>` renders an empty string, and for as long as the modal stays open there 
is no error text and no retry.
   
   Two sibling components share the defect:
   
   - `web/src/components/AlertRuleAssetList.tsx` — 业务告警 asset list (View 
button).
   - `web/src/components/GrafanaDashboardList.tsx` — Grafana 看板 list (View 
button).
   
   Both already implement the correct pattern for their *list* request (an 
error state plus a retry button, `AlertRuleAssetList.tsx:232-248` and the 
Grafana equivalent); the preview request is the one load in these files whose 
failure has no surface.
   
   Trigger (deterministic): click 查看/View on any row while the preview request 
fails (4xx/5xx/timeout, e.g. the backend restarts or the dashboard file is 
unreadable). The modal opens, the toast flashes once, and the pane stays blank; 
the operator cannot tell a failed request from an empty document and must close 
and reopen the modal to try again.
   
   ### Root cause
   
   `viewContent` is the only view state: it stays `''` on failure and the 
render has no failure branch, so a rejected request and a successful-but-empty 
response are indistinguishable.
   
   ### Fix
   
   Add a `viewError` flag to both components: set on the catch (next to the 
existing toast), cleared at the start of every attempt and on close. The modal 
body now renders an error `Alert` with a retry button that re-issues the 
request for the asset/dashboard currently being previewed, instead of the empty 
`<pre>`. No i18n keys added — the existing `alertAssets.loadFailed` / 
`grafana.loadFailed` messages and `common.retry` are reused, matching the 
list-level failure UI in the same files.
   
   ### Priority
   
   **70** = impact 26 + reach 10 + reproducibility 20 + maintenance value 14.
   
   - Impact 26/40: a recoverable read failure is presented as an empty 
document; the only signal lives for seconds.
   - Reach 10/20: two components on two pages, any transient preview failure.
   - Reproducibility 20/20: deterministic — stub the service to reject once.
   - Maintenance value 14/20: restores parity with the list-level failure 
handling already in these files.
   
   `FIX_CONFIDENCE`: **92** — the failing test and the sibling pattern in the 
same file fix the expected behavior; the change is additive state plus one 
render branch.
   
   ### Tests
   
   Red (source at base commit `7ce9a682`, new tests added):
   
   ```
   npx vitest run src/components/__tests__/AlertRuleAssetList.test.tsx 
src/components/__tests__/GrafanaDashboardList.test.tsx
       × renders a failed preview as an error with a retry instead of an empty 
pane   (AlertRuleAssetList)
       × renders a failed preview as an error with a retry instead of an empty 
pane   (GrafanaDashboardList)
   TestingLibraryElementError: Unable to find role="button" and name 
`/Retry|重试/`
   ```
   
   Green (this branch):
   
   ```
   npx vitest run src/components/__tests__/AlertRuleAssetList.test.tsx 
src/components/__tests__/GrafanaDashboardList.test.tsx
       Test Files  2 passed (2)
            Tests  21 passed (21)
   ```
   
   Each new test asserts the full contract: the failed preview shows a retry 
inside the dialog, the retry re-issues the request (call count 1 → 2), the 
content replaces the error, and the retry button is gone afterwards.
   
   Related suites and gates on this branch (`fix/asset-preview-failure-state` @ 
16160cb5):
   
   - `npx vitest run --maxWorkers=4` → **134 files / 1237 tests, all passed** 
(5 min).
   - `npx tsc -b` → clean.
   - `npx eslint <the 4 changed files>` → clean.
   - `npm run build` → `✓ built in 11.21s`.
   
   ### Risk
   
   Low. The change is additive: a new boolean plus one render branch per 
component, reusing the same loading/failure vocabulary as the list request 
above it. The retry path calls the existing `handleView(viewing)`, which 
already bumps the request-generation ref, so an in-flight/stale response still 
cannot land (covered by the existing "keeps the latest preview" tests, which 
stay green). The only visible change on the success path is that a stale error 
can no longer survive a successful retry.
   
   ### Base branch
   
   Targets `rocketmq-studio`, the development trunk. Note the repository's 
default branch is still `master`; GitHub interprets the closing keyword only 
for PRs that target the default branch, so the `Fixes` link above does not 
auto-close #4731 when this merges — the issue needs to be closed by hand.
   


-- 
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]

Reply via email to