Skip to content

[fix] keep a settings save message on the card that saved - #137

Merged
malickyeu merged 1 commit into
mainfrom
fix/settings-save-message
Aug 5, 2026
Merged

[fix] keep a settings save message on the card that saved#137
malickyeu merged 1 commit into
mainfrom
fix/settings-save-message

Conversation

@malickyeu

Copy link
Copy Markdown
Contributor

Summary

Reported from use: saving Enabled features also showed a success message on
Security → localhost 2FA exemption.

Both cards persist through the same endpoint (one settings payload), so the page
kept a single msg string and both cards rendered it. Two things were wrong with
that: the message appeared where nothing had been saved from, and the wording —
"Users may need to reload for nav changes to apply" — is about the feature flags
and says nothing true about the 2FA exemption.

The message now carries the card that produced it, and each card gets text about
what it actually changed (the exemption applies to the next sign-in).

Deliberately unchanged: Save still submits both values, because that is what
the endpoint takes. Splitting the payload would be a behaviour change beyond the
reported bug, and the current arrangement is harmless — it persists what's on
screen either way.

Type of change

  • Bug fix
  • New feature
  • Docs only
  • Refactor / chore

Checklist

  • go test -short ./... and go vet ./... pass — N/A (no Go changed)
  • gofmt gate is clean — N/A (no Go changed)
  • Frontend type-checks (cd web && npx tsc --noEmit)
  • Rebuilt and committed web/dist
  • Added/updated tests for the change — 3 component tests, 80 frontend tests total
  • Updated docs/ and added a CHANGELOG.md entry — N/A: a status message on an admin page, no documented behaviour changes

Notes for reviewers

The component test is the first thing the happy-dom environment from #130 has been
useful for outside its own wiring: this bug is invisible to a unit test and obvious
to a rendered one.

Mutation-tested — putting the shared message back makes two of the three fail
(does not carry the Features message over to Security, gives Security its own wording). The third asserts the message still appears on the card that saved, so
"render nothing" cannot pass either.

Both cards on the Settings page write through one endpoint, so the status
message was one string rendered by both: saving Enabled features lit up
the 2FA card in Security too — and with Features' wording, which talks
about nav changes and says nothing true about the exemption.

The message now carries the card that produced it, and each card gets
text about what it actually changed: the exemption applies to the next
sign-in.

Covered by a component test that fails when the message is unscoped again.
Copilot AI lite review requested due to automatic review settings August 5, 2026 11:46

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes Settings page save feedback so success/error messages stay attached to the card/tab that initiated the save, avoiding misleading cross-card messaging when both cards persist through the same setSettings endpoint.

Changes:

  • Scope the save status message to the originating Settings tab/card and customize the success text per card.
  • Add a happy-dom component test covering scoped messaging across the Features and Security tabs.
  • Update committed web/dist artifacts for the frontend rebuild.

Reviewed changes

Copilot reviewed 2 out of 5 changed files in this pull request and generated 2 comments.

File Description
web/src/pages/Settings.tsx Scopes save feedback by tab/card and customizes success copy per card.
web/src/pages/Settings.dom.test.tsx Adds DOM-level regression tests for scoped save feedback across tabs.
web/dist/index.html Updates asset hash reference after rebuild.
web/dist/assets/CodeEditor-DS5r_yrM.js Rebuilt bundle chunk reflecting updated asset linkage.
Suppressed comments (4)

web/src/pages/Settings.tsx:44

  • save() sets an error message on failure, but the message currently has no success/failure flag. Once msg includes an ok boolean, populate it here so the renderer can style failures appropriately.
    try {
      await api.setSettings({ disabledSections: [...disabled], localhostNo2fa: no2fa });
      setMsg({ scope, text: okText });
    } catch {
      setMsg({ scope, text: "Save failed" });

web/src/pages/Settings.tsx:86

  • Once msg.ok is available, use it to pick text-ok vs text-danger so errors don't render with success styling.
                {msg?.scope === "features" && <span className="text-sm text-ok">{msg.text}</span>}

web/src/pages/Settings.tsx:109

  • Same as the Features card: when save fails, the status text should render with an error class rather than text-ok.
                {msg?.scope === "security" && <span className="text-sm text-ok">{msg.text}</span>}

web/src/pages/Settings.dom.test.tsx:78

  • Use the clickSave() helper (awaiting the mocked setSettings promise) instead of act(async () => saveButton().click()) so assertions run after the post-save status message has been applied.
  it("shows the result on the card that saved", async () => {
    await act(async () => saveButton().click());
    expect(container.textContent).toContain("nav changes");
  });

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +21 to 26
// Scoped to the card that saved. Both cards write through the same endpoint
// (one settings payload), so a single message string meant pressing Save under
// Features also lit up the 2FA card in Security — with Features' wording, which
// is about nav changes and says nothing true about the exemption.
const [msg, setMsg] = useState<{ scope: Tab; text: string } | null>(null);
const [tab, setTab] = useState<Tab>("features");
Comment on lines +68 to +73
function saveButton(): HTMLElement {
const el = [...container.querySelectorAll("button")].find((b) => b.textContent?.includes("Save settings"));
if (!el) throw new Error("save button not found");
return el;
}

@malickyeu
malickyeu merged commit cc36c81 into main Aug 5, 2026
4 checks passed
@malickyeu
malickyeu deleted the fix/settings-save-message branch August 5, 2026 11:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants