Skip to content

fix(pad): keep menu_right visible on readonly pads by default#7783

Merged
JohnMcLear merged 1 commit into
developfrom
fix/readonly-menu-right-overhide
May 16, 2026
Merged

fix(pad): keep menu_right visible on readonly pads by default#7783
JohnMcLear merged 1 commit into
developfrom
fix/readonly-menu-right-overhide

Conversation

@JohnMcLear
Copy link
Copy Markdown
Member

Summary

The client-side `$('#editbar .menu_right').hide()` introduced for issue #5182 hides the userlist toggle alongside import/export when a pad is readonly. That breaks any auth plugin that hangs a "Log In" button off the userlist popup (notably ep_guest, which injects its button into `#myuser`): the readOnly guest user can see the pad but has no way to escape readOnly mode because the very button they need is hidden.

It also throws useful chrome (settings, embed, home, timeslider, userlist) out with the truly write-only stuff (savedrevision, import) — none of those are write-only, and the server already strips the ones that are.

Root cause

Two server-side mechanisms already handle readonly correctly:

  • `src/node/utils/toolbar.ts:282-290` — `toolbar.menu(..., isReadOnly)` removes `savedrevision` from the right toolbar for readonly pads.
  • `src/static/css/pad/popup_import_export.css:1` — `.readonly .acl-write { display: none }` hides the Import column of the import/export popup; export stays visible and is legitimately useful in readonly.

The blanket client-side hide is redundant against both and only serves the iframe-embed clean-chrome use case from #5182 — which is already served by the explicit `?showMenuRight=false` opt-out (handler at `src/static/js/pad.ts:91-107`), or by `?showControls=false` which hides the entire editbar.

Change

  • Remove the auto-hide at `pad.ts:783`. Readonly pads now show `.menu_right` by default.
  • Update the comment on the `showMenuRight` URL parameter handler to reflect that hiding is now opt-in via `?showMenuRight=false` (was: opt-out of an auto-hide via `?showMenuRight=true`).

The `?showMenuRight=true` and `?showMenuRight=false` overrides still work; iframe-embed deployments switch from `?showMenuRight=true` (no-op now) to `?showMenuRight=false` (still hides).

Tests

`src/tests/frontend-new/specs/hide_menu_right.spec.ts`:

  • ✏️ Inverted `readonly pad hides .menu_right by default` → `readonly pad shows .menu_right by default`.
  • ➕ Added `readonly pad with showMenuRight=false hides the menu` to cover the iframe-embed opt-out.
  • ✅ `readonly pad with showMenuRight=true keeps the menu visible` still passes.

Test plan

  • Frontend tests green (the test file is rewritten to match the new behaviour)
  • Backend tests green
  • Manual: install ep_guest, set the guest user to `readOnly: true`, visit a pad unauth; the Log In button is reachable from the userlist popup.
  • Manual: visit a readonly pad with `?showMenuRight=false`; the right toolbar is still hidden (issue Hide menu_right on ReadOnly pads #5182 iframe-embed case still works).

🤖 Generated with Claude Code

PR #X (issue #5182) added a client-side `$('#editbar .menu_right').hide()`
for readonly pads, opt-out via `?showMenuRight=true`. The intent — clean
chrome for iframe-embedded readonly announcement pads — was good but the
implementation hid the userlist toggle along with import/export.

That has two unwanted effects on non-embed deployments:

  * Plugins like ep_guest inject their "Log In" button into `#myuser`
    inside the userlist popup, which lives under `.menu_right`. When
    the guest user (readOnly: true) lands on a readonly pad, the button
    they need to escape readonly is hidden. Chicken-and-egg.
  * Settings, embed, home, timeslider, showusers are all legitimately
    useful for readonly viewers and got removed alongside the actual
    write-only controls.

The server already does the right thing without help from the client:

  * src/node/utils/toolbar.ts:282-290 strips `savedrevision` from the
    right toolbar when isReadOnly is true.
  * src/static/css/pad/popup_import_export.css:1 has
    `.readonly .acl-write { display: none }`, which hides the Import
    column of the import/export popup. Export stays visible (and is
    legitimately useful in readonly).

Drop the client-side blanket hide. The iframe-embed use case from #5182
is still served by `?showMenuRight=false` (the existing handler at
src/static/js/pad.ts:91-107), and `?showControls=false` continues to
hide the entire editbar for callers who want even the left menu gone.

Tests: rewrite `hide_menu_right.spec.ts`. The "readonly pad hides
.menu_right by default" assertion is inverted; a new test confirms
`?showMenuRight=false` still hides on readonly pads.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@qodo-code-review
Copy link
Copy Markdown

Qodo reviews are paused for this user.

Troubleshooting steps vary by plan Learn more →

On a Teams plan?
Reviews resume once this user has a paid seat and their Git account is linked in Qodo.
Link Git account →

Using GitHub Enterprise Server, GitLab Self-Managed, or Bitbucket Data Center?
These require an Enterprise plan - Contact us
Contact us →

@qodo-free-for-open-source-projects
Copy link
Copy Markdown

Review Summary by Qodo

Keep menu_right visible on readonly pads by default

🐞 Bug fix

Grey Divider

Walkthroughs

Description
• Remove client-side blanket hide of .menu_right on readonly pads
• Server-side mechanisms already handle readonly toolbar correctly
• Restore access to userlist for auth plugins like ep_guest
• Keep iframe-embed opt-out via ?showMenuRight=false parameter
Diagram
flowchart LR
  A["Readonly Pad Load"] --> B{"showMenuRight param?"}
  B -->|false| C["Hide menu_right<br/>iframe-embed case"]
  B -->|true or absent| D["Show menu_right<br/>default behavior"]
  D --> E["Server strips<br/>savedrevision"]
  D --> F["CSS hides Import<br/>column only"]
  D --> G["Userlist accessible<br/>for auth plugins"]
Loading

Grey Divider

File Changes

1. src/static/js/pad.ts 🐞 Bug fix +18/-12

Remove readonly menu_right auto-hide, update parameter docs

• Removed client-side auto-hide of .menu_right for readonly pads
• Updated showMenuRight parameter comment to reflect new opt-in behavior
• Changed from opt-out (?showMenuRight=true to show) to opt-in (?showMenuRight=false to hide)
• Added detailed explanation of server-side readonly handling mechanisms

src/static/js/pad.ts


2. src/tests/frontend-new/specs/hide_menu_right.spec.ts 🧪 Tests +16/-1

Update tests to match new readonly menu visibility behavior

• Inverted test assertion: "readonly pad shows .menu_right by default" (was hides)
• Added new test for ?showMenuRight=false parameter on readonly pads
• Updated test comments to explain server-side readonly handling
• Maintained existing test for ?showMenuRight=true override

src/tests/frontend-new/specs/hide_menu_right.spec.ts


Grey Divider

Qodo Logo

@qodo-free-for-open-source-projects
Copy link
Copy Markdown

qodo-free-for-open-source-projects Bot commented May 16, 2026

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (1)

Context used

Grey Divider


Action required

1. Readonly shows menu_right toolbar 📎 Requirement gap ⛨ Security
Description
The PR changes the default behavior so #editbar .menu_right remains visible on read-only pads.
This violates the requirement that read-only pads (especially iframe/embed) must not expose the
menu_right toolbar options.
Code

src/static/js/pad.ts[R789-803]

      $('#chaticon').hide();
      $('#options-chatandusers').parent().hide();
      $('#options-stickychat').parent().hide();
-      // Hide the right-side toolbar on readonly pads — import/export,
-      // timeslider, settings, share, users are all noise for viewers
-      // who can't interact with the pad. Callers who need those
-      // controls visible on a readonly pad can force them back via
-      // `?showMenuRight=true`, which runs in getParameters() above.
-      if (getUrlVars().get('showMenuRight') !== 'true') {
-        $('#editbar .menu_right').hide();
-      }
+      // The right-side toolbar stays visible on readonly pads. The
+      // server-side `toolbar.menu(buttons, isReadOnly)` (see
+      // src/node/utils/toolbar.ts) already strips `savedrevision`, and
+      // `.readonly .acl-write { display: none }` hides the Import column
+      // inside the import/export popup, so the remaining controls
+      // (export, timeslider, settings, embed, home, showusers) are all
+      // safe for readonly viewers — and the userlist is the surface that
+      // plugins like ep_guest hang their "Log In" button off, so hiding
+      // it traps guests in readonly with no way out. Iframe-embed use
+      // cases that want a clean look (issue #5182) opt in to the hide
+      // via `?showMenuRight=false`, or hide the whole editbar via
+      // `?showControls=false`.
Evidence
PR Compliance ID 1 requires hiding the menu_right toolbar options when the pad is read-only. In
pad.ts, the readonly branch now explicitly states the right-side toolbar stays visible and no
longer hides #editbar .menu_right; the updated test asserts the toolbar is visible by default on
readonly pads, confirming the non-compliant behavior.

Hide menu_right toolbar options on read-only pads (iframe/embed support)
src/static/js/pad.ts[785-803]
src/tests/frontend-new/specs/hide_menu_right.spec.ts[47-67]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The compliance requirement states that when a pad is opened in read-only mode (especially embedded via iframe), the `menu_right` toolbar must not be visible. The current PR explicitly keeps `#editbar .menu_right` visible on readonly pads by default, and the frontend test suite was updated to assert that visibility.

## Issue Context
To comply, readonly pads should hide `#editbar .menu_right` by default, while still allowing explicit overrides via the existing `showMenuRight` URL parameter.

## Fix Focus Areas
- src/static/js/pad.ts[785-803]
- src/tests/frontend-new/specs/hide_menu_right.spec.ts[47-67]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Qodo Logo

Comment thread src/static/js/pad.ts
Comment on lines 789 to +803
$('#chaticon').hide();
$('#options-chatandusers').parent().hide();
$('#options-stickychat').parent().hide();
// Hide the right-side toolbar on readonly pads — import/export,
// timeslider, settings, share, users are all noise for viewers
// who can't interact with the pad. Callers who need those
// controls visible on a readonly pad can force them back via
// `?showMenuRight=true`, which runs in getParameters() above.
if (getUrlVars().get('showMenuRight') !== 'true') {
$('#editbar .menu_right').hide();
}
// The right-side toolbar stays visible on readonly pads. The
// server-side `toolbar.menu(buttons, isReadOnly)` (see
// src/node/utils/toolbar.ts) already strips `savedrevision`, and
// `.readonly .acl-write { display: none }` hides the Import column
// inside the import/export popup, so the remaining controls
// (export, timeslider, settings, embed, home, showusers) are all
// safe for readonly viewers — and the userlist is the surface that
// plugins like ep_guest hang their "Log In" button off, so hiding
// it traps guests in readonly with no way out. Iframe-embed use
// cases that want a clean look (issue #5182) opt in to the hide
// via `?showMenuRight=false`, or hide the whole editbar via
// `?showControls=false`.
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Action required

1. Readonly shows menu_right toolbar 📎 Requirement gap ⛨ Security

The PR changes the default behavior so #editbar .menu_right remains visible on read-only pads.
This violates the requirement that read-only pads (especially iframe/embed) must not expose the
menu_right toolbar options.
Agent Prompt
## Issue description
The compliance requirement states that when a pad is opened in read-only mode (especially embedded via iframe), the `menu_right` toolbar must not be visible. The current PR explicitly keeps `#editbar .menu_right` visible on readonly pads by default, and the frontend test suite was updated to assert that visibility.

## Issue Context
To comply, readonly pads should hide `#editbar .menu_right` by default, while still allowing explicit overrides via the existing `showMenuRight` URL parameter.

## Fix Focus Areas
- src/static/js/pad.ts[785-803]
- src/tests/frontend-new/specs/hide_menu_right.spec.ts[47-67]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

@JohnMcLear JohnMcLear merged commit 8c4f974 into develop May 16, 2026
31 checks passed
@JohnMcLear JohnMcLear deleted the fix/readonly-menu-right-overhide branch May 16, 2026 16:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant