Open external links in new tabs (#48) #49
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "fix/target-blank-and-board-work"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
button_towithtarget="_blank"cardcontrollertarget="_blank" rel="noopener noreferrer"Changes
app/views/links/_link.html.erb: Addtarget: "_blank"to click-tracking form, addtarget/relto repo link, wire card body tocardStimulus controller for details navigationapp/views/links/show.html.erb: Addtarget: "_blank"to click-tracking form, addtarget/relto repo linkapp/javascript/controllers/card_controller.js: New Stimulus controller — navigates to show page on card body click, ignores clicks on interactive elements (links, buttons, forms, drag handle)Test Plan
Review Checklist
Related Notes
ldraney/palinks #48— the Forgejo issue this PR implementsproject-palinks— project pageCloses #48
PR #49 Review
DOMAIN REVIEW
Tech stack: Ruby on Rails (ERB views), development config.
View changes (
_link.html.erb,show.html.erb):The
target: "_blank", rel: "noopener noreferrer"additions to external links are correct security practice. Therel="noopener noreferrer"prevents reverse tabnapping. No issues with the attribute additions themselves.However, the changes go beyond adding
target="_blank"-- they reverse behavioral decisions from PR #44 (merged, Closes #43):_link.html.erbline 13: PR #44 deliberately changed card titles fromlink_to link.title, link.urltolink_to link.title, link_path(link)so card titles navigate to the show page. This PR reverts that tolink_to link.title, link.url, target: "_blank"-- now card titles open the external URL directly in a new tab. The show page becomes unreachable from the card title.show.html.erblines 4-5: PR #44 added a dedicated "Visit" button (link_to "Visit", @link.url, target: "_blank", rel: "noopener noreferrer", class: "btn btn-primary") as the intentional entry point for the external URL. This PR removes that button entirely and makes the<h1>title a clickable link to the external URL. This is a UX regression -- users lose the explicit "Visit" CTA, and the clickable title is less discoverable than a button.If the intent is to reverse PR #44's approach entirely, that should be stated explicitly in the PR description and the parent issue. The current description says "Add
target="_blank"" which understates the behavioral scope.config/environments/development.rb:Removes
config.hosts << "palinks-dev.tail5b443a.ts.net"-- this was added in PR #46 (merged, Closes #45). This removal is unrelated to issue #48 (target="_blank" for external links).docs/custom-domain.md:Complete rewrite from spike format to architecture summary (153 deletions, 33 additions). This was the scope of PR #47 (merged). This change is unrelated to issue #48.
BLOCKERS
Scope creep -- stale changes from prior PRs leaked into this branch. Two of four changed files (
config/environments/development.rbanddocs/custom-domain.md) are unrelated to issue #48. Thedevelopment.rbchange reverses PR #46, and thedocs/custom-domain.mdchange duplicates PR #47. This strongly indicates the branch was created from a stale local main that was not synced with the Forgejo remote after those PRs merged. The PRmergeablefield isfalse, confirming merge conflicts exist. These unrelated changes must be removed from this PR.Undisclosed behavioral regression of PR #44. The
_link.html.erbchange reverts the card-title-to-show-page navigation introduced by PR #44. Theshow.html.erbchange removes the "Visit" button PR #44 added. If this reversal is intentional, it needs explicit acknowledgment in the PR description and issue #48. If unintentional, the card title should remainlink_path(link)(navigating to the show page), and the show page should keep the "Visit" button while addingtarget="_blank"to the repo link.No test coverage. No view tests, system tests, or integration tests exist for the new-tab behavior. The repo has only one test file (
test/controllers/links_controller_sort_test.rb). Given that this is the third PR touching the same link navigation behavior (#43/#44 -> now #48/#49), at minimum a system test confirming external links open in new tabs would prevent future regressions.NITS
fix/target-blank-and-board-workreferences "board work" which is not reflected in the PR changes. Branch names should match the PR scope.development.rbordocs/custom-domain.md, confirming these are unintended inclusions.SOP COMPLIANCE
mergeable: falseindicates conflicts with mainPROCESS OBSERVATIONS
This is a textbook case of the stale-local-main problem. The branch was created before fetching the latest main from the remote, so it carries forward changes that have already been merged via PRs #46 and #47. The fix is to rebase this branch onto current main, which will drop the already-merged hunks and resolve the merge conflict. After rebase, only the view file changes should remain.
The repeated churn on link navigation (issue #43 -> PR #44 -> now issue #48 -> PR #49 partially reverting #44) suggests the UX intent is not fully settled. A clear decision on "do card titles go to the show page or directly to the external URL?" should be made before this merges, and a system test should lock in that decision.
VERDICT: NOT APPROVED
a465a26217to75b413149ePR #49 Review (Re-review)
DOMAIN REVIEW
Stack: Rails 8 (ERB views, Stimulus JS, vanilla CSS). Three files changed: one new Stimulus controller, two view template updates. Clean, focused diff -- 15 additions, 5 deletions across 3 files.
Stimulus controller (
card_controller.js):static values = { url: String }) for the navigation URL.event.target.closest("a, button, form, .link-card-handle")guard is well-chosen -- it covers all interactive children: the titlebutton_to(renders a<form>with a<button>), the "Edit"<a>, the "Delete"<form>, the repo<a>, and the drag handle. This prevents the card click from hijacking those actions.window.location.hreffor same-app navigation is appropriate here since the target islink_path(link)(the Rails show route), not an external URL.eagerLoadControllersFrominindex.js-- no manual registration needed.View changes (
_link.html.erb):data-controller="card"/data-card-url-value/data-action="click->card#navigate"are correct Stimulus wiring on the.link-card-bodydiv.target: "_blank"on thebutton_toform is the correct approach --button_togenerates a<form>, andtargeton the<form>tag controls where the form submits. The POST toclick_link_pathwill fire in a new tab, and theClicksController#createredirect tolink.urlwill land in that new tab. Click tracking is preserved.rel: "noopener noreferrer"on external repo links is correct security practice.View changes (
show.html.erb):target: "_blank"andrel: "noopener noreferrer"patterns applied consistently to the show page. Good -- no duplication of logic, just consistent attribute additions.Interaction with sortable controller:
.link-card(the parent), while the new card controller binds click on.link-card-body(a child). Theclosest(".link-card-handle")guard in the card controller prevents click-to-navigate from firing when the drag handle is clicked. The HTML5 drag events on the parent card won't conflict with the click handler on the body since drag events and click events are distinct. This is a clean separation.BLOCKERS
None.
closest()guard. The existing test suite covers server-side click tracking (clicks_controller_test.rb). The PR's test plan lists 9 manual verification steps covering all interaction paths. For a controller this simple, the lack of JS unit tests is not a blocker -- it would be scope creep to introduce a JS test framework for this alone.link_path(link), a Rails route helper (server-generated, trusted).NITS
Inline style:
style="cursor: pointer;"on the.link-card-bodydiv would be cleaner as a CSS rule. The stylesheet already usescursor: pointerin six places via classes. Adding.link-card-body { cursor: pointer; }toapplication.csswould be more consistent. Non-blocking -- it works as-is and is a single instance.Accessibility: The clickable card body has no keyboard support --
cursor: pointersignals clickability visually, but keyboard users cannot tab to or activate it. Consider addingtabindex="0"and akeydown->card#navigateaction (filtering for Enter/Space) in a follow-up. Not a blocker for this PR since the title link and all action buttons remain individually keyboard-accessible -- the card click is a convenience shortcut, not the only path.SOP COMPLIANCE
PROCESS OBSERVATIONS
target: "_blank"on the form element.sortable_controller.js-- same import style, same arrow function binding pattern.VERDICT: APPROVED