feat(marketplace): destination tab picker and completion feedback - #8487
Merged
LWS49 merged 3 commits intoJul 31, 2026
Merged
Conversation
LWS49
force-pushed
the
lws49/feat-marketplace-pr5-preview
branch
2 times, most recently
from
July 17, 2026 07:14
a31b07a to
85ab1fc
Compare
LWS49
force-pushed
the
lws49/feat-marketplace-pr5b-misc
branch
from
July 17, 2026 07:27
2fce896 to
a3e493d
Compare
LWS49
force-pushed
the
lws49/feat-marketplace-pr5-preview
branch
from
July 17, 2026 08:11
85ab1fc to
a7086e3
Compare
LWS49
force-pushed
the
lws49/feat-marketplace-pr5b-misc
branch
2 times, most recently
from
July 17, 2026 08:14
3bc206d to
909976b
Compare
LWS49
marked this pull request as ready for review
July 17, 2026 08:14
LWS49
force-pushed
the
lws49/feat-marketplace-pr5-preview
branch
8 times, most recently
from
July 30, 2026 17:18
2f5f481 to
3d472f2
Compare
Base automatically changed from
lws49/feat-marketplace-pr5-preview
to
lws49/feat-marketplace-pr1-foundation
July 31, 2026 04:49
LWS49
force-pushed
the
lws49/feat-marketplace-pr5b-misc
branch
3 times, most recently
from
July 31, 2026 05:28
f936a7a to
c99120e
Compare
Contributor
There was a problem hiding this comment.
Pull request overview
This PR completes the marketplace listing duplicate/preview flow by letting users choose the destination assessment tab at duplication time, and by improving UX feedback (preview badging + completion toast with link) after the duplication job finishes.
Changes:
- Add a
DestinationTabPickerand wireDuplicateConfirmationto acceptdestinationTabs+initialDestinationTabId, preserving user selection while open and re-seeding on reopen. - Move “duplication completed” feedback to the job poller completion callback, including an optional link to the duplicated assessment’s landing tab.
- Add preview-page “Preview” badging and route
/marketplace/listings→ marketplace index redirect; extend listing show payload to include destination tabs.
Reviewed changes
Copilot reviewed 18 out of 18 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| spec/controllers/course/assessment/marketplace/listings_controller_spec.rb | Adds coverage to ensure listing show returns destinationTabs for the UI picker. |
| client/locales/en.json | Adds/updates strings for preview badge, tab picker, and completion/failure toasts. |
| client/locales/ko.json | Adds/updates strings for preview badge, tab picker, and completion/failure toasts. |
| client/locales/zh.json | Adds/updates strings for preview badge, tab picker, and completion/failure toasts. |
| client/app/routers/course/marketplace.tsx | Redirects bare listings route back to the marketplace index. |
| client/app/lib/hooks/toast/toast.tsx | Widens toast message typing to accept ReactNode (to support link-in-toast). |
| client/app/bundles/course/marketplace/types.ts | Extends listing preview data type to include destinationTabs. |
| client/app/bundles/course/marketplace/translations.ts | Adds new marketplace i18n keys (picker label, completion/failure copy, view link). |
| client/app/bundles/course/marketplace/pages/MarketplaceIndex/index.tsx | Passes destinationTabs and initial tab id into the duplicate dialog (no longer pre-resolving a fixed destination). |
| client/app/bundles/course/marketplace/pages/ListingPreview/index.tsx | Adds a “Preview” chip in the page title and wires duplicate dialog to listing-provided destinationTabs. |
| client/app/bundles/course/marketplace/pages/ListingPreview/test/index.test.tsx | Updates fixtures for destinationTabs and adds a test asserting the preview badge. |
| client/app/bundles/course/marketplace/components/DuplicateConfirmation.tsx | Implements tab selection UI + job-completion toast/link; shows duplicating list with badges/tooltips. |
| client/app/bundles/course/marketplace/components/DestinationTabPicker.tsx | New component: category-grouped tab radio picker. |
| client/app/bundles/course/marketplace/components/test/DuplicationConfirmation.test.tsx | Adds extensive behavioral tests for selection seeding/preservation, job polling toasts, locking, and redirect link behavior. |
| client/app/bundles/course/marketplace/components/test/DestinationTabPicker.test.tsx | Tests category grouping, ordering, controlled selection, and onChange wiring. |
| client/app/bundles/course/duplication/components/TypeBadge/index.tsx | Adds dense option to support compact badges in marketplace UI. |
| app/views/course/assessment/marketplace/listings/show.json.jbuilder | Emits destinationTabs in listing show JSON. |
| app/controllers/course/assessment/marketplace/listings_controller.rb | Populates @destination_tabs for show to support the new JSON payload. |
Suppressed comments (1)
client/locales/zh.json:6130
- The Simplified Chinese toast strings end with an ASCII period ("."), while nearby strings consistently use the Chinese full stop ("。"). This reads like a localization regression in the UI.
"course.marketplace.duplicateFailed": {
"defaultMessage": "{n, plural, one {无法复制评估} other {无法复制评估}}."
},
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Replace the static destination summary with an in-dialog tab picker and report duplication results honestly: - Add DestinationTabPicker, a radio tree grouping the current course's tabs by category, so the duplicator chooses the destination tab inside the dialog instead of it being fixed by the launching `from_tab`. The selection seeds from `from_tab` (falling back to the first tab) and re-seeds on each reopen, but a parent re-render never resets a choice mid-decision. - Serve `destinationTabs` from the listing show endpoint too, so the picker is available when duplicating from the listing detail page, not just the marketplace index. - Restyle the dialog: vertically stacked tabs with larger category/tab text, a dense TypeBadge variant, an explicit "Duplicating" heading, the ⊘ "arrives unpublished" hint, and explicit cancel/primary colors. - Report a *completed* duplication (the toast fires from pollJob's completion callback, not on submit) and link to where the copy landed via the job's redirectUrl; reword the failure copy to plain language. Widen the shared toast Toaster type to ReactNode so the toast can carry that link (type-only change, no runtime effect).
`marketplace/listings` with no listing id matched no route and 404'd. Add a redirect so it lands on the same page as `marketplace/`.
Add a "Preview" chip beside the title on the read-only listing detail page, so it is never mistaken for the real assessment it mirrors.
LWS49
force-pushed
the
lws49/feat-marketplace-pr5b-misc
branch
from
July 31, 2026 08:13
c99120e to
84a3f69
Compare
LWS49
merged commit Jul 31, 2026
4cc2c6d
into
lws49/feat-marketplace-pr1-foundation
1 of 8 checks passed
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.
Summary
This rounds out the preview/duplicate flow from the parent PR. The duplicate confirmation dialog now lets the user actively pick the destination category/tab via a new
DestinationTabPicker, instead of just displaying whichever tab they happened to arrive from. Completion feedback is upgraded to report once the duplication job actually finishes, with a link to where the assessment landed, instead of a fire-and-forget "started" toast. The listing preview page is badged so it's never mistaken for the real assessment it mirrors, and a bare/marketplace/listingsnow redirects to the marketplace index instead of 404ing.Design decisions
DuplicateConfirmationnow takes the fulldestinationTabslist and aninitialDestinationTabId, letting the user change the destination tab instead of being locked into the one they arrived from; the initial selection still defaults to thefrom_tabtab when it names a real tab, falling back to the course's first tab otherwise.pollJob's completion callback and links to the duplicated assessment (redirectUrl), since the previous "Duplicating assessment started." toast fired on job submission and gave no way to find the result afterward.[open]as the sole effect dependency), not on every parent re-render, so an in-progress tab choice isn't reset out from under the user while the dialog stays open.Regression prevention
Tests cover:
DestinationTabPicker's category grouping (including tabs arriving non-contiguously) and its selection wiring; the tab-selection reset-on-reopen vs. preserve-while-open behaviour; the completion and failure toast copy and the redirect link; the dialog locking/unlocking around an in-flight job so it can't be double-submitted or abandoned mid-job; thedestinationTabsnow returned from the listing show endpoint; the/marketplace/listingsredirect; and the listing preview page's "Preview" badge.Manual testing covered picking a different destination tab before confirming, the completion toast and its link after a duplication job finishes, a failed duplication leaving the dialog open for retry, and the bare
/marketplace/listingsredirect.