Skip to content

[solidus_admin] Add force_legacy_admin_proc preference to route individual requests to the legacy admin - #6601

Merged
AlistairNorman merged 1 commit into
solidusio:mainfrom
SuperGoodSoft:preference-for-forcing-legacy-ui
Nov 4, 2026
Merged

AlistairNorman merged 1 commit into
solidusio:mainfrom
SuperGoodSoft:preference-for-forcing-legacy-ui

Conversation

@Noah-Silvera

@Noah-Silvera Noah-Silvera commented Sep 9, 2026 •

Copy link
Copy Markdown
Contributor

What this adds

A new SolidusAdmin::Config.force_legacy_admin_proc preference. It receives the Rack request and returns whether that request should be served by the legacy admin (solidus_backend) instead of SolidusAdmin.

Until now the only switch was all-or-nothing: the solidus_admin=false cookie or query param. Stores that have heavily customized some legacy admin pages couldn't adopt the new admin at all. With this, you can send just the pages you haven't ported back to the legacy admin and use the new admin everywhere else.

It defaults to never forcing the legacy admin, so nothing changes unless you opt in.

Upgrading

New installs (solidus_admin:install) get everything automatically.

Existing apps need a one-time edit, because rerunning the generator adds a second SolidusAdmin mount instead of replacing the existing one. Apply this change to the SolidusAdmin::Engine mount in config/routes.rb (line numbers will differ in your app):

--- a/config/routes.rb
+++ b/config/routes.rb
@@
 mount SolidusAdmin::Engine, at: '/admin', constraints: ->(req) {
   req.cookies['solidus_admin'] != 'false' &&
-  req.params['solidus_admin'] != 'false'
+  req.params['solidus_admin'] != 'false' &&
+  !SolidusAdmin::Config.force_legacy_admin_proc.call(req)
 }

If you already customized the constraint, add !SolidusAdmin::Config.force_legacy_admin_proc.call(req) to your own logic. Until you do, setting the preference has no effect.

Using it

# config/initializers/solidus_admin.rb
SolidusAdmin::Config.force_legacy_admin_proc = ->(req) {
  req.path.start_with?('/admin/promotions')
}

The cookie and query param still work and take precedence.

Testing locally

This walks through both an existing app that upgrades without touching its routes, and a fresh install. It uses the Docker setup from the root README (docker-compose up -d first). Restart bin/dev after any change to config/routes.rb or config/initializers/, since neither is reloaded.

Throughout, "the two basic tests" are:

  • A. Log in at http://localhost:3000/admin (admin@example.com / test123), open /admin/products and run document.body.className in DevTools. This is the new admin, so the result is 'bg-gray-15 font-sans text-sm'.
  • B. Open /admin/products?solidus_admin=false. This is the legacy admin, so the result is 'admin '.
  1. Baseline on main. Check out main, then build and start the sandbox:

    docker-compose exec app bin/sandbox   # replaces ./sandbox
    docker-compose exec app bin/dev       # http://localhost:3000

    Run tests A and B.

  2. Switch to this branch. The sandbox is gitignored and loads the admin gem from ../admin, so it keeps working. Check out this branch, restart bin/dev, and run tests A and B again. Nothing should change.

  3. Upgrade without touching the routes. The sandbox's mount is now the old one, without the new clause, like an existing app. Add this inside the configure block of sandbox/config/initializers/solidus_admin.rb, restart, and run tests A and B again:

    config.force_legacy_admin_proc = ->(req) { req.path.start_with?("/admin/products") }

    Both results are unchanged: /admin/products is still the new admin. The preference is set but nothing calls it, because the old mount doesn't consult it.

  4. Edit the routes. Add && !SolidusAdmin::Config.force_legacy_admin_proc.call(req) to the constraint of the SolidusAdmin::Engine mount in sandbox/config/routes.rb, as described in "Upgrading" above, and restart. /admin/products now serves the legacy admin ('admin ') without any param, while /admin/stores still serves the new admin.

  5. Fresh install on this branch. Rebuild the sandbox with docker-compose exec app bin/sandbox, start bin/dev, and confirm the generated sandbox/config/routes.rb already has !SolidusAdmin::Config.force_legacy_admin_proc.call(req) in the mount's constraint. Run tests A and B.

  6. Use the proc on the fresh install. Add the force_legacy_admin_proc line from step 3 to the new sandbox's initializer and restart. /admin/products now serves the legacy admin, and no routes edit was needed.

🤖 Generated with Claude Code

@jarednorman jarednorman changed the title WIP: Interface for forcing the legacy UI for certain routes Interface for forcing the legacy UI for certain routes Sep 17, 2026
@Noah-Silvera
Noah-Silvera force-pushed the preference-for-forcing-legacy-ui branch 2 times, most recently from 110cbc6 to da6672e Compare October 14, 2026 17:46
@codecov

codecov Bot commented Oct 14, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 92.58%. Comparing base (f41bf95) to head (daf65d7).

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #6601      +/-   ##
==========================================
+ Coverage   92.48%   92.58%   +0.10%     
==========================================
  Files        1065     1065              
  Lines       21544    21546       +2     
==========================================
+ Hits        19924    19948      +24     
+ Misses       1620     1598      -22     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@Noah-Silvera
Noah-Silvera force-pushed the preference-for-forcing-legacy-ui branch from da6672e to 84fe77d Compare October 14, 2026 18:37
@Noah-Silvera Noah-Silvera changed the title Interface for forcing the legacy UI for certain routes [solidus_admin] Add force_legacy_admin_proc preference to route individual requests to the legacy admin Oct 14, 2026
@Noah-Silvera
Noah-Silvera force-pushed the preference-for-forcing-legacy-ui branch 3 times, most recently from 9db9505 to 3aca0ef Compare October 14, 2026 19:06
@Noah-Silvera
Noah-Silvera marked this pull request as ready for review October 14, 2026 21:00
@Noah-Silvera
Noah-Silvera requested a review from a team as a code owner October 14, 2026 21:00
@jarednorman
jarednorman force-pushed the preference-for-forcing-legacy-ui branch from 3aca0ef to d6669a4 Compare October 15, 2026 19:57
@jarednorman
jarednorman force-pushed the preference-for-forcing-legacy-ui branch from 3aca0ef to d6669a4 Compare October 15, 2026 19:57
@Noah-Silvera
Noah-Silvera force-pushed the preference-for-forcing-legacy-ui branch from d6669a4 to 78e69c5 Compare November 2, 2026 14:46
@github-actions github-actions Bot added changelog:solidus_api Changes to the solidus_api gem changelog:solidus_backend Changes to the solidus_backend gem changelog:solidus_core Changes to the solidus_core gem changelog:solidus_legacy_promotions Changes to the solidus_legacy_promotions gem changelog:solidus_promotions Changes to the solidus_promotions gem changelog:solidus_i18n Changes to the solidus_i18n gem changelog:solidus_storefront Changes to the storefront labels Nov 2, 2026
@Noah-Silvera
Noah-Silvera force-pushed the preference-for-forcing-legacy-ui branch from 78e69c5 to c7b8eb0 Compare November 2, 2026 15:15
Stores with heavily customized legacy admin pages can't move to the new
admin today, because the only switch is the all-or-nothing cookie/param.
This adds a `force_legacy_admin_proc` preference that gets the Rack
request, so an app can send just the pages it hasn't ported back to the
legacy admin. By default it never forces it, so nothing changes unless an
app opts in.

The route constraint lives in the install generator's template, so only new
installs pick it up. Rerunning the generator adds a second mount rather than
replacing the old one, so existing apps have to add the clause to their mount
by hand. The PR description spells that out.

The default is a lambda returning the proc, like `storefront_product_path_proc`,
because Solidus calls a Proc default to build the value.

Co-authored-by: GitHub Copilot <copilot@github.com>
@Noah-Silvera
Noah-Silvera force-pushed the preference-for-forcing-legacy-ui branch from c7b8eb0 to daf65d7 Compare November 2, 2026 15:18
@Noah-Silvera

Copy link
Copy Markdown
Contributor Author

Just pushed to see if I could get the tests to pass

@github-actions github-actions Bot removed the changelog:solidus_api Changes to the solidus_api gem label Nov 2, 2026
@github-actions github-actions Bot removed changelog:solidus_backend Changes to the solidus_backend gem changelog:solidus_core Changes to the solidus_core gem changelog:solidus_legacy_promotions Changes to the solidus_legacy_promotions gem changelog:solidus_promotions Changes to the solidus_promotions gem changelog:solidus_i18n Changes to the solidus_i18n gem changelog:solidus_storefront Changes to the storefront labels Nov 2, 2026
@jarednorman
jarednorman requested a review from a team November 2, 2026 23:53
@Noah-Silvera

Copy link
Copy Markdown
Contributor Author

Checks passed and Jared approves: @AlistairNorman could we merge this one?

@AlistairNorman

Copy link
Copy Markdown
Contributor

Nice work, I think this will really help with adoption

@AlistairNorman
AlistairNorman merged commit ed00fc8 into solidusio:main Nov 4, 2026
42 checks passed
@AlistairNorman
AlistairNorman deleted the preference-for-forcing-legacy-ui branch November 4, 2026 00:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

3 participants