Skip to content

feat(ol_openedx_feedback): send a visible title only for blocks that render one - #876

Open
zamanafzal wants to merge 1 commit into
mainfrom
zafzal/13643-feedback-visible-title
Open

zamanafzal wants to merge 1 commit into
mainfrom
zafzal/13643-feedback-visible-title

Conversation

@zamanafzal

@zamanafzal zamanafzal commented Sep 29, 2026 •

Copy link
Copy Markdown
Contributor

What are the relevant tickets?

Part of https://github.com/mitodl/hq/issues/13643

Paired with mitodl/smoot-design#263 — both are needed for the fix to show up.

Description (What does it do?)

The aside sends the block's Studio display_name and the feedback drawer labels itself with it. For most block types that name is never drawn on the page, so learners see internal authoring notes like "Wk3 intro copy - REVISED, do not reuse".

  • Adds a curated block-type → title-field map (DEFAULT_VISIBLE_TITLE_FIELDS) and sends the result as a new visibleTitle field on the ol-feedback::drawer-open payload. It is "" for types that render no title, which is the drawer's cue to name the block type instead.
  • blockDisplayName is unchanged, so the submitted record still carries the Studio name the content team uses to find the component.
  • Bumps the package to 0.3.1 and documents the map in the README.
Implementation details

Most mapped types report display_name. Two don't, because their Studio "name" input writes somewhere else:

  • openassessment renders its own title field.
  • survey renders block_name — the Studio editor writes the name input to block_name (poll/poll.py:1260,1275) and leaves display_name at the class default "Survey". Its template confirms it: survey.html:6 is <h3 class="poll-header">{{block_name}}</h3>.

The two polls are different blocks and land on opposite sides of the map:

  • poll (the third-party poll package) is mapped. poll.html:7 renders <h3 class="poll-header">{{ display_name }}</h3>, and the question lives in a separate question field shown as the fieldset legend.
  • poll_question (the built-in) is not mapped. Its extracted template renders only a hidden JSON config div and the JS draws the question text; display_name never reaches the page.

drag-and-drop-v2's title only renders when the author's show_title toggle is on, so TITLE_VISIBILITY_TOGGLES gates it. A runtime missing the field is treated as hidden rather than assumed visible.

The map keys on the usage-key category. The xblocks-contrib extracted variants register under _<name>_extracted entry points but keep the plain category and render the name the same way, so they need no separate entry.

Types outside the map report no visible title on purpose. Omitting one costs generic wording in the panel; adding a wrong one leaks an author's private note.

The map is a constant, not a setting. An operator-settable version can only widen what the panel shows, which is the leak this PR exists to close, and each entry is a claim about what a block draws on the page — that belongs in reviewed code. get_visible_title still type-checks the value it reads, because most of the mapped blocks ship in third-party packages that can redefine a field in any release, and this runs inside student_view_aside where a raise breaks the learner's page rather than just the panel.

Screenshots (if appropriate):

Full-page shots from a Tutor LMS, one per map case, with the companion smoot bundle deployed. The red outline marks the block whose 📣 was clicked; the drawer is in the right sidebar, so each shot shows both what the block draws on the page and what the aside told the panel to say.

Video — mapped to display_name. The name is on the page as a heading, so sending it is safe.

Courseware unit with a video block outlined; panel reads 'What kind of feedback do you have about Lecture 3: Recursion?'

Problem — mapped to display_name. Same, with the name rendered above the choices.

Problem block headed 'Quiz 1: Base cases' outlined; panel reads 'What kind of feedback do you have about Quiz 1: Base cases?'

poll (third-party) — mapped. This is the evidence for mapping poll but not poll_question: the <h3> is display_name ("WHICH APPROACH DID YOU PREFER?") and the question field is separate below it ("What is your favorite color?").

Poll block whose heading is 'WHICH APPROACH DID YOU PREFER?' with a separate question below; panel reads 'What kind of feedback do you have about Which approach did you prefer?'

survey — mapped to block_name, not display_name. The heading is block_name, and that's what the panel names.

Survey block headed 'END OF WEEK CHECK-IN' outlined; panel reads 'What kind of feedback do you have about End of week check-in?'

Text block — not mapped. Its Studio name is Wk3 intro copy - REVISED, do not reuse; the block renders only its body text. The name is on neither the page nor the panel.

HTML block rendering only its body text, outlined; panel reads 'What kind of feedback do you have about this text?' with no Studio name anywhere

poll_question (built-in) — not mapped. It draws its question text, so the aside withholds the title and the drawer names the type.

Built-in poll block outlined; panel reads 'What kind of feedback do you have about this poll?'

Problem with a blank Studio name. A mapped type with a blank name reports no visible title rather than an empty one.

Problem block with no heading, outlined; panel reads 'What kind of feedback do you have about this problem?'

Unmapped type. done is outside the map, so no title is sent and the drawer falls back to generic wording.

'Mark as complete' done block outlined; panel reads 'What kind of feedback do you have about this content?'

How can this be tested?

  • Install the plugin in the LMS and enable the ol_openedx_feedback.feedback_enabled CourseWaffleFlag (globally or per course). The panel wording also needs the companion smoot bundle (mitodl/smoot-design#263) deployed in the Learning MFE — an older bundle ignores visibleTitle and keeps showing the Studio name.

  • Author a unit with one block per case: a video named in Studio, a text/HTML block, and a built-in poll. Give the text block a deliberately author-only name like Wk3 intro copy - REVISED, do not reuse so a leak is obvious.

  • Open the unit as a signed-in learner and click the 📣 on each block:

    1. Title path — the video panel reads What kind of feedback do you have about <the video's title>?
    2. Fallback path — the text block reads "…about this text?" and the poll "…about this poll?", with no Studio name anywhere in the panel.
    3. Record unchanged — submit from the text block and confirm the mit-learn row still has block_display_name set.
  • Automated: pytest src/ol_openedx_feedback/tests — 50 pass. test_utils.py covers each mapped field, the show_title toggle, lazy translation proxies, and a non-string title; test_aside.py asserts the payload carries visibleTitle for a video and withholds it for an html block while still sending blockDisplayName.

    Inside a Tutor dev container that command needs --ds=lms.envs.test. The container exports DJANGO_SETTINGS_MODULE=lms.envs.tutor.development, and pytest-django ranks the environment variable above the DJANGO_SETTINGS_MODULE in this package's setup.cfg, so collection otherwise fails on COMMON_TEST_DATA_ROOT:

    docker exec <lms-container> bash -c \
      "cd /openedx/src/open-edx-plugins/src/ol_openedx_feedback && \
       python -m pytest tests -q --ds=lms.envs.test"

Run on a Tutor LMS against a test course with a section per case — the screenshots above are that run, one shot per case. drag-and-drop-v2's show_title toggle, lazy translation proxies and non-string titles are covered by unit tests only.

Additional Context

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.

Copilot review overview

🟡 Changes recommended

Several newly curated title mappings are not covered by the parameterized mapping test.

Review effort: Balanced
Findings: 1 Medium severity

Open (1)
What changed in this PR

Adds learner-visible XBlock titles to the feedback payload while retaining Studio names for submissions.

Changes:

  • Adds curated title-field mapping and visibility handling.
  • Sends visibleTitle and expands tests/documentation.
  • Bumps the plugin to 0.3.1.
File Description
uv.lock Updates locked plugin version.
src/​ol_openedx_feedback/​tests/​utils.py Adds an HTML block fixture.
src/​ol_openedx_feedback/​tests/​test_utils.py Tests visible-title resolution and overrides.
src/​ol_openedx_feedback/​tests/​test_aside.py Verifies emitted payload titles.
src/​ol_openedx_feedback/​README.rst Documents title behavior and configuration.
src/​ol_openedx_feedback/​pyproject.toml Bumps package version.
src/​ol_openedx_feedback/​ol_openedx_feedback/​utils.py Implements safe title resolution.
src/​ol_openedx_feedback/​ol_openedx_feedback/​constants.py Defines title mappings and visibility toggles.
src/​ol_openedx_feedback/​ol_openedx_feedback/​block.py Adds visibleTitle to drawer events.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/ol_openedx_feedback/tests/test_utils.py Outdated
@zamanafzal
zamanafzal marked this pull request as ready for review September 30, 2026 09:11
@zamanafzal
zamanafzal requested a balanced review from Copilot September 30, 2026 11:25

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.

Copilot review overview

🔵 Needs a closer look

The privacy-sensitive mapping depends on upstream rendering behavior that requires human verification, and two documentation claims need correction.

Review effort: Balanced
Findings: 1 Low severity

Open (1)
Resolved since last review (1)
Previously missed (1)

In code that hasn't changed since last review

Low severity Require compatible drawer clients to enforce hidden display names

src/​ol_openedx_feedback/​README.rst:19

The “never shown” guarantee is not enforced by this plugin: blockDisplayName is still sent to the learner’s browser, and the currently deployed drawer reads this field until the paired smoot-design change is deployed. Phrase this as a requirement for compatible drawer clients so the documentation remains accurate during the documented staggered rollout.

Comment thread src/ol_openedx_feedback/ol_openedx_feedback/block.py Outdated
…render one

For most block types display_name is an authoring label that never appears on
the learner's page ("Wk3 intro copy - REVISED, do not reuse"), so the feedback
drawer was naming blocks with text only the author was meant to see.

The payload now carries `visibleTitle`, set from a curated map of the types
that do draw a title and the field holding it — display_name for most, `title`
for openassessment, `block_name` for survey. A type outside the map sends "",
which the drawer renders as generic block-type wording. drag-and-drop-v2 is
gated on its author-controlled `show_title` toggle.

blockDisplayName is still sent, so the submission keeps recording the Studio
name for the content team.

Each map entry asserts that the type draws that field on the learner's page, so
a wrong entry leaks the author's private note — which is the bug the map exists
to prevent. It is therefore deliberately not a deployment setting, every entry
was verified against the rendering template, and a test fails if a new
display_name entry ships uncovered.
@zamanafzal
zamanafzal force-pushed the zafzal/13643-feedback-visible-title branch from 6c1ca98 to d6d522b Compare October 1, 2026 06:24
@arslanashraf7 arslanashraf7 self-assigned this Oct 1, 2026
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.

3 participants