fix(editor): repair block identity for template pages (duplicate/reordered lines)
Template-created pages (weekly report, project doc, meeting notes, to-do list, ...) were persisted without block ids. The editor assigned ids client-side, but the realtime room loaded the raw id-less content and sent it back on 'sync'; applySync then merged id-less server blocks with local blocks, producing data-bid='undefined' collisions and duplicated/shuffled lines as soon as the user edited. Editing an empty page was unaffected because the server state was empty. Fixes: - board.use_page_template: materialize unique block ids (recursively) when instantiating built-in or user templates. - realtime_server: unique block_id() (uuid) + ensure_block_ids() on room load and on insert ops. - editor: recursive ensureBlockIds() in init; gtTok() now restores [[fddate:...]] tokens (date chips survived as labels before). - realtime client: applySync() normalizes ids, no longer appends unknown local blocks (duplication), and keeps local content when server is empty. Tests: pytest (templates + realtime) and Playwright e2e covering to-do list, weekly report date chip, Enter ordering and legacy id-less repair.
This commit is contained in:
@@ -283,6 +283,23 @@ def test_use_builtin_template_creates_page(client):
|
||||
cookies={"flowdeck_session": s}, headers={"X-CSRF-Token": c}).status_code == 404
|
||||
|
||||
|
||||
def test_use_builtin_template_assigns_block_ids(client):
|
||||
"""Template blocks must be persisted with unique ids (v5.13.1).
|
||||
|
||||
Without ids the realtime room and the editor disagree on block identity,
|
||||
which duplicated/shuffled lines when editing a template page.
|
||||
"""
|
||||
s, c, uid = _login(client)
|
||||
r = client.post("/board/api/page-templates/0/use", json={"key": "weekly_report"},
|
||||
cookies={"flowdeck_session": s}, headers={"X-CSRF-Token": c})
|
||||
assert r.status_code == 200
|
||||
page = client.get(f"/board/api/pages/{r.json()['id']}").json()
|
||||
blocks = json.loads(page["content"])
|
||||
ids = [b.get("id") for b in blocks]
|
||||
assert all(ids), f"missing ids: {ids}"
|
||||
assert len(set(ids)) == len(ids), f"duplicate ids: {ids}"
|
||||
|
||||
|
||||
def test_use_template_persists_workspace_id(client):
|
||||
s, c, uid = _login(client)
|
||||
# Create a local workspace owned by this user
|
||||
|
||||
Reference in New Issue
Block a user