Skip to content

PR 7c - feat(marketplace): preview attempt frontend#8513

Draft
LWS49 wants to merge 9 commits into
lws49/feat-marketplace-pr7b-preview-attemptfrom
lws49/feat-marketplace-pr7c-preview-frontend
Draft

PR 7c - feat(marketplace): preview attempt frontend#8513
LWS49 wants to merge 9 commits into
lws49/feat-marketplace-pr7b-preview-attemptfrom
lws49/feat-marketplace-pr7c-preview-frontend

Conversation

@LWS49

@LWS49 LWS49 commented Jul 24, 2026

Copy link
Copy Markdown
Collaborator

Summary

Phase 3 (frontend) of the marketplace preview attempt, stacked on #8511 (PR7b, the backend serving stack). This adds the frontend for previewing a published marketplace assessment as a real, interactive attempt: an entrance from the listing preview page and from each marketplace index row, the interactive attempt page itself, and a banner marking it as a throwaway preview. The attempt page reuses the real submission editor (SubmissionEditIndex) wholesale, since PR7b deliberately made the preview serving payload shape-compatible with the real submission edit.json. The only new machinery is a small context seam so the reused submission API routes to the shallow /marketplace/attempt/... endpoints, plus the banner and the two entrances. No backend changes.

Design decisions

  • Reuse SubmissionEditIndex wholesale instead of forking it - PR7b's payload is shape-compatible on purpose, and forking would duplicate the ~30-component submission editor and guarantee the two experiences drift.
  • Route the reused submission/scribing APIs to the preview endpoints via a module-level getActivePreview() singleton that swaps the URL prefix to /courses/:c/marketplace/attempt. The swap also triggers whenever the URL carries no assessment id, so a poller firing after the preview page unmounts can never emit a /assessments/null/... request (the fallback the repo's preview note calls for).
  • Set the preview-context singleton synchronously in the route wrapper's render body, not in a useEffect - the reused class component dispatches its fetch in componentDidMount, which runs before a parent component's effects, so an effect would set the flag too late for the first request.
  • Keep the React context and banner in the submission bundle (not marketplace) so the dependency direction stays marketplace -> submission (the marketplace route already imports the submission editor).
  • Provide two entrances (the listing preview page and each marketplace index row), sharing one useStartPreviewAttempt hook for the create -> navigate -> 409-notify flow.

Regression prevention

  • Covers: the getActivePreview singleton lifecycle; submission, scribing, and create-attempt URL routing including the assessments/null fallback (mutation-verified); the preview banner render plus its Reset and Exit actions; the route wrapper's synchronous singleton set, unmount cleanup, and course-context forwarding (mutation-verified); both entrances (create -> navigate on success, notification and no navigation on 409); and the index row play button's position between the preview and duplicate buttons and its callback.
  • The banner also mounts on the shared real-submission edit page and self-hides for non-preview submissions; it reads the course outlet context defensively so it can never throw there, and the route wrapper forwards that context so the reused editor keeps working under the preview route.
  • Backward compatible: the submission API's preview branch is inert on real submission URLs (which always carry an assessment id), and the new onAttempt table prop is optional, so existing submission and marketplace behaviour is unchanged.

@LWS49
LWS49 marked this pull request as draft July 24, 2026 03:50
@LWS49
LWS49 force-pushed the lws49/feat-marketplace-pr7b-preview-attempt branch 2 times, most recently from f850512 to 3900460 Compare July 24, 2026 05:29
@LWS49
LWS49 force-pushed the lws49/feat-marketplace-pr7c-preview-frontend branch from 3312db1 to cc62410 Compare July 24, 2026 05:29
@LWS49
LWS49 force-pushed the lws49/feat-marketplace-pr7b-preview-attempt branch from 3900460 to 46fb69c Compare July 24, 2026 07:22
@LWS49
LWS49 force-pushed the lws49/feat-marketplace-pr7c-preview-frontend branch from cc62410 to 029379d Compare July 24, 2026 07:22
@LWS49
LWS49 force-pushed the lws49/feat-marketplace-pr7b-preview-attempt branch from 46fb69c to 4c04c36 Compare July 24, 2026 07:35
@LWS49
LWS49 force-pushed the lws49/feat-marketplace-pr7c-preview-frontend branch from 029379d to e0ee5b0 Compare July 24, 2026 07:35
@LWS49
LWS49 force-pushed the lws49/feat-marketplace-pr7b-preview-attempt branch from 4c04c36 to bec2ee1 Compare July 24, 2026 07:37
@LWS49
LWS49 force-pushed the lws49/feat-marketplace-pr7c-preview-frontend branch from e0ee5b0 to cde901b Compare July 24, 2026 07:37
@LWS49 LWS49 changed the title feat(marketplace): preview attempt frontend PR 7c - feat(marketplace): preview attempt frontend Jul 24, 2026
@LWS49
LWS49 force-pushed the lws49/feat-marketplace-pr7b-preview-attempt branch from bec2ee1 to a466080 Compare July 24, 2026 09:29
@LWS49
LWS49 force-pushed the lws49/feat-marketplace-pr7c-preview-frontend branch from cde901b to 110dce1 Compare July 24, 2026 09:29
LWS49 added 9 commits July 24, 2026 17:56
A bare <Outlet/> nulls the outlet context, so the reused SubmissionEditIndex
banner would read undefined from useCourseContext() on the preview page (and
throw when destructuring). Forward CourseContainer's context and read it
defensively in the banner.
Add a play (attempt) icon button between the preview eye and duplicate buttons
in each listing row. Extract the create-attempt + navigate + 409-notify flow
into a shared useStartPreviewAttempt hook reused by the listing preview page.
…attempt/null

Preview pages reuse the submission edit UI, but a preview URL has no
/assessments/:aid/submissions segment, so any id derived from the path was null.

- getSubmissionId() also parses /courses/:c/marketplace/attempt/:id, so the
  SubmissionForm pollers and action buttons stop emitting /attempt/null/...
- AnswersAPI routes per-answer saveDraft/submitAnswer to the shallow attempt
  endpoint in preview (same fallback as Submissions.js/Scribing.js).
- Recorder reducer no longer calls stopRecord() when nothing is recording, which
  produced an unhandled 'Recorder has already stopped' rejection on unmount.
@LWS49
LWS49 force-pushed the lws49/feat-marketplace-pr7b-preview-attempt branch from a466080 to 4c28286 Compare July 24, 2026 09:56
@LWS49
LWS49 force-pushed the lws49/feat-marketplace-pr7c-preview-frontend branch from 110dce1 to 2fb3d97 Compare July 24, 2026 09:56
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.

1 participant