Skip to content

[6.x] Save each draft once per autosave and keep its menus - #20649

Merged
riasvdv merged 2 commits into
6.xfrom
rias/cms-2685-6x-each-draft-autosave-blocks-the-entry-editor
Nov 12, 2026
Merged

riasvdv merged 2 commits into
6.xfrom
rias/cms-2685-6x-each-draft-autosave-blocks-the-entry-editor

Conversation

@riasvdv

@riasvdv riasvdv commented Nov 12, 2026

Copy link
Copy Markdown
Contributor

Description

Each autosave of a provisional draft sent a second save-draft with no fields, and rebuilt every action menu item on the page.

 pause in typing
   ├─ save-draft (fields)
   └─ update-field-layout            # custom fields are reactive
        └─ renderer re-applies the unsaved values it was asked to render
-            → counted as a new edit → save-draft (no fields)
+            → identical to the last mutation, so not an edit

 action menu items sent to the client
-  id: $item['id'] ?? 'menu-item-'.mt_rand()     # new on every render
+  id: $item['id'] ?? null                       # the HTML path still mints its own
 card menus (ElementHtml::elementCardActionItems)
-  keep their items' mt_rand() IDs (action-copy-…, action-view-…)
+  drop them once they've been filtered on, as Ui\Nodes\ActionMenu does

ActionList keys items by their id, so a new id on every response made Vue recreate the items in each closed menu.

Evidence

Workbench Matrix Playground "Populated views" entry, with a provisional draft. Headless Chromium, one character typed, then a pause:

Requests per autosave Long tasks craft-action-items removed and re-added
Before save-draft, update-field-layout, save-draft (no fields) 184–204ms 522
After save-draft, update-field-layout 68–125ms 1

These numbers come from an earlier version of this fix that changed ActionList's keying on the client instead of the server IDs; the server version wasn't measured in the browser. Edited values were still there after a reload.

useElementEditor.test.ts
  saves a draft once when the layout refresh for the same edit lands first
    6.x:  2 save-draft calls    this PR: 1

NestedElementManagerTest.php
  sends the same card menu each time the card is rendered
    6.x:  action-view-1800827766 ≠ action-view-809652481, menu-item-… ≠ menu-item-…    this PR: identical

Related issues

riasvdv and others added 2 commits November 12, 2026 21:50
When a layout refresh answers, the renderer emits the unsaved values it
was asked to render. The editor counted that as a new edit and saved the
draft a second time, with nothing left to save.

Amp-Thread-ID: https://ampcode.com/threads/T-01a1d198-13ad-7182-b555-18b8fcbf088e
Co-authored-by: Amp <amp@ampcode.com>
Menu items without an ID were given a random one for the client, and card
menus kept the random IDs their items were made with. Every response that
sent the same menu again, such as each autosave, made the client recreate
all of its items. The HTML path still mints its own IDs.

Amp-Thread-ID: https://ampcode.com/threads/T-01a1d198-13ad-7182-b555-18b8fcbf088e
Co-authored-by: Amp <amp@ampcode.com>
@linear-code

linear-code Bot commented Nov 12, 2026

Copy link
Copy Markdown
Contributor

CMS-2685

@riasvdv
riasvdv requested a review from brianjhanson November 12, 2026 21:52
@github-actions

Copy link
Copy Markdown

📚 Storybook previews

@craftcms/ui — open Storybook

No changed components detected in this Storybook.

resources/js — open Storybook

No changed components detected in this Storybook.

@riasvdv
riasvdv merged commit e7cdc90 into 6.x Nov 12, 2026
22 checks passed
@riasvdv
riasvdv deleted the rias/cms-2685-6x-each-draft-autosave-blocks-the-entry-editor branch November 12, 2026 22:05
riasvdv added a commit that referenced this pull request Nov 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants