fix(frontend): tell the user what is wrong instead of showing nothing - #11
Merged
TheMeinerLP merged 1 commit intoAug 8, 2026
Merged
Conversation
Four places reported failure by not reporting it, and two of them lost the message entirely. The console rendered an empty white rectangle whenever the log stream did not come up. The only signal was a toast, which faded after a few seconds and left no trace, so the panel was indistinguishable from a server that simply had nothing to say. It now carries its own state: connecting, connected but quiet, or disconnected with the reason and a Reconnect button. The command input is disabled while the stream is down instead of silently swallowing what gets typed into it. The three toasts are gone, because the information belongs where the reader is already looking. Toasts appeared in the top right corner, which is where the header keeps the account name and the logout button. While one was up, logging out was not clickable. They come up bottom right now, decided once in helpers/toast.js rather than per call site. Four files reached for `createToast` directly and picked a corner each; one login attempt could put its success message in one corner and its failure in another. The sign-in button was filled light grey on white, the same treatment this interface gives a disabled control, and the fields carried no label beyond a placeholder that disappears as soon as anything is typed. It is a primary button now, in the same blue the token page already uses, with real labels and the failure shown inside the dialog rather than behind it. Upload sat inside the file list as a rounded row the same size and shape as a directory entry, told apart from real content by the colour of a dot. It is a labelled drop area below the listing now, so an action no longer looks like content. Two defects surfaced while reading that code and are fixed here: - Nothing ever closed the log stream. `close()` on unmount was commented out, so every visit to the tab left another EventSource running against the server. Verified: one connection per mount, none left behind after leaving. - Every `.catch` that formatted an error read `error.response.status` and `error.response.data.message` directly. That works for a server that answered and throws for one that did not, and the throw happened inside the catch, taking the handler with it. A refused connection or an unreachable host, the most common failure of all, produced no message at all. There is one `errorMessage` helper now, lifted out of the tokens store where a correct version was already hiding, and the five call sites use it. Verified against the previous state view by view: overview and tokens come out pixel identical, settings differs only in the two bands where the toast moved from one corner to the other, and the dashboard only in its live values. Console is the intended redesign. Also removes five stray semicolons that eslint flagged in the console store, which the rewrite touched anyway. Errors on the branch drop from seven to two; both survivors sit in files this change does not open. Signed-off-by: TheMeinerLP <github@themeinerlp.dev>
9 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Stacked on #10. This targets
feat/tailwind-dashboard-ui, notmain, so the diff stays readable. Merge #10 first and GitHub retargets this one.Four places in the dashboard reported failure by not reporting it. Two of them lost the message entirely.
The console showed nothing at all
When the log stream did not come up, the panel was an empty white rectangle. The only signal was a toast, which faded after a few seconds and left no trace, so a broken connection looked exactly like a server with nothing to say.
It carries its own state now: connecting, connected but quiet, or disconnected with the reason and a Reconnect button. The command input is disabled while the stream is down instead of silently swallowing whatever gets typed into it. The three toasts are gone, because the information belongs where the reader is already looking.
No automatic retry, on purpose. A stream that failed because the server is struggling is the worst moment to start reconnecting in a loop, so the retry happens when somebody decides it should.
Toasts covered the logout button
They appeared top right, which is where the header keeps the account name and the logout button. While a toast was up, logging out was not clickable.
Bottom right now, decided once in
helpers/toast.js. Four files reached forcreateToastdirectly and picked a corner each, so a single login attempt could put its success message in one corner and its failure in another.The sign-in button looked disabled
Filled light grey on white, the same treatment this interface gives a disabled control, and it is the primary action of the whole authentication flow. The fields carried no label beyond a placeholder that disappears the moment anything is typed.
It is a primary button now in the blue the token page already uses, with real labels, and the failure appears inside the dialog rather than behind it.
Upload looked like a directory
It sat inside the file list as a rounded row the same size and shape as a directory entry, told apart from real content by the colour of a dot. It is a labelled drop area below the listing now.
The screenshots come from
fake-api/fake-ingot-backend.jsand live on the orphan branchassets/pr-11-screenshots, which shares no history withmainand is never merged. Deleting that branch breaks the images above.Two defects found while reading that code
close()on unmount was commented out, so every visit to the Console tab left anotherEventSourcerunning against the server. Measured after the fix: one connection per mount, one per reconnect, none left behind..catchhandlers readerror.response.statusanderror.response.data.messagedirectly. That works for a server that answered and throws for one that did not, and the throw happened inside the catch, taking the handler with it. A refused connection or an unreachable host produced no message at all. There is oneerrorMessagehelper now, lifted out ofstore/tokens.jswhere a correct version was already hiding, and the five call sites use it.Type of change
fix- bug fixHow was this tested?
Same method as #10: both states rendered and compared per pixel, five views times two themes times two viewports.
The views that do differ were checked band by band rather than accepted:
settingsdiffers in exactly two horizontal bands, y 12-75 and y 824-887, which is the toast leaving one corner and arriving in the other. Nothing else on that page moved.dashboarddiffers only in its live values: the uptime figure and the two chart areas.consoleis the intended redesign.Behaviour was checked directly rather than inferred:
/api/console/logrequestsThe rejected-login path was exercised against the stub and renders the server's own message inline. No page errors during any of it.
npm run eslint: errors drop from 7 to 2. Five were stray semicolons in the console store, which this change rewrites anyway. Both survivors sit in files this branch does not open../gradlew buildpasses.Checklist
CLAUDE.md./gradlew buildpasses locallySame note as #10 on the tests box: the frontend has no test infrastructure and this branch does not add one. The verification above is a screenshot comparison plus a request count, reproducible but not committed. The connection lifecycle in particular is the kind of thing that deserves a real test, and that is worth its own PR.