Thomas Trompette a747e62970 fix(workflow): use as draft with an existing draft and cross-object record page filters (#23524)
Fixes two workflow issues.

### "Use as draft" fails when a draft already exists

`UseAsDraftWorkflowVersionSingleRecordCommand` rendered its own
`OverrideWorkflowDraftConfirmationModal`. Headless commands are
unmounted by `HeadlessEngineCommandWrapperEffect` as soon as `execute`
resolves, so the modal was removed from the tree right after `openModal`
was called and the user saw nothing happen. This regressed when the
command was converted from a rendered `<Command onClick>` to a
self-unmounting effect.

The command now uses `HeadlessConfirmationModalEngineCommandEffect`, the
existing mechanism for headless commands that need a confirmation: it
opens the app-wide `CommandMenuConfirmationModalManager` and keeps the
command mounted until the modal emits its result.
`OverrideWorkflowDraftConfirmationModal`, its modal id and its config
state are deleted.

To keep the "Go to Draft" shortcut, the shared confirmation modal config
gains an optional `linkButton` rendered as a secondary link button that
emits a `cancel` result on click.

The command also resolved the workflow id through `useWorkflowVersion`,
which is `undefined` while the query is in flight, so it threw and
surfaced an error snackbar through the command error boundary. It now
reads the workflow id off the selected record like the sibling workflow
version commands, and waits for the workflow to load before deciding
whether a confirmation is needed.

### `workflow object doesn't have any "workflowId" field` when opening a
workflow from a version

`useRecordShowPagePagination` builds prev/next queries from the parent
view stored in `contextStoreRecordShowParentViewComponentState`.
Navigating from a workflow version record page to its workflow through
the relation chip keeps the workflow version parent view, whose relation
filter compiles to `workflowId: { in: [...] }` and is then sent against
the `workflow` object, which the API rejects.

`useQueryVariablesFromParentView` now ignores the parent view when
`parentViewObjectNameSingular` does not match the current object, which
covers every navigation path between record pages of different objects.

### Test

Added `useQueryVariablesFromParentView.test.tsx` covering both the
matching and mismatching parent view object.

Manually checked on a local instance: override with an existing draft,
"Go to Draft", cancel then re-trigger, and the no-existing-draft path,
plus navigating from a filtered workflow versions view to a workflow.

---------

Co-authored-by: Tom <tom@twenty.com>
2026-07-30 16:45:25 +00:00
2026-06-11 11:02:28 +02:00

Twenty logo

The #1 Open-Source CRM

Website · Documentation · Roadmap · Discord · Figma

Twenty banner


Why Twenty

Twenty gives technical teams the building blocks for a custom CRM that meets complex business needs and quickly adapts as the business evolves. Twenty is the CRM you build, ship, and version like the rest of your stack.

Learn more about why we built Twenty


Installation

Cloud

The fastest way to get started. Sign up at twenty.com and spin up a workspace in under a minute, with no infrastructure to manage and always up to date.

Build an app

Scaffold a new app with the Twenty CLI:

npx create-twenty-app my-app

Define objects, fields, and views as code:

import { defineObject, FieldType } from 'twenty-sdk/define';

export default defineObject({
  nameSingular: 'deal',
  namePlural: 'deals',
  labelSingular: 'Deal',
  labelPlural: 'Deals',
  fields: [
    { name: 'name', label: 'Name', type: FieldType.TEXT },
    { name: 'amount', label: 'Amount', type: FieldType.CURRENCY },
    { name: 'closeDate', label: 'Close Date', type: FieldType.DATE_TIME },
  ],
});

Then ship it to your workspace:

npx twenty app:publish --private

See the app development guide for objects, views, agents, and logic functions.

Self-hosting

Run Twenty on your own infrastructure with Docker Compose, or contribute locally via the local setup guide.



Everything you need

Twenty gives you the building blocks of a modern CRM (objects, views, workflows, and agents) and lets you extend them as code. Here's a tour of what's in the box.

Want to go deeper? Read the User Guide for product walkthroughs, or the Documentation for developer reference.

Create your apps

Learn more about apps in doc

Stay on top with version control

Learn more about version control in doc

All the tools you need to build anything

Learn more about primitives in doc

Customize your layouts

Learn more about layouts in doc

AI agents and chats

Learn more about AI in doc

Plus all the tools of a good CRM

Learn more about CRM features in doc


Stack

Thanks

Greptile      Sentry      Crowdin

Thanks to these amazing services that we use and recommend for code review (Greptile), catching bugs (Sentry) and translating (Crowdin).

Join the Community

Star the repo · Discord · Feature requests · Releases · X · LinkedIn · Crowdin · Contribute

S
Description
The open alternative to Salesforce, designed for AI.
Readme AGPL-3.0 1.4 GiB
Languages
TypeScript 79.6%
MDX 17.3%
JavaScript 2.7%
Python 0.2%
SCSS 0.1%