Skip to content

script actions can only redirect to a NEW TAB — the redirectUrl convention has no same-tab (SPA route) form #9566

Description

@baozhoutao

Current behavior

When a server-side action handler returns { redirectUrl }, objectui's consoleServerAction.ts (the one place the /api/v1/actions/... response is interpreted for navigation) has exactly two paths:

  • with opensInNewTab: true — the pre-opened spinner tab is driven to the URL (popup-safe, works well);
  • without it — window.open(url, '_blank') after the awaited POST, where the user-gesture context is already gone, so the popup blocker fires almost every time and the user is left with the “Popup blocked” toast fallback.

A same-tab navigation exists only as the error fallback when the pre-opened tab handle has gone stale (window.location.href = url). There is no way for an author or a handler to ask for it: ActionSchema is strict and has no post-success navigation key (redirect / onSuccess / navigate are all rejected), and openIn applies to type:'url' only.

References: spec opensInNewTab/newTabUrl (#1787, in packages/spec/src/ui/action.zod.ts); redirectUrl convention fixed by objectui#2967 and consolidated in objectui#2904 (packages/app-shell/src/utils/consoleServerAction.ts). All shipped in spec/console@17.0.0.

Why this matters

“Server-side action completes → take the user to the resulting record” is the standard ask for copy/clone/generate-style actions. Real case: steedos-labs/os-project-titanwind-ehr#1172 — a “copy as new version” record-header button clones a v+1 draft, but the user is left on the old record and has to re-filter the list to find the new one. The new-tab form is a workable interim, but the natural UX is an in-place jump.

Ask

  1. Same-tab form for the redirectUrl convention. Let the handler (or the action metadata) express it — e.g. handler returns { redirectUrl, openIn: 'self' }, or an ActionSchema key — and have the console perform an SPA route navigation (no full page load, immune to popup blocking).
  2. (Companion) client-side routing convention. Today the handler must hand-build the console route (/apps/<appId>/<object>/…), leaking the console's URL scheme into every app's server code. A convention like “handler returns { recordId, objectName } and the client routes to that record's detail page” keeps route knowledge where it belongs.

Either half alone is not enough for the case above: (1) without (2) still hard-codes routes server-side; (2) without (1) still lands in a new tab.

Acceptance

A type:'script' action whose handler returns the designated shape navigates the CURRENT tab to the target record's detail page via the SPA router — no full reload, no popup-blocker interaction.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions